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.
		
		
		
		
			
				
					1280 lines
				
				48 KiB
			
		
		
			
		
	
	
					1280 lines
				
				48 KiB
			| 
											2 years ago
										 | /* Licensed under the Apache License, Version 2.0 (the "License"); | ||
|  |  * you may not use this file except in compliance with the License. | ||
|  |  * You may obtain a copy of the License at | ||
|  |  * | ||
|  |  *      http://www.apache.org/licenses/LICENSE-2.0
 | ||
|  |  * | ||
|  |  * Unless required by applicable law or agreed to in writing, software | ||
|  |  * distributed under the License is distributed on an "AS IS" BASIS, | ||
|  |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
|  |  * See the License for the specific language governing permissions and | ||
|  |  * limitations under the License. | ||
|  |  */ | ||
|  | flowableModule | ||
|  |   .directive('restrictInput', ["$parse", function ($parse) { | ||
|  |     return { | ||
|  |       restrict: 'A', | ||
|  |       require: 'ngModel', | ||
|  |       priority: 1002, | ||
|  | 
 | ||
|  |       link: function postLink(scope, elm, attrs, ctrl) { | ||
|  | 
 | ||
|  |         var acceptedFormat = attrs["restrictInput"]; | ||
|  |         if (acceptedFormat == undefined || acceptedFormat == null || acceptedFormat == "") { | ||
|  |            acceptedFormat = attrs["dateFormat"]; | ||
|  |         } | ||
|  | 
 | ||
|  |         scope.field.acceptedFormat=acceptedFormat; | ||
|  | 
 | ||
|  |         function calculateAcceptedFormats(format) { | ||
|  |           var format1 = format.toUpperCase(); //d-m-yyyy
 | ||
|  |           var format2 = format1.replace(/-D-/,"-DD-").replace(/^D-/,"DD-").replace(/-D$/,"-DD"); //dd-m-yyyy
 | ||
|  |           var format3 = format1.replace(/-M-/,"-MM-").replace(/^M-/,"MM-").replace(/-M$/,"-MM");  //d-mm-yyyy
 | ||
|  |           var format4 = format2.replace(/-M-/,"-MM-").replace(/^M-/,"MM-").replace(/-M$/,"-MM");  //dd-mm-yyyy
 | ||
|  |           return [format1,format2,format3,format4]; | ||
|  |         } | ||
|  | 
 | ||
|  |         var acceptedFormats = calculateAcceptedFormats(acceptedFormat); | ||
|  |         var skipValidation = false; | ||
|  | 
 | ||
|  |         if (acceptedFormat == undefined || acceptedFormat == null || acceptedFormat == "") { | ||
|  |           skipValidation = true; | ||
|  |         } | ||
|  |         var oldRenderer = ctrl.$render; | ||
|  | 
 | ||
|  |         ctrl.$render = function () { | ||
|  |           elm.val(ctrl.$viewValue); | ||
|  |           if (ctrl.$dateValue && !isNaN(ctrl.$dateValue.getTime())) { | ||
|  |             if (oldRenderer) { | ||
|  |               oldRenderer(); | ||
|  |             } | ||
|  |           } | ||
|  |         }; | ||
|  | 
 | ||
|  |         function isValidText(viewValue, format) { | ||
|  |           if (viewValue === undefined || viewValue == null || viewValue ==='') return true; | ||
|  |           if (viewValue.length > format.length) return false; | ||
|  | 
 | ||
|  |            for (var i = 0; i < Math.min(format.length, viewValue.length); i++) { | ||
|  |              var charType = format[i]; | ||
|  |              if (charType.toUpperCase().match(/D|M|Y/)) { | ||
|  |                if (viewValue[i].match(/\d/) == null) return false; | ||
|  |              }else { | ||
|  |                if (viewValue[i] != charType) return false; | ||
|  |              } | ||
|  |            } | ||
|  |            return true; | ||
|  |          } | ||
|  | 
 | ||
|  |         ctrl.$parsers.unshift(function (viewValue) { | ||
|  | 
 | ||
|  |           if (skipValidation) return viewValue; //just skip this parser
 | ||
|  | 
 | ||
|  |           var isValid = false; | ||
|  |           for(var i =0 ; i < acceptedFormats.length && !isValid; i++){ | ||
|  |             isValid |= isValidText(viewValue,acceptedFormats[i]); | ||
|  |           } | ||
|  | 
 | ||
|  |           if (!isValid) { | ||
|  |             //should restore to the latest known well formated date.
 | ||
|  |             ctrl.$dateValue = null; | ||
|  |           } else { | ||
|  |             ctrl.$lastValidText = viewValue; | ||
|  | 
 | ||
|  |               //by default the date picker in angular strap does not reset the dateValue if the viewValue is null or empty.
 | ||
|  |               if (viewValue === undefined || viewValue == null || viewValue === '') { | ||
|  |                   ctrl.$dateValue = null; | ||
|  |               } | ||
|  | 
 | ||
|  |             return viewValue; | ||
|  |           } | ||
|  | 
 | ||
|  |           ctrl.$setViewValue(ctrl.$lastValidText); | ||
|  |           ctrl.$render(); | ||
|  |           return ctrl.$lastValidText; | ||
|  |         }); | ||
|  | 
 | ||
|  |       } | ||
|  |     } | ||
|  |   } | ||
|  |   ]); | ||
|  | 
 | ||
|  | 
 | ||
|  | flowableModule | ||
|  |     .directive('autoHeight', ['$rootScope', '$timeout', function($rootScope, $timeout) { | ||
|  |         return { | ||
|  |             restrict: 'AC', | ||
|  |             scope: { | ||
|  |               'toWatch': '=autoHeight' | ||
|  |             }, | ||
|  |             compile: function (element, attr) { | ||
|  |                 return function ($scope, $element, $attrs) { | ||
|  |                     var offset = 0; | ||
|  |                     if($attrs['offset']) { | ||
|  |                         offset = parseInt($attrs['offset']); | ||
|  |                         if(isNaN(offset) || offset == undefined) { | ||
|  |                             offset = 0; | ||
|  |                         } | ||
|  |                     } | ||
|  | 
 | ||
|  |                     var update = function($element) { | ||
|  |                         // Get hold of parent and iterate all the children to get available height
 | ||
|  | 
 | ||
|  |                         $timeout(function() { | ||
|  |                             var total = $element.parent().outerHeight() - offset; | ||
|  |                             var found = false; | ||
|  |                             $element.parent().children().each(function() { | ||
|  |                                 if(!found) { | ||
|  |                                     if($element[0] == this) { | ||
|  |                                         found = true; | ||
|  |                                     } else { | ||
|  |                                         // Substract preceding child's height
 | ||
|  |                                         total -= angular.element(this).outerHeight(); | ||
|  |                                     } | ||
|  |                                 } | ||
|  |                             }); | ||
|  | 
 | ||
|  |                             if(found) { | ||
|  |                                 $element.height(total); | ||
|  |                             } | ||
|  |                         }, 0); | ||
|  |                     }; | ||
|  | 
 | ||
|  |                     if($scope.unregisterWatcher) { | ||
|  |                         $scope.unregisterWatcher(); | ||
|  |                     } | ||
|  |                     $scope.unregisterWatcher = $rootScope.$watch('window.height', function(windowHeight) { | ||
|  |                         update($element); | ||
|  |                     }); | ||
|  | 
 | ||
|  |                     if($scope.unregisterForceWatcher) { | ||
|  |                         $scope.unregisterForceWatcher(); | ||
|  |                     } | ||
|  |                     $scope.unregisterForceWatcher = $rootScope.$watch('window.forceRefresh', function(forceValue) { | ||
|  |                         update($element); | ||
|  |                     }); | ||
|  | 
 | ||
|  | 
 | ||
|  |                     $scope.$on('$destroy', function() { | ||
|  |                         // Cleanup watcher for window-height
 | ||
|  |                         if($scope.unregisterWatcher) { | ||
|  |                             $scope.unregisterWatcher(); | ||
|  |                         } | ||
|  |                         if($scope.unregisterForceWatcher) { | ||
|  |                             $scope.unregisterForceWatcher(); | ||
|  |                         } | ||
|  |                     }); | ||
|  |                 } | ||
|  |             } | ||
|  |         }; | ||
|  |     }]); | ||
|  | 
 | ||
|  | /** | ||
|  |  * Directive that ensures the child-element with class .active is visible and scrolls if needed. Watches the value | ||
|  |  * of the directive and will re-apply if this value is changes. | ||
|  |  */ | ||
|  | flowableModule | ||
|  |     .directive('scrollToActive', ['$timeout', function($timeout) { | ||
|  |         return { | ||
|  |             restrict: 'AC', | ||
|  |             scope: { | ||
|  |                 toWatch: "=scrollToActiveModel" | ||
|  |             }, | ||
|  |             compile: function (element, attr) { | ||
|  |                 return function ($scope, $element, $attrs) { | ||
|  |                     $scope.$watch('toWatch', function() { | ||
|  |                         $timeout(function() { | ||
|  |                             var useParent = $attrs['useParent']; | ||
|  |                             var offsetTop = $attrs['offsetTop']; | ||
|  |                             if(offsetTop) { | ||
|  |                                 offsetTop = parseInt(offsetTop); | ||
|  |                                 if(isNaN(offsetTop)) { | ||
|  |                                     offsetTop = 0; | ||
|  |                                 } | ||
|  |                             } | ||
|  |                             if (!offsetTop) { | ||
|  |                                 offsetTop = 0; | ||
|  |                             } | ||
|  | 
 | ||
|  |                             var selectedArr = $element.children('.active'); | ||
|  |                             if(selectedArr && selectedArr.length > 0) { | ||
|  |                                 var selected = angular.element(selectedArr[0]); | ||
|  | 
 | ||
|  |                                 if(useParent) { | ||
|  |                                     $element = angular.element($element.parent()); | ||
|  |                                 } | ||
|  |                                 var selectedTop = selected.position().top - $element.position().top + $element.scrollTop(); | ||
|  |                                 var selectedBottom = selectedTop + selected.outerHeight(); | ||
|  |                                 var elementBottom = $element.scrollTop() + $element.innerHeight(); | ||
|  |                                 var elementTop = elementBottom - $element.innerHeight(); | ||
|  | 
 | ||
|  |                                 if(selectedTop <= elementTop) { | ||
|  |                                     // scroll up
 | ||
|  |                                     $element.scrollTop(selectedTop - selected.outerHeight() - offsetTop); | ||
|  |                                 } else if(selectedBottom > elementBottom) { | ||
|  |                                     // scroll down
 | ||
|  |                                     $element.scrollTop(elementTop + selected.outerHeight() - offsetTop); | ||
|  |                                 } | ||
|  |                             } | ||
|  |                         }, 0); | ||
|  |                     }); | ||
|  |                 } | ||
|  |             } | ||
|  |         }; | ||
|  |     }]); | ||
|  | 
 | ||
|  | /** | ||
|  |  * Directive that ensures the popup is scrolled into view, using the first parent as scroll-pane that has | ||
|  |  * a class 'scroll-container' set on it. Is applied when the popup is shown. | ||
|  |  */ | ||
|  | flowableModule | ||
|  |     .directive('autoScroll', ['$timeout', function($timeout) { | ||
|  |         return { | ||
|  |             restrict: 'AC', | ||
|  |             compile: function (element, attr) { | ||
|  |                 return function ($scope, $element, $attrs) { | ||
|  |                     $scope.$on('tooltip.show', function() { | ||
|  |                         $timeout(function() { | ||
|  |                             // Find appropriate parent
 | ||
|  |                             var parent = $element[0]; | ||
|  |                             while(parent) { | ||
|  |                                 if(parent.className && parent.className.indexOf('scroll-container') >= 0) { | ||
|  |                                     break; | ||
|  |                                 } | ||
|  |                                 parent = parent.parentNode; | ||
|  |                             } | ||
|  | 
 | ||
|  |                             if(parent) { | ||
|  |                                 parent = angular.element(parent); | ||
|  |                                 var selectedTop = $element.offset().top  - parent.offset().top + $element.scrollTop(); | ||
|  |                                 var selectedBottom = selectedTop + $element.outerHeight(); | ||
|  | 
 | ||
|  |                                 if(selectedBottom + 30 >= parent.outerHeight()) { | ||
|  |                                     parent.scrollTop(selectedTop); | ||
|  |                                 } | ||
|  |                             } | ||
|  |                         }, 50); | ||
|  |                     }); | ||
|  |                 } | ||
|  |             } | ||
|  |         }; | ||
|  |     }]); | ||
|  | 
 | ||
|  | flowableModule | ||
|  |     .directive('userName', function() { | ||
|  |         var directive = {}; | ||
|  |         directive.template = '{{user.firstName && user.firstName || ""}} {{user.lastName && user.lastName || ""}} {{ (user.email && !user.firstName && !user.lastName) && user.email || ""}}'; | ||
|  |         directive.scope = { | ||
|  |             user: "=userName" | ||
|  |         }; | ||
|  |         return directive; | ||
|  |     }); | ||
|  | 
 | ||
|  | 
 | ||
|  | /** | ||
|  |  * Executes the method that is set on the directive attribute value when ANY OTHER element is clicked, which is not the element the | ||
|  |  * directive is on, or any of it's children. | ||
|  |  * | ||
|  |  */ | ||
|  | flowableModule | ||
|  |     .directive('clickAnywhere', ["$document", "$parse", function ($document, $parse) { | ||
|  | 
 | ||
|  |         var linkFunction = function ($scope, $element, $attributes) { | ||
|  | 
 | ||
|  |             var scopeExpression = $attributes.clickAnywhere; | ||
|  |             var invoker = $parse(scopeExpression); | ||
|  | 
 | ||
|  |             var ignoreId = $attributes.ignore; | ||
|  |             var ignoreClass = $attributes.ignoreClass; | ||
|  |             var ignorePopupEvents = $attributes.ignorePopupEvents == 'true'; | ||
|  | 
 | ||
|  |             var handler = function (event) { | ||
|  |                 // Check source of event
 | ||
|  |                 var parent = event.target; | ||
|  |                 while(parent) { | ||
|  |                     if(parent == $element[0] || | ||
|  |                         (ignoreId && parent.id == ignoreId) || | ||
|  |                         (ignoreClass && parent.className && parent.className.indexOf(ignoreClass) >= 0)) { | ||
|  | 
 | ||
|  |                         event.stopPropagation(); | ||
|  |                         event.preventDefault(); | ||
|  |                         return; | ||
|  |                     } | ||
|  |                     parent = parent.parentNode; | ||
|  |                 } | ||
|  | 
 | ||
|  |                 $scope.$apply( | ||
|  |                     function () { | ||
|  |                         invoker($scope, {$event: event}); | ||
|  |                     } | ||
|  |                 ); | ||
|  |             }; | ||
|  | 
 | ||
|  |             $document.on("click", handler); | ||
|  | 
 | ||
|  |             $scope.$on('$destroy', function () { | ||
|  |                 $document.off("click", handler); | ||
|  |             }); | ||
|  | 
 | ||
|  |             // Special handling for tooltips which don't destroy the scope
 | ||
|  |             var hideReg = $scope.$on('tooltip.hide', function () { | ||
|  |                 if(!ignorePopupEvents) { | ||
|  |                     $document.off("click", handler); | ||
|  |                     hideReg(); | ||
|  |                 } | ||
|  |             }); | ||
|  | 
 | ||
|  |         }; | ||
|  | 
 | ||
|  |         // Return the linking function.
 | ||
|  |         return( linkFunction ); | ||
|  |     } | ||
|  |     ]); | ||
|  | 
 | ||
|  | 
 | ||
|  | 
 | ||
|  | 
 | ||
|  | flowableModule | ||
|  |     .directive('autoFocus', ['$timeout', '$parse', function($timeout, $parse) { | ||
|  |         return { | ||
|  |             restrict: 'AC', | ||
|  |             compile: function($element, attr) { | ||
|  |                 var selectText; | ||
|  | 
 | ||
|  |                 if(attr["selectText"]) { | ||
|  |                     selectText = $parse(attr["selectText"]); | ||
|  |                 } | ||
|  | 
 | ||
|  |                 return function(_scope, _element, _attrs) { | ||
|  |                     var firstChild = (_attrs.focusFirstChild !== undefined); | ||
|  |                     $timeout(function () { | ||
|  |                         if (firstChild) { | ||
|  |                             // look for first input-element in child-tree and focus that
 | ||
|  |                             var inputs = _element.find('input'); | ||
|  |                             if (inputs && inputs.length > 0) { | ||
|  |                                 inputs[0].focus(); | ||
|  | 
 | ||
|  |                                 if(selectText && selectText(_scope.$parent)) { | ||
|  |                                     input[0].setSelectionRange(0,input[0].value.length); | ||
|  |                                 } | ||
|  |                             } | ||
|  |                         } else { | ||
|  |                             // Focus element where the directive is put on
 | ||
|  |                             _element[0].focus(); | ||
|  |                             if(selectText && selectText(_scope.$parent)) { | ||
|  |                                 _element[0].setSelectionRange(0,_element[0].value.length); | ||
|  |                             } | ||
|  |                         } | ||
|  |                     }, 100); | ||
|  |                 } | ||
|  |             } | ||
|  |         }; | ||
|  |     }]); | ||
|  | 
 | ||
|  | flowableModule | ||
|  |     .directive('focusWhen', ['$timeout', function ($timeout) { | ||
|  |         return { | ||
|  |             link: function (scope, element, attrs) { | ||
|  |                 scope.$watch(attrs.ngFocus, function (val) { | ||
|  |                     if (angular.isDefined(val) && val) { | ||
|  |                         $timeout(function () { | ||
|  |                             element[0].focus(); | ||
|  |                         }); | ||
|  |                     } | ||
|  |                 }, true); | ||
|  | 
 | ||
|  |                 element.bind('blur', function () { | ||
|  |                     if (angular.isDefined(attrs.ngFocusLost)) { | ||
|  |                         scope.safeApply(attrs.ngFocusLost); | ||
|  |                     } | ||
|  |                 }); | ||
|  |             } | ||
|  |         }; | ||
|  |     }]); | ||
|  | 
 | ||
|  | 
 | ||
|  | flowableModule | ||
|  |     .directive('loading', [function() { | ||
|  |         var directive = {}; | ||
|  |         directive.restrict = 'A'; | ||
|  |         directive.template = '<div class="loading" ng-show="loading"><div class="l1"></div><div class="l2"></div><div class="l3"></div></div>'; | ||
|  |         directive.scope = { | ||
|  |             loading : "=loading", | ||
|  |             loadingText: "=loadingText" | ||
|  |         }; | ||
|  |         return directive; | ||
|  |     }]); | ||
|  | 
 | ||
|  | // Workaround for https://github.com/twbs/bootstrap/issues/8379 :
 | ||
|  | // prototype.js interferes with regular dropdown behavior
 | ||
|  | flowableModule | ||
|  |     .directive('activitiFixDropdownBug', function() { | ||
|  |         return { | ||
|  |             restrict: 'AEC', | ||
|  |             link: function(scope, element, attrs) { | ||
|  |                 element.on('hidden.bs.dropdown	', function () { | ||
|  |                     element.show(); // evil prototype.js has added display:none to it ...
 | ||
|  |                 }) | ||
|  |             } | ||
|  |         }; | ||
|  |     }); | ||
|  | 
 | ||
|  | /** | ||
|  |  * Directive for rendering user link. | ||
|  |  */ | ||
|  | flowableModule | ||
|  |   .directive('userLink', function() { | ||
|  |     var directive = {}; | ||
|  |     directive.template = '{{user.firstName && user.firstName || ""}} {{user.lastName && user.lastName || ""}} {{ (user.email && !user.firstName && !user.lastName) && user.email || ""}}'; | ||
|  |     directive.scope = { | ||
|  |         user: "=userLink" | ||
|  |     }; | ||
|  | 
 | ||
|  |     directive.compile = function(element, attributes) { | ||
|  |         element.addClass('people-link'); | ||
|  |     }; | ||
|  | 
 | ||
|  |     return directive; | ||
|  | }); | ||
|  | 
 | ||
|  | /** | ||
|  |  * Directive for rendering a form field. | ||
|  |  */ | ||
|  | flowableModule | ||
|  |     .directive('formField', function () { | ||
|  |         var directive = {}; | ||
|  | 
 | ||
|  |         directive.template = ' {{field.name || ""}} - {{field.id}}'; | ||
|  |         directive.scope = { | ||
|  |             field: "=formField" | ||
|  |         }; | ||
|  | 
 | ||
|  |         directive.compile = function (element, attributes) { | ||
|  |             element.addClass('form-field'); | ||
|  |         }; | ||
|  |         return directive; | ||
|  |     }); | ||
|  | /** | ||
|  |  * Directive to capture mouse up, down, enter and escape on input fields (eg. list navigation) | ||
|  |  */ | ||
|  | flowableModule | ||
|  |     .directive('customKeys', ["$parse", function ($parse) { | ||
|  |         var directive = {}; | ||
|  |         directive.compile = function($element, attr) { | ||
|  |             var up, down, enter, escape; | ||
|  | 
 | ||
|  |             if(attr["upPressed"]) { | ||
|  |                 up = $parse(attr["upPressed"]); | ||
|  |             } | ||
|  |             if(attr["downPressed"]) { | ||
|  |                 down = $parse(attr["downPressed"]); | ||
|  |             } | ||
|  |             if(attr["enterPressed"]) { | ||
|  |                 enter = $parse(attr["enterPressed"]); | ||
|  |             } | ||
|  | 
 | ||
|  |             if(attr["escapePressed"]) { | ||
|  |                 escape = $parse(attr["escapePressed"]); | ||
|  |             } | ||
|  | 
 | ||
|  |             return function(scope, element, attr) { | ||
|  |                 element.on('keyup', function(e) { | ||
|  |                     if(e.keyCode === 38) { | ||
|  |                         scope.$apply(function() { | ||
|  |                             if(up) { | ||
|  |                                 up(scope, {$event:e}); | ||
|  |                             } | ||
|  |                         }); | ||
|  |                     } else if(e.keyCode === 40) { | ||
|  |                         scope.$apply(function() { | ||
|  |                             if(down) { | ||
|  |                                 down(scope, {$event:e}); | ||
|  |                             } | ||
|  |                         }); | ||
|  |                     } else if(e.keyCode === 13) { | ||
|  |                         scope.$apply(function() { | ||
|  |                             if(enter) { | ||
|  |                                 enter(scope, {$event:e}); | ||
|  |                             } | ||
|  |                         }); | ||
|  |                     } else if(e.keyCode === 27) { | ||
|  |                     scope.$apply(function() { | ||
|  |                         if(escape) { | ||
|  |                             escape(scope, {$event:e}); | ||
|  |                         } | ||
|  |                     }); | ||
|  |                 } | ||
|  |                 }); | ||
|  | 
 | ||
|  |                 element.on('keydown', element, function (e) { | ||
|  |                     if (e.keyCode === 38 || e.keyCode === 40 || e.keyCode === 13 || e.keyCode === 27) | ||
|  |                         e.preventDefault(); | ||
|  |                 }); | ||
|  |             }; | ||
|  |     }; | ||
|  |     return directive; | ||
|  | }]); | ||
|  | 
 | ||
|  | // Delayed setting of model value in scope, based on input value unchanged after a number of millis
 | ||
|  | // See below: ngDebounce is preferred (as it hooks into ngModel, meaning that ng-change will keep working - but not with delayedModel)
 | ||
|  | flowableModule | ||
|  |     .directive('delayedModel', ['$timeout', function($timeout) { | ||
|  |     return { | ||
|  |         scope: { | ||
|  |             targetModel: '=delayedModel' | ||
|  |         }, | ||
|  |         link: function(scope, element, attrs) { | ||
|  | 
 | ||
|  |             element.val(scope.targetModel); | ||
|  | 
 | ||
|  |             // Also watch model for any changes not triggered by timer
 | ||
|  |             scope.$watch('targetModel', function(newVal, oldVal) { | ||
|  |                 if(scheduled) { | ||
|  |                     $timeout.cancel(scheduled); | ||
|  |                 } | ||
|  |                 if (newVal !== oldVal) { | ||
|  |                     element.val(scope.targetModel); | ||
|  |                 } | ||
|  |             }); | ||
|  | 
 | ||
|  |             var scheduled; | ||
|  |             element.on('keyup paste search', function() { | ||
|  |                 if(element.val() !== scope.targetModel) { | ||
|  |                     if(scheduled) { | ||
|  |                         $timeout.cancel(scheduled); | ||
|  |                     } | ||
|  |                     scheduled = $timeout(function() { | ||
|  |                         scope.targetModel = element[0].value; | ||
|  |                         element.val(scope.targetModel); | ||
|  |                         scope.$apply(); | ||
|  |                     }, attrs.delay || 200); | ||
|  |                 } | ||
|  |             }); | ||
|  |         } | ||
|  |     }; | ||
|  | }]); | ||
|  | 
 | ||
|  | 
 | ||
|  | // From https://gist.github.com/benbrandt22/bb44184a2eddcd4b0b8a
 | ||
|  | flowableModule.directive('ngDebounce', ['$timeout', function($timeout) { | ||
|  |     return { | ||
|  |         restrict: 'A', | ||
|  |         require: 'ngModel', | ||
|  |         priority: 99, | ||
|  |         link: function(scope, elm, attr, ngModelCtrl) { | ||
|  |             if (attr.type === 'radio' || attr.type === 'checkbox') return; | ||
|  | 
 | ||
|  |             elm.unbind('input'); | ||
|  | 
 | ||
|  |             var debounce; | ||
|  |             elm.bind('input', function() { | ||
|  |                 $timeout.cancel(debounce); | ||
|  |                 debounce = $timeout( function() { | ||
|  |                     scope.$apply(function() { | ||
|  |                         ngModelCtrl.$setViewValue(elm.val()); | ||
|  |                     }); | ||
|  |                 }, attr.ngDebounce || 1000); | ||
|  |             }); | ||
|  |             elm.bind('blur', function() { | ||
|  |                 scope.$apply(function() { | ||
|  |                     ngModelCtrl.$setViewValue(elm.val()); | ||
|  |                 }); | ||
|  |             }); | ||
|  |         } | ||
|  | 
 | ||
|  |     } | ||
|  | }]); | ||
|  | 
 | ||
|  | flowableModule. | ||
|  |     directive('selectPeoplePopover', ['$rootScope', '$http', '$popover', 'UserService', '$parse', function($rootScope, $http, $popover, UserService, $parse) { | ||
|  |         var directive = {}; | ||
|  |         directive.restrict = 'A'; | ||
|  | 
 | ||
|  |         directive.scope = { | ||
|  |             excludeTaskId: '=excludeTaskId', | ||
|  |             excludeProcessId: '=excludeProcessId', | ||
|  |             excludeUserId: '=excludeUserId', | ||
|  |             excludeUserIds: '=excludeUserIds', | ||
|  |             tenantId: '=tenantId', | ||
|  |             type: '=type', | ||
|  |             restrictWithGroup: '=restrictWithGroup', | ||
|  |             selectPeopleFormFields: '=selectPeopleFormFields', | ||
|  |             ignoreContainer: '=ignoreContainer' | ||
|  |         }; | ||
|  | 
 | ||
|  |         directive.link = function($scope, $element, attrs) { | ||
|  |             // Set defaults
 | ||
|  |             var placement = "bottom"; | ||
|  | 
 | ||
|  |             $element.addClass("toggle-people-select"); | ||
|  | 
 | ||
|  |             if(attrs.placement) { | ||
|  |                 placement = attrs.placement; | ||
|  |             } | ||
|  | 
 | ||
|  |             var closeOnSelect = true; | ||
|  |             if(attrs.closeOnSelect !== undefined) { | ||
|  |                 closeOnSelect = attrs.closeOnSelect; | ||
|  |             } | ||
|  | 
 | ||
|  |             if ($scope.ignoreContainer) { | ||
|  |                 $scope.popover = $popover($element, {template: 'views/common/popover/select-people-popover.html?'  + | ||
|  |                     Date.now(), placement: placement}); | ||
|  | 
 | ||
|  |             } else { | ||
|  |                 $scope.popover = $popover($element, {template: 'views/common/popover/select-people-popover.html?'  + | ||
|  |                     Date.now(), placement: placement, container: 'body'}); | ||
|  |             } | ||
|  | 
 | ||
|  |             // Parse callbacks
 | ||
|  |             var selectedCallback, cancelledCallback, emailSelectedCallback; | ||
|  |             if (attrs['onPeopleSelected']) { | ||
|  |                 selectedCallback = $parse(attrs['onPeopleSelected']); | ||
|  |             } | ||
|  |             if (attrs['onCancel']) { | ||
|  |                 cancelledCallback = $parse(attrs['onCancel']); | ||
|  |             } | ||
|  |             if (attrs['onEmailSelected']) { | ||
|  |                 emailSelectedCallback = $parse(attrs['onEmailSelected']); | ||
|  |             } | ||
|  | 
 | ||
|  |             // Parse type
 | ||
|  |             // Can be 'workflow' or 'idm'. In 'workflow', the users are retrieved for filling task assignments etc. This is the default if this param is omitted. 'idm' is more strict.
 | ||
|  |             var backendType = 'workflow'; | ||
|  |             if ($scope.type !== null && $scope.type !== undefined) { | ||
|  |                 backendType = $scope.type; | ||
|  |             } | ||
|  | 
 | ||
|  |             var popoverScope = $scope.popover.$scope; | ||
|  |             popoverScope.title = attrs['popoverTitle']; | ||
|  | 
 | ||
|  |             popoverScope.popupModel = { | ||
|  |                 emailMode: false, | ||
|  |                 showRecentResults: false, // Disabled recent for the moment. Put this on true to set it back
 | ||
|  |                 userResults: [], | ||
|  |                 userField: {}, | ||
|  |                 userFieldFilter: ['people'] | ||
|  |             }; | ||
|  |              | ||
|  |             if ($scope.selectPeopleFormFields) { | ||
|  |                 popoverScope.popupModel.formFields = $scope.selectPeopleFormFields; | ||
|  |             } | ||
|  | 
 | ||
|  |             if (attrs['emailModeDisabled']) { | ||
|  |                 var emailModeDisabledValue = attrs['emailModeDisabled']; | ||
|  |                 if (emailModeDisabledValue === 'true') { | ||
|  |                     popoverScope.popupModel.emailDisabled = true; | ||
|  |                 } | ||
|  |             } | ||
|  | 
 | ||
|  |             popoverScope.popupModel.emailMode = false; | ||
|  | 
 | ||
|  | 
 | ||
|  |             popoverScope.setSearchType = function() { | ||
|  |                 popoverScope.popupModel.userSourceType = 'search'; | ||
|  |             }; | ||
|  |              | ||
|  |             popoverScope.setFormFieldType = function() { | ||
|  |                 popoverScope.popupModel.userSourceType = 'field'; | ||
|  |             }; | ||
|  |              | ||
|  |             popoverScope.$watch('popupModel.userField', function() { | ||
|  |                 if (popoverScope.popupModel.userField && popoverScope.popupModel.userField.id) { | ||
|  |                     if (selectedCallback) { | ||
|  |                         // Run callback in parent scope of directive
 | ||
|  |                         var simpleUserField = { | ||
|  |                                 id: popoverScope.popupModel.userField.id,  | ||
|  |                                 name: popoverScope.popupModel.userField.name, | ||
|  |                                 type: popoverScope.popupModel.userField.type | ||
|  |                         } | ||
|  |         | ||
|  |                         selectedCallback($scope.$parent, {'userField': simpleUserField}); | ||
|  |                         popoverScope.popupModel.userField = {}; | ||
|  |                     } | ||
|  |                      | ||
|  |                     if (closeOnSelect || closeOnSelect === 'true') { | ||
|  |                         popoverScope.$hide(); | ||
|  |                     } | ||
|  |                 }            | ||
|  |             }); | ||
|  | 
 | ||
|  |             popoverScope.$watch('popupModel.filter', function() { | ||
|  |                 if (popoverScope.popupModel.filter && popoverScope.popupModel.filter.length > 0) { | ||
|  | 
 | ||
|  |                     var userGetPromise; | ||
|  |                     if (backendType === 'idm') { | ||
|  |                         userGetPromise = UserService.getFilteredUsersStrict(popoverScope.popupModel.filter, $scope.tenantId, $scope.restrictWithGroup); | ||
|  |                     } else { | ||
|  |                         // Default: go to workflow users backend
 | ||
|  |                         userGetPromise = UserService.getFilteredUsers(popoverScope.popupModel.filter, $scope.excludeTaskId, | ||
|  |                                 $scope.excludeProcessId, $scope.tenantId, $scope.restrictWithGroup); | ||
|  |                     } | ||
|  | 
 | ||
|  |                     userGetPromise.then(function(result) { | ||
|  |                         popoverScope.popupModel.showRecentResults =  false; | ||
|  | 
 | ||
|  |                         var users = []; | ||
|  |                         var excludeUserIdSet = $scope.excludeUserId !== null && $scope.excludeUserId !== undefined; | ||
|  |                         var excludeUserIdsSet = $scope.excludeUserIds !== null && $scope.excludeUserIds !== undefined; | ||
|  |                         if (excludeUserIdSet === true || excludeUserIdsSet === true) { | ||
|  |                             for (var userIndex=0; userIndex < result.data.length; userIndex++) { | ||
|  | 
 | ||
|  |                                 var userExcluded = false; | ||
|  |                                 if (excludeUserIdSet === true && result.data[userIndex].id === $scope.excludeUserId) { | ||
|  |                                     userExcluded = true; | ||
|  |                                 } | ||
|  |                                 if (excludeUserIdsSet === true && $scope.excludeUserIds.indexOf(result.data[userIndex].id) >= 0) { | ||
|  |                                     userExcluded = true; | ||
|  |                                 } | ||
|  | 
 | ||
|  |                                 if (!userExcluded) { | ||
|  |                                     users.push(result.data[userIndex]); | ||
|  |                                 } | ||
|  | 
 | ||
|  |                             } | ||
|  |                         } else { | ||
|  |                             users = result.data; | ||
|  |                         } | ||
|  |                         popoverScope.popupModel.userResults = users; | ||
|  |                         popoverScope.resetSelection(); | ||
|  |                     }); | ||
|  |                 } else { | ||
|  |                     popoverScope.resetSelection(); | ||
|  |                     popoverScope.popupModel.userResults = []; | ||
|  |                 } | ||
|  |             }); | ||
|  | 
 | ||
|  |             popoverScope.resetSelection = function() { | ||
|  |                 popoverScope.popupModel.selectedUser = undefined; | ||
|  |                 popoverScope.popupModel.selectedIndex = -1; | ||
|  |             }; | ||
|  | 
 | ||
|  |             popoverScope.nextUser = function() { | ||
|  |                 var users = popoverScope.popupModel.userResults; | ||
|  |                 if(users && users.length > 0 && popoverScope.popupModel.selectedIndex < users.length -1) { | ||
|  |                     popoverScope.popupModel.selectedIndex+=1; | ||
|  |                     popoverScope.popupModel.selectedUser = users[popoverScope.popupModel.selectedIndex]; | ||
|  |                 } | ||
|  |             }; | ||
|  | 
 | ||
|  |             popoverScope.previousUser = function() { | ||
|  |                 var users = popoverScope.popupModel.userResults; | ||
|  |                 if(users && users.length > 0 && popoverScope.popupModel.selectedIndex > 0) { | ||
|  |                     popoverScope.popupModel.selectedIndex-=1; | ||
|  |                     popoverScope.popupModel.selectedUser = users[popoverScope.popupModel.selectedIndex]; | ||
|  |                 } | ||
|  |             }; | ||
|  | 
 | ||
|  |             popoverScope.confirmUser = function(user) { | ||
|  |                 if (!user) { | ||
|  |                     // Selection is done with keyboard, use selection index
 | ||
|  |                     var users = popoverScope.popupModel.userResults; | ||
|  |                     if (popoverScope.popupModel.selectedIndex >= 0 && popoverScope.popupModel.selectedIndex <users.length) { | ||
|  |                         user = users[popoverScope.popupModel.selectedIndex]; | ||
|  |                     } | ||
|  |                 } | ||
|  | 
 | ||
|  |                 if (user) { | ||
|  |                     if (selectedCallback) { | ||
|  |                         // Run callback in parent scope of directive
 | ||
|  |                         selectedCallback($scope.$parent, {'user': user}); | ||
|  |                     } | ||
|  | 
 | ||
|  |                     if (closeOnSelect === 'true') { | ||
|  |                         popoverScope.$hide(); | ||
|  |                     } else { | ||
|  |                         var users = popoverScope.popupModel.userResults; | ||
|  |                         users.splice(jQuery.inArray(user, users),1); | ||
|  |                         popoverScope.popupModel.selectedIndex=0; | ||
|  |                         popoverScope.popupModel.selectedUser = users[popoverScope.popupModel.selectedIndex]; | ||
|  |                     } | ||
|  |                 } | ||
|  |             }; | ||
|  | 
 | ||
|  |             popoverScope.selectPersonByEmail = function(validEmail) { // Not so nice we have to pass the valid email agrument, but couldnt make it work properly
 | ||
|  |                 if (validEmail) { | ||
|  |                     if (emailSelectedCallback) { | ||
|  |                         emailSelectedCallback($scope.$parent, {email: popoverScope.popupModel.email}); | ||
|  |                         popoverScope.$hide(); | ||
|  |                     } | ||
|  |                 } | ||
|  |             }; | ||
|  | 
 | ||
|  |             popoverScope.$on('tooltip.hide', function() { | ||
|  |                 // Invalidate recent results
 | ||
|  |                 if(popoverScope.popupModel.showRecentResults && popoverScope.popupModel.added) { | ||
|  |                     popoverScope.popupModel.recentUsers = []; | ||
|  |                 } | ||
|  |                 popoverScope.popupModel.userResults = []; | ||
|  |                 popoverScope.popupModel.filter = ''; | ||
|  |                 popoverScope.popupModel.emailMode = false; | ||
|  | 
 | ||
|  |                 if(popoverScope.popupModel.added) { | ||
|  |                     popoverScope.popupModel.added = false; | ||
|  |                 } else { | ||
|  |                     if(cancelledCallback) { | ||
|  |                         // Run callback in parent scope of directive
 | ||
|  |                         cancelledCallback($scope.$parent); | ||
|  |                     } | ||
|  |                 } | ||
|  |             }); | ||
|  | 
 | ||
|  |         }; | ||
|  |         return directive; | ||
|  |     }]); | ||
|  | 
 | ||
|  | flowableModule. | ||
|  | directive('selectFunctionalGroupPopover', ['$rootScope', '$http', '$popover', 'FunctionalGroupService', '$parse', | ||
|  |     function($rootScope, $http, $popover, FunctionalGroupService, $parse) { | ||
|  | 
 | ||
|  |     var directive = {}; | ||
|  |     directive.restrict = 'A'; | ||
|  | 
 | ||
|  |     directive.scope = { | ||
|  |         type: '=type', | ||
|  |         ignoreContainer: '=ignoreContainer', | ||
|  |         restrictWithGroup: '=restrictWithGroup', | ||
|  |         excludeGroupIds: '=excludeGroupIds' | ||
|  |     }; | ||
|  | 
 | ||
|  |     directive.link = function($scope, $element, attrs) { | ||
|  |         // Set defaults
 | ||
|  |         var placement = "bottom"; | ||
|  | 
 | ||
|  |         $element.addClass("toggle-functional-group-select"); | ||
|  | 
 | ||
|  |         if (attrs.placement) { | ||
|  |             placement = attrs.placement; | ||
|  |         } | ||
|  | 
 | ||
|  |         var closeOnSelect = true; | ||
|  |         if (attrs.closeOnSelect !== undefined) { | ||
|  |             closeOnSelect = attrs.closeOnSelect; | ||
|  |         } | ||
|  | 
 | ||
|  |         if ($scope.ignoreContainer) { | ||
|  |             $scope.popover = $popover($element, {template: 'views/common/popover/select-functional-group-popover.html?' + | ||
|  |                 Date.now(), placement: placement}); | ||
|  | 
 | ||
|  |         } else { | ||
|  |             $scope.popover = $popover($element, {template: 'views/common/popover/select-functional-group-popover.html?' + | ||
|  |                 Date.now(), placement: placement, container: 'body'}); | ||
|  |         } | ||
|  | 
 | ||
|  |         // Parse callbacks
 | ||
|  |         var selectedCallback, cancelledCallback; | ||
|  |         if (attrs['onGroupSelected']) { | ||
|  |             selectedCallback = $parse(attrs['onGroupSelected']); | ||
|  |         } | ||
|  |         if (attrs['onCancel']) { | ||
|  |             cancelledCallback = $parse(attrs['onCancel']); | ||
|  |         } | ||
|  | 
 | ||
|  |         var popoverScope = $scope.popover.$scope; | ||
|  |         popoverScope.title = attrs['popoverTitle']; | ||
|  | 
 | ||
|  |         popoverScope.popupModel = { | ||
|  |             groupResults: [] | ||
|  |         }; | ||
|  | 
 | ||
|  |         popoverScope.$watch('popupModel.filter', function() { | ||
|  |             if (popoverScope.popupModel.filter && popoverScope.popupModel.filter.length > 0) { | ||
|  | 
 | ||
|  |                 var tenantId; | ||
|  |                 if ($rootScope.common !== null && $rootScope.common !== undefined && $rootScope.common.selectedTenantId !== null && $rootScope.common.selectedTenantId !== undefined) { | ||
|  |                     tenantId = $rootScope.common.selectedTenantId > 0 ? $rootScope.common.selectedTenantId : undefined; | ||
|  |                 } | ||
|  | 
 | ||
|  |                FunctionalGroupService.getFilteredGroups(popoverScope.popupModel.filter, $scope.restrictWithGroup, tenantId).then(function(result) { | ||
|  |                     var groups = []; | ||
|  |                     if ($scope.excludeGroupId != null && $scope.excludeGroupId) { | ||
|  |                         for (var groupIndex=0; groupIndex < result.data.length; groupIndex++) { | ||
|  |                             if (result.data[groupIndex].id !== $scope.excludeGroupId) { | ||
|  |                                 groups.push(result.data[groupIndex]); | ||
|  |                             } | ||
|  |                         } | ||
|  |                     } else if ($scope.excludeGroupIds != null && $scope.excludeGroupIds !== undefined) { | ||
|  |                         for (var groupIndex=0; groupIndex < result.data.length; groupIndex++) { | ||
|  |                             if ($scope.excludeGroupIds.indexOf(result.data[groupIndex].id) < 0) { | ||
|  |                                 groups.push(result.data[groupIndex]); | ||
|  |                             } | ||
|  |                         } | ||
|  |                     } else { | ||
|  |                         groups = result.data; | ||
|  |                     } | ||
|  |                     popoverScope.popupModel.groupResults = groups; | ||
|  |                     popoverScope.resetSelection(); | ||
|  |                 }); | ||
|  |             } else { | ||
|  |                 popoverScope.resetSelection(); | ||
|  |                 popoverScope.popupModel.groupResults = []; | ||
|  |             } | ||
|  |         }); | ||
|  | 
 | ||
|  |         popoverScope.resetSelection = function() { | ||
|  |             popoverScope.popupModel.selectedGroup = undefined; | ||
|  |             popoverScope.popupModel.selectedIndex = -1; | ||
|  |         }; | ||
|  | 
 | ||
|  |         popoverScope.nextGroup = function() { | ||
|  |             var groups = popoverScope.popupModel.groupResults; | ||
|  |             if (groups && groups.length > 0 && popoverScope.popupModel.selectedIndex < groups.length -1) { | ||
|  |                 popoverScope.popupModel.selectedIndex+=1; | ||
|  |                 popoverScope.popupModel.groupUser = groups[popoverScope.popupModel.selectedIndex]; | ||
|  |             } | ||
|  |         }; | ||
|  | 
 | ||
|  |         popoverScope.previousGroup = function() { | ||
|  |             var groups = popoverScope.popupModel.groupResults; | ||
|  |             if (groups && groups.length > 0 && popoverScope.popupModel.selectedIndex > 0) { | ||
|  |                 popoverScope.popupModel.selectedIndex-=1; | ||
|  |                 popoverScope.popupModel.selectedGroup = groups[popoverScope.popupModel.selectedIndex]; | ||
|  |             } | ||
|  |         }; | ||
|  | 
 | ||
|  |         popoverScope.confirmGroup = function(group) { | ||
|  |             if (!group) { | ||
|  |                 // Selection is done with keyboard, use selection index
 | ||
|  |                 var groups = popoverScope.popupModel.groupResults; | ||
|  |                 if (popoverScope.popupModel.selectedIndex >= 0 && popoverScope.popupModel.selectedIndex < groups.length) { | ||
|  |                     group = groups[popoverScope.popupModel.selectedIndex]; | ||
|  |                 } | ||
|  |             } | ||
|  | 
 | ||
|  |             if (group) { | ||
|  |                 if(selectedCallback) { | ||
|  |                     // Run callback in parent scope of directive
 | ||
|  |                     selectedCallback($scope.$parent, {'group': group}); | ||
|  |                 } | ||
|  | 
 | ||
|  |                 if (closeOnSelect === 'true') { | ||
|  |                     popoverScope.$hide(); | ||
|  |                 } else { | ||
|  |                     var groups = popoverScope.popupModel.groupResults; | ||
|  |                     groups.splice(jQuery.inArray(group, groups), 1); | ||
|  |                     popoverScope.popupModel.selectedIndex = 0; | ||
|  |                     popoverScope.popupModel.selectedGroup = groups[popoverScope.popupModel.selectedIndex]; | ||
|  |                 } | ||
|  |             } | ||
|  |         }; | ||
|  | 
 | ||
|  |         popoverScope.$on('tooltip.hide', function() { | ||
|  |             popoverScope.popupModel.groupResults = []; | ||
|  |             popoverScope.popupModel.filter = ''; | ||
|  | 
 | ||
|  |             if (popoverScope.popupModel.added) { | ||
|  |                 popoverScope.popupModel.added = false; | ||
|  |             } else { | ||
|  |                 if (cancelledCallback) { | ||
|  |                     // Run callback in parent scope of directive
 | ||
|  |                     cancelledCallback($scope.$parent); | ||
|  |                 } | ||
|  |             } | ||
|  |         }); | ||
|  | 
 | ||
|  |     }; | ||
|  |     return directive; | ||
|  | }]); | ||
|  | 
 | ||
|  | flowableModule.directive('tabControl', ['$compile', '$http', '$templateCache', function($compile, $http, $templateCache) { | ||
|  | 
 | ||
|  |         var updateTemplate = function($scope, element, attributes) { | ||
|  |             if(!$scope.activeTemplate || $scope.activeTemplate != $scope.activeTab.id) { | ||
|  |                 // Check if current loaded template is still the right one
 | ||
|  |                 var contentDiv = $(element.children()[1]); | ||
|  | 
 | ||
|  |                 var childScope = angular.element(element.children()[1]).scope(); | ||
|  |                 if($scope.activeTemplate && childScope != $scope) { | ||
|  |                     // Child-scope created by the included element, should be destroyed
 | ||
|  |                     childScope.$destroy(); | ||
|  |                 } | ||
|  | 
 | ||
|  |                 if($scope.activeTab && $scope.activeTab.templateUrl) { | ||
|  |                     // Load the HTML-fragment or get from cache
 | ||
|  |                     var loader = $http.get($scope.activeTab.templateUrl, {cache: $templateCache}); | ||
|  |                     var promise = loader.success(function(html) { | ||
|  |                         contentDiv.html(html); | ||
|  |                     }).then(function (response) { | ||
|  |                         $scope.activeTemplate = $scope.activeTab.id; | ||
|  |                         contentDiv.replaceWith($compile(contentDiv.html())($scope)); | ||
|  |                     }); | ||
|  |                 } else { | ||
|  |                     // No templates are being used, no need to use the contentDiv for this tab, clear it
 | ||
|  |                     contentDiv.empty(); | ||
|  |                 } | ||
|  |             } | ||
|  |         }; | ||
|  | 
 | ||
|  |         var directive = {}; | ||
|  |         directive.restrict = 'A'; | ||
|  |         directive.replace = true; | ||
|  |         directive.transclude = true; | ||
|  |         directive.template = '<div><div class="clearfix"><ul class="tabs clearfix">' + | ||
|  |             '<li ng-repeat="tab in tabs" ng-class="{\'active\': tab.id == activeTab.id}"><a ng-click="tabClicked(tab)">{{tab.title && (tab.title | translate) || (tab.name | translate)}}</a></li>' + | ||
|  |             '</ul></div>' + | ||
|  |             '<div></div>' + | ||
|  |             '</div>'; | ||
|  | 
 | ||
|  |         directive.scope = { | ||
|  |             possibleTabs : "=tabControl", | ||
|  |             model: "=model", | ||
|  |             activeTabReference: "=activeTab" | ||
|  |         }; | ||
|  | 
 | ||
|  | 
 | ||
|  |         directive.controller = ['$scope', '$element', function($scope, $element) { | ||
|  | 
 | ||
|  |             $scope.refreshTabs = function() { | ||
|  |                 var tabs = []; | ||
|  |                 for(var i=0; i < $scope.possibleTabs.length; i++) { | ||
|  |                     var tab = $scope.possibleTabs[i]; | ||
|  |                     if(!tab.hide) { | ||
|  |                         tabs.push(tab); | ||
|  |                     } | ||
|  |                 } | ||
|  |                 $scope.tabs = tabs; | ||
|  |             }; | ||
|  | 
 | ||
|  |             $scope.$watch('possibleTabs', function() { | ||
|  |                 $scope.refreshTabs(); | ||
|  |             }, true); | ||
|  | 
 | ||
|  |             $scope.$watch('activeTabReference', function(newValue, oldValue) { | ||
|  |                 if(!$scope.activeTab || $scope.activeTab.id != newValue) { | ||
|  |                     // Active tab ID changed from outside of the directive controller, need to switch to the
 | ||
|  |                     // right tab within this scope
 | ||
|  |                     var newTab = $scope.findTab(newValue); | ||
|  |                     if(newTab) { | ||
|  |                         $scope.tabClicked(newTab); | ||
|  |                     } | ||
|  |                 } | ||
|  |             }); | ||
|  | 
 | ||
|  |             $scope.findTab = function(tabId) { | ||
|  |                 if($scope.possibleTabs) { | ||
|  |                     for(var i=0; i< $scope.possibleTabs.length; i++) { | ||
|  |                         if($scope.possibleTabs[i].id == tabId) { | ||
|  |                             return $scope.possibleTabs[i]; | ||
|  |                         } | ||
|  |                     } | ||
|  |                 } | ||
|  |                 return undefined; | ||
|  |             }; | ||
|  | 
 | ||
|  |             $scope.tabClicked = function(tab) { | ||
|  |                 if (tab.hide) { | ||
|  |                     tab.hide = false; | ||
|  |                     $scope.refreshTabs(); | ||
|  |                 } | ||
|  |                 $scope.activeTab = tab; | ||
|  |                 if (tab) { | ||
|  |                     $scope.activeTabReference = tab.id; | ||
|  |                 } else { | ||
|  |                     $scope.activeTabReference = undefined; | ||
|  |                 } | ||
|  |                 updateTemplate($scope, $element); | ||
|  |             }; | ||
|  | 
 | ||
|  |             $scope.refreshTabs(); | ||
|  | 
 | ||
|  |             if($scope.tabs && $scope.tabs.length > 0) { | ||
|  |                 if($scope.activeTabReference) { | ||
|  |                     $scope.activeTab = $scope.findTab($scope.activeTabReference); | ||
|  |                 } | ||
|  | 
 | ||
|  |                 if(!$scope.activeTab) { | ||
|  |                     // Revert to the first tab, if no tab is forced to be shown first
 | ||
|  |                     $scope.activeTab = $scope.tabs[0]; | ||
|  |                 } | ||
|  |                 $scope.tabClicked($scope.activeTab); | ||
|  |             } | ||
|  |         }]; | ||
|  | 
 | ||
|  |         directive.link = updateTemplate; | ||
|  | 
 | ||
|  |         return directive; | ||
|  |     }]); | ||
|  | 
 | ||
|  | /** | ||
|  |  * Directive that calls the function present in the toggle-dragover attribute with a single parameter (over) when | ||
|  |  * dragging over the element has started (over = true) or ended (over = false) | ||
|  |  */ | ||
|  | flowableModule | ||
|  |     .directive('toggleDragover', ["$document", "$parse", function ($document, $parse) { | ||
|  |         var linkFunction = function ($scope, $element, $attributes) { | ||
|  | 
 | ||
|  | 
 | ||
|  |             var toggleFunction = $attributes.toggleDragover; | ||
|  |             var callback = $parse(toggleFunction); | ||
|  | 
 | ||
|  |             var el = $element[0]; | ||
|  | 
 | ||
|  |             el.addEventListener('dragenter',function(e) { | ||
|  |                     $scope.$apply(function() { | ||
|  |                         callback($scope, {'over': true}); | ||
|  |                     }); | ||
|  |                     return false; | ||
|  |                 }, | ||
|  |                 false | ||
|  |             ); | ||
|  | 
 | ||
|  |             el.addEventListener('dragleave', function(e) { | ||
|  |                     $scope.$apply(function() { | ||
|  |                         callback($scope, {'over': false}); | ||
|  |                     }); | ||
|  |                     return false; | ||
|  |                 }, | ||
|  |                 false | ||
|  |             ); | ||
|  |         }; | ||
|  | 
 | ||
|  |         return( linkFunction ); | ||
|  |     }]); | ||
|  | 
 | ||
|  | flowableModule.directive('editInPlace', function () { | ||
|  |     return { | ||
|  |         restrict: 'E', | ||
|  |         scope: { | ||
|  |             value: '=' | ||
|  |         }, | ||
|  |         template: '<span ng-click="edit()" ng-bind="value"></span><span class="glyphicon glyphicon-pencil edit-in-place-icon"></span><input ng-model="value" class="inline-edit-value form-control" ng-blur="stopEdit()" custom-keys enter-pressed="stopEdit()">', | ||
|  |         link: function ($scope, element, attrs) { | ||
|  | 
 | ||
|  |             var iconElement = angular.element(element.children()[1]); | ||
|  |             var inputElement = angular.element(element.children()[2]); | ||
|  | 
 | ||
|  |             // This directive should have a set class so we can style it.
 | ||
|  |             element.addClass('edit-in-place'); | ||
|  | 
 | ||
|  |             // Initially, we're not editing.
 | ||
|  |             $scope.editing = false; | ||
|  | 
 | ||
|  |             // ng-click handler to activate edit-in-place
 | ||
|  |             $scope.edit = function () { | ||
|  |                 $scope.editing = true; | ||
|  | 
 | ||
|  |                 // We control display through a class on the directive itself. See the CSS.
 | ||
|  |                 element.addClass('active'); | ||
|  | 
 | ||
|  |                 // And we must focus the element.
 | ||
|  |                 // `angular.element()` provides a chainable array, like jQuery so to access a native DOM function,
 | ||
|  |                 // we have to reference the first element in the array.
 | ||
|  |                 inputElement[0].focus(); | ||
|  |             }; | ||
|  | 
 | ||
|  |             $scope.stopEdit = function() { | ||
|  |                 $scope.editing = false; | ||
|  |                 element.removeClass('active'); | ||
|  |             }; | ||
|  | 
 | ||
|  | //            // When we leave the input, we're done editing.
 | ||
|  | //            inputElement.prop('onblur', function () {
 | ||
|  | //                console.log('ONBLUR');
 | ||
|  | //                $scope.editing = false;
 | ||
|  | //                element.removeClass('active');
 | ||
|  | //            });
 | ||
|  |         } | ||
|  |     }; | ||
|  | }); | ||
|  | 
 | ||
|  | 
 | ||
|  | /* UTILITY METHODS */ | ||
|  | 
 | ||
|  | /** | ||
|  |  * This creates a modal window that auto closes on route change. | ||
|  |  * By default, this is NOT the case, and leads to some funny behaviour. | ||
|  |  * | ||
|  |  * Use this method vs the default $modal({myJson}) approach | ||
|  |  */ | ||
|  | var _internalCreateModal = function(modalConfig, $modal, $scope) { | ||
|  | 
 | ||
|  |     if ($scope !== null && $scope !== undefined) { | ||
|  |         $scope.modal = $modal(modalConfig); | ||
|  | 
 | ||
|  |         $scope.$on('$routeChangeStart', function () { | ||
|  |             if ($scope.modal) { | ||
|  |                 $scope.modal.hide(); | ||
|  |             } | ||
|  |         }); | ||
|  | 
 | ||
|  |         return $scope.modal; | ||
|  |     } else { | ||
|  |         return $modal(modalConfig); | ||
|  |     } | ||
|  | 
 | ||
|  | }; | ||
|  | 
 | ||
|  | flowableModule. | ||
|  |     directive('numberInputCheck', function() { | ||
|  | 
 | ||
|  |         return { | ||
|  |             require: 'ngModel', | ||
|  |             link: function(scope, element, attrs, modelCtrl) { | ||
|  | 
 | ||
|  |                 modelCtrl.$parsers.push(function (inputValue) { | ||
|  | 
 | ||
|  |                     var transformedInput; | ||
|  |                     if (inputValue && inputValue.indexOf('-') == 0) { | ||
|  |                         transformedInput = inputValue.substr(1).replace(/([^0-9])/g, ''); | ||
|  |                         transformedInput = '-' + transformedInput; | ||
|  |                     } else { | ||
|  |                         transformedInput = inputValue.replace(/([^0-9])/g, ''); | ||
|  |                     } | ||
|  | 
 | ||
|  |                     if (transformedInput != inputValue) { | ||
|  |                         modelCtrl.$setViewValue(transformedInput); | ||
|  |                         modelCtrl.$render(); | ||
|  |                     } | ||
|  | 
 | ||
|  |                     return transformedInput; | ||
|  |                 }); | ||
|  |             } | ||
|  |         }; | ||
|  |     }); | ||
|  | 
 | ||
|  | flowableModule. | ||
|  | directive('decimalNumberInputCheck', function() { | ||
|  | 
 | ||
|  |     return { | ||
|  |         require: 'ngModel', | ||
|  |         link: function(scope, element, attrs, modelCtrl) { | ||
|  | 
 | ||
|  |             modelCtrl.$parsers.push(function (inputValue) { | ||
|  | 
 | ||
|  |             	var transformedInput = inputValue; | ||
|  |                 var negativeSign = '';                 | ||
|  | 
 | ||
|  |                 if (transformedInput && transformedInput.indexOf('-') == 0) { | ||
|  |                     negativeSign = '-'; | ||
|  |                     transformedInput = inputValue.substr(1); | ||
|  |                 } | ||
|  | 
 | ||
|  |                 if(transformedInput && transformedInput.indexOf('.') == 0 ){ | ||
|  |                     transformedInput = "0" + transformedInput; | ||
|  |                 } | ||
|  | 
 | ||
|  |                 if(transformedInput && transformedInput.indexOf('.') > -1){        | ||
|  |                     var dotIndex = transformedInput.indexOf('.');              | ||
|  |                     var left = transformedInput.substr(0, dotIndex); | ||
|  |                     var right = transformedInput.substr(dotIndex+1); | ||
|  |                      | ||
|  |                     left = left.replace(/([^0-9])/g, ''); | ||
|  |                     right = right.replace(/([^0-9])/g, ''); | ||
|  |                     transformedInput = negativeSign + left + '.' + right; | ||
|  |                 } | ||
|  |                 else{ | ||
|  |                     transformedInput = negativeSign + transformedInput.replace(/([^0-9])/g, ''); | ||
|  |                 } | ||
|  | 
 | ||
|  | 
 | ||
|  |                 if (transformedInput != inputValue) { | ||
|  |                     modelCtrl.$setViewValue(transformedInput); | ||
|  |                     modelCtrl.$render(); | ||
|  |                 } | ||
|  | 
 | ||
|  |                 return transformedInput; | ||
|  |             }); | ||
|  |         } | ||
|  |     }; | ||
|  | }); |