SmartIT_Extensions/BMC/smart-it-full-helix/scripts/app/admin/screen-configuration/expression-builder/expression-builder-directiv...

262 lines
16 KiB
JavaScript

"use strict";
(function () {
'use strict';
angular.module('myitsmApp')
.directive('expressionBuilder', [function () {
return {
restrict: 'E',
scope: {
fieldName: '=',
expression: '=',
propertyName: '=',
fieldAcceleratorsList: '=',
onExpressionChange: '&',
isRequired: '=?'
},
templateUrl: 'views/admin/screen-configuration/expression-builder.html',
controller: ['$scope', '$element', '$filter', '$timeout', 'expressionSyntaxTreeBuilder', 'i18nService', 'screenConfigurationModel', function ($scope, $element, $filter, $timeout, expressionSyntaxTreeBuilder, i18nService, screenConfigurationModel) {
var typeAheadMode = false, gotFullMatch = false, actualTypeAheadText, expressionStart = 0, expressionEnd = 0;
var textFieldExpression = $element.find('.text-input')[0];
var keyCodes = {
enter: 13,
escape: 27,
tab: 9,
upArrow: 38,
downArrow: 40,
space: 32
};
var preventDefaultForKeys = [keyCodes.enter, keyCodes.upArrow, keyCodes.downArrow, keyCodes.tab];
$scope.accelerators = {
expression: '',
showAcceleratorsList: false,
availableExpressions: $scope.fieldAcceleratorsList
};
$scope.errorMsg = '';
function validateExpression(exp) {
var parsedExp, errorType, mapperObject, pos, params, key;
$scope.errorMsg = '';
try {
parsedExp = expressionSyntaxTreeBuilder(exp);
}
catch (e) {
mapperObject = {
errorMessage1: 'Expected expression after',
errorMessage2: 'Expected :',
errorMessage3: 'Expected expression',
errorMessage4: 'Expected exponent (',
errorMessage5: 'Variable names cannot start with a number (',
errorMessage6: 'Unexpected period',
errorMessage7: 'Unclosed quote after',
errorMessage8: 'Unexpected',
errorMessage9: 'Unclosed [',
errorMessage10: 'Unclosed (',
errorMessage11: 'Expected [',
errorMessage12: 'Expected ]',
errorMessage13: 'Expected (',
errorMessage14: 'Expected )',
errorMessage15: 'Expected comma'
};
for (key in mapperObject) {
if (_.includes(e.description, mapperObject[key])) {
errorType = key;
break;
}
}
if (mapperObject[errorType]) {
pos = e.message.substring(mapperObject[errorType].length, e.message.indexOf('at character'));
}
params = [pos, e.index];
if (errorType) {
$scope.errorMsg = i18nService.getLocalizedStringwithParams('expression.builder.' + errorType, params);
}
else {
$scope.errorMsg = i18nService.getLocalizedString('expression.builder.standard.error');
}
}
if (!$scope.errorMsg) {
$scope.errorMsg = screenConfigurationModel.checkExpressionValid(parsedExp, $scope.fieldAcceleratorsList);
}
}
if ($scope.expression) {
validateExpression($scope.expression);
}
$scope.handleBodyKeyDown = function ($event) {
if (($event.which === 52 || $event.keyCode === 52 || $event.key === '$')) {
$scope.accelerators.showAcceleratorsList = true;
expressionStart = $event.target.selectionStart;
typeAheadMode = true;
}
if ($scope.accelerators.showAcceleratorsList && (preventDefaultForKeys.indexOf($event.keyCode) >= 0 || ($event.keyCode === keyCodes.space && gotFullMatch))) {
$event.preventDefault();
}
};
$scope.handleBodyChange = function ($event) {
var actionText = textFieldExpression.value;
var pos = -1, flag = false, temp;
if (!$scope.accelerators.showAcceleratorsList) {
for (temp = 0; temp < actionText.length; temp++) {
if (actionText[temp] === '$' && !flag) {
flag = true;
pos = temp;
}
else if (actionText[temp] === ' ' && flag) {
flag = false;
pos = -1;
}
}
if (pos > -1) {
$scope.accelerators.showAcceleratorsList = true;
expressionStart = pos;
typeAheadMode = true;
if (preventDefaultForKeys.indexOf($event.keyCode) >= 0 || ($event.keyCode === keyCodes.space && gotFullMatch)) {
$event.preventDefault();
}
}
}
expressionEnd = $event.target.selectionEnd;
if (textFieldExpression.value.length > 1 && typeAheadMode && (expressionStart > expressionEnd)) {
$scope.accelerators.showAcceleratorsList = false;
return;
}
if ($scope.accelerators.showAcceleratorsList) {
if (gotFullMatch && [keyCodes.tab, keyCodes.rightArrow, keyCodes.space].indexOf($event.keyCode) >= 0) {
gotFullMatch = false;
return;
}
if (typeAheadMode && ($event.keyCode === keyCodes.tab)) {
var urlText = textFieldExpression.value;
($scope.typeAheadListPos === $scope.acceleratorsList.length - 1) ? $scope.typeAheadListPos = 0 : $scope.typeAheadListPos++;
var selectedItem = $scope.acceleratorsList[$scope.typeAheadListPos] ? $scope.acceleratorsList[$scope.typeAheadListPos].name : '';
var updatedText = [urlText.slice(0, expressionStart), selectedItem, urlText.slice(expressionEnd)].join('');
expressionEnd = parseInt(expressionStart + selectedItem.length);
actualTypeAheadText = updatedText.substring(expressionStart, expressionEnd);
textFieldExpression.value = updatedText;
$timeout(function () {
textFieldExpression.setSelectionRange(expressionStart, expressionEnd);
textFieldExpression.selectionStart = expressionStart;
textFieldExpression.selectionEnd = expressionEnd;
});
return;
}
// ignore if control or alternate key was pressed
if ($event.ctrlKey === true || $event.altKey === true || $event.keyCode === keyCodes.leftArrow || $event.keyCode === keyCodes.rightArrow) {
return;
}
else if ($event.keyCode === keyCodes.upArrow) {
if ($scope.typeAheadListPos > 0) {
$scope.typeAheadListPos--;
}
return;
}
else if ($event.keyCode === keyCodes.downArrow) {
if ($scope.typeAheadListPos < ($scope.acceleratorsList.length - 1)) {
$scope.typeAheadListPos++;
}
return;
}
else if ($event.keyCode === keyCodes.enter) {
$scope.accelerators.expression = actualTypeAheadText;
$scope.insertAcceleratorText();
return;
}
else if ($event.keyCode === keyCodes.escape) {
$scope.disableTypeAheadMode();
return;
}
}
if ($scope.expression && $scope.expression.length) {
if (typeAheadMode) {
actualTypeAheadText = textFieldExpression.value.substring(expressionStart, expressionEnd);
$scope.typeAheadListPos = 0;
}
}
if (typeAheadMode) {
if (actualTypeAheadText && actualTypeAheadText.length > 0 && actualTypeAheadText !== $scope.accelerators.expression) {
$scope.acceleratorsList = $filter('filter')($scope.accelerators.availableExpressions, { name: actualTypeAheadText.substring(1) });
if ($scope.acceleratorsList.length > 0 || $scope.accelerators.expression.length === 0) {
($scope.acceleratorsList.length > 0) ? $scope.accelerators.showAcceleratorsList = true : angular.noop();
$scope.accelerators.expression = actualTypeAheadText;
$scope.popupLeftPosition = 0;
$scope.popupTopPosition = 0;
}
else if ($scope.acceleratorsList.length === 0 && $scope.accelerators.expression.length > 1) {
$scope.hideTypeAheadPopup();
}
}
else if (actualTypeAheadText === '$' || textFieldExpression.value === '$') {
$scope.acceleratorsList = $scope.accelerators.availableExpressions;
}
}
};
$scope.handleBodyClick = function ($event) {
if ($event.target.value.length > 1 && $scope.accelerators.showAcceleratorsList && expressionStart > expressionEnd) {
$scope.accelerators.showAcceleratorsList = false;
}
};
$scope.acceleratorMouseover = function ($index) {
$scope.typeAheadListPos = $index;
};
$scope.insertAcceleratorText = function (selectedItem) {
var urlText = textFieldExpression.value, accelerator = selectedItem || $scope.acceleratorsList[$scope.typeAheadListPos], insertText = accelerator.name, updatedText = urlText;
if ($scope.accelerators.expression) {
if (expressionStart === 0) {
updatedText = insertText + ' ';
}
else {
if (expressionEnd < urlText.length) {
updatedText = [urlText.slice(0, expressionStart), insertText + ' ', urlText.slice(expressionEnd)].join('');
}
else if (expressionEnd === urlText.length) {
updatedText = urlText.substr(0, urlText.length - actualTypeAheadText.length) + insertText + ' ';
}
}
}
else {
if (urlText.length === 0) {
updatedText = insertText;
}
else {
if (expressionEnd > 0) {
updatedText = [urlText.slice(0, expressionStart), insertText + ' ', urlText.slice(expressionEnd)].join('');
}
else {
updatedText += insertText + ' ';
}
}
}
$scope.disableTypeAheadMode();
$scope.expression = updatedText;
$scope.handleExpressionChange();
};
$scope.hideTypeAheadPopup = function () {
$scope.accelerators.showAcceleratorsList = false;
};
$scope.disableTypeAheadMode = function () {
actualTypeAheadText = '';
$scope.accelerators.expression = '';
$scope.accelerators.showAcceleratorsList = false;
$scope.typeAheadListPos = 0;
$scope.acceleratorsList = null;
typeAheadMode = false;
expressionStart = 0;
expressionEnd = 0;
};
$scope.acceleratorsHelp = function () {
actualTypeAheadText = '$';
$scope.accelerators.expression = '';
$scope.accelerators.showAcceleratorsList = true;
$scope.typeAheadListPos = 0;
$scope.acceleratorsList = $scope.accelerators.availableExpressions;
expressionStart = $scope.expression.length;
};
$scope.handleExpressionChange = function () {
validateExpression($scope.expression);
if (angular.isFunction($scope.onExpressionChange)) {
$scope.onExpressionChange();
}
};
}]
};
}]);
}());