Skip to content

Instantly share code, notes, and snippets.

@Imater
Last active September 7, 2015 09:24
Show Gist options
  • Select an option

  • Save Imater/5e754a1c60a58b9447e3 to your computer and use it in GitHub Desktop.

Select an option

Save Imater/5e754a1c60a58b9447e3 to your computer and use it in GitHub Desktop.
fabEdit
<div click-out="closePopover()" class="form-group label-inside-new"
ng-class="{'has-error': isShowError}"
ng-show="visible=='true'">
<div class="popover-place" popover-trigger="triggerPopover"
popover-placement="top"
popover-template="'components/fabPopover/fabSwitchPopover.tpl.html'">
<input class="form-control"
required='{{required}}'
type="{{inputKindField}}"
name="{{id}}"
ng-disabled="enabled=='false'"
ng-model="ngModel"
ng-model-options="{debounce: 200}"
placeholder="{{kind==='small'?caption + (required=='true' ? ' *' : ''):''}}"
ng-keyup="onKeyUp({keyCode: $event.keyCode})"
ng-keydown="onKeyDown({keyCode: $event.keyCode})"
ng-keypress="onKeyPressed({keyCode: $event.keyCode})"
ng-change="onChange({value: ngModel})"
ng-blur="onExit({value: ngModel});checkValueRX();"
ng-focus="onFocus({value: ngModel});showErrorMsg();"
fab-mask
input-mask="inputMaskKind"
mask-option="maskForInput"
tabindex="{{tabIndex}}"/>
<label class=""
alt="{{caption + (required=='true' ? ' *' : '')}}"
caption="{{caption + (required=='true' ? ' *' : '')}}"
ng-click="setFocus()"
ng-class="{'label-required': required=='true' && !ngModel}"
>
</label>
</div>
<div class="form-control-feedback" ng-class="{'' : !showHelp , 'opaque' : showHelp}">
<span class="glyphicon glyphicon-question-sign help-button"
ng-click="triggerPopover('help')"
ng-if="help">
</span>
<span class="glyphicon glyphicon-info-sign error-button"
ng-click="triggerPopover('error')"
ng-if="isShowError">
</span>
</div>
</div>
angular.module('fab.components.fabEdit', []).directive('fabEdit', function ($timeout, hotkeys, $log) {
return {
restrict: 'E',
scope: {
alignment: '@',
enabled: '@',
error: '@',
help: '@',
hint: '@',
inputCheckValueRX: '@',
inputFilterRX: '@',
inputMask: '@',
inputKind: '@',
minLength: '@',
maxLength: '@',
id: '@',
caption: '@',
readOnly: '@',
required: '@',
shortAccessKey: '@',
tabIndex: '@',
visible: '@',
kind: '@',
ngModel: '=?',
onChange: '&',
onFocus: '&',
onExit: '&',
onKeyDown: '&',
onKeyPressed: '&',
onKeyUp: '&',
onValidate: '&',
onValid: '&'
},
require: ['ngModel', '^?fabForm'],
templateUrl: 'components/fabEdit/fabEdit.tpl.html',
compile: function(element, attrs) {
var utils = {
addAlignClass: function(align, element){
var alignClass;
switch (align){
case 'left':
alignClass = 'align-left';
break;
case 'center':
alignClass = 'align-center';
break;
case 'right':
alignClass = 'align-right';
break;
default:
alignClass = 'align-left';
}
element.addClass(alignClass);
},
addKindClass: function(kind, element){
var kindClass;
switch (kind){
case 'small':
kindClass = 'small-input';
break;
case 'big':
kindClass = 'big-input';
break;
default:
kindClass = 'big-input';
}
element.addClass(kindClass);
},
setDefaultValues : function(attrs, vars){
angular.forEach(vars, function(value, key){
attrs[key] = attrs[key] !== undefined ? attrs[key] : value;
});
},
apiGet: function ($scope, fnName, scopeProperty) {
$scope[fnName] = function(){
if (fnName === "isEnabled" || fnName === "isReadOnly" || fnName === "isRequired" || fnName === "isVisible"){
return $scope[scopeProperty] == "true";
}
return $scope[scopeProperty];
}
},
apiSet: function ($scope, fnName, scopeProperty, permanentValue) {
$scope[fnName] = function(value){
$timeout(function(){
$scope[scopeProperty] = permanentValue === undefined ? value.toString() : permanentValue.toString();
},1);
}
},
addFocusHotkey: function(scope, shortAccessKey){
if(!shortAccessKey){
return angular.noop();
}
hotkeys.bindTo(scope).add({
combo: shortAccessKey,
description: 'set focus to edit',
allowIn: ['INPUT', 'TEXTAREA', 'SELECT'],
callback: function(){
scope.setFocus();
}
});
},
addBlurHotkey: function(scope){
hotkeys.bindTo(scope).add({
combo: 'enter',
description: 'set blur to edit',
allowIn: ['INPUT', 'TEXTAREA', 'SELECT'],
callback: function(){
scope.setBlur();
}
});
}
};
utils.setDefaultValues(attrs, {
alignment: 'left',
enabled: "true",
error: '',
help: '',
inputCheckValueRx: '',
inputFilterRx: '',
tabIndex: -1,
caption: '',
readOnly: "false",
required: 'false',
visible: "true",
kind: "big",
showHelp: "false"
});
//link function
return function ($scope, element, attrs, ctrls) {
$scope.isShowError = false;
$scope.firstValidateExist = false;
$scope.isValid = true;
var formCtrl = ctrls[1];
if (attrs.id && formCtrl && formCtrl.registerComponent) {
formCtrl.registerComponent(attrs.id, $scope);
}
//popover
$scope.popover = {
error: {
className: 'popover-error',
content: $scope.error
},
help: {
className: 'popover-help',
content: $scope.help
},
selected: undefined //currently selected popover
};
$scope.closePopover = function(){
var input = element[0].querySelector('.popover-place');
if ($scope.popover.selected == "help"){
$timeout(function(){
angular.element(input).triggerHandler('triggerPopover');
$scope.showHelp = false;
$scope.popover.selected = undefined;
},1);
}
if ($scope.popover.selected == "error"){
$timeout(function(){
angular.element(input).triggerHandler('triggerPopover');
$scope.popover.selected = undefined;
},1);
}
};
$scope.showErrorMsg = function(){
if ($scope.popover.selected !== "error" && $scope.isShowError){
$scope.triggerPopover('error');
}
};
$scope.triggerPopover = function(type){
var input = element[0].querySelector('.popover-place');
$timeout(function(){
if(!$scope.popover.selected && $scope.popover[type]) {
//open first time
$scope.popover.selected = type;
if (type == "help"){
$scope.showHelp = true;
}
$timeout(function(){
angular.element(input).triggerHandler('triggerPopover');
},1);
} else if ($scope.popover.selected && $scope.popover.selected !== type){
//switch popover to other type
//close and open to recalculate placement
$timeout(function(){
angular.element(input).triggerHandler('triggerPopover');
},1);
$timeout(function(){
angular.element(input).triggerHandler('triggerPopover');
},1);
$scope.popover.selected = type;
$scope.showHelp = type=="help" ? true : false;
} else if ($scope.popover.selected){
//close
$scope.popover.selected = undefined;
$scope.showHelp = false;
$timeout(function(){
angular.element(input).triggerHandler('triggerPopover');
},1);
}
},1)
};
//align
utils.addAlignClass($scope.alignment, element.find('input'));
utils.addKindClass($scope.kind, element);
$scope.setFocus = function () {
$timeout(function(){
$(element.find('input')).focus();
},1);
};
$scope.setBlur = function () {
$timeout(function(){
$(element.find('input')).blur();
},1);
};
//focus on hotkey, blur on Esc
utils.addFocusHotkey($scope, $scope.shortAccessKey);
utils.addBlurHotkey($scope);
var validate = function(value){
if (value === undefined) return '';
var validateFunctions = [
function(value){
if(value.length < $scope.minLength) {
return "Минимальная длина вводимого значения: " + $scope.minLength;
}
},
function(value){
if(value.length > $scope.maxLength) {
return "Максимальная длина вводимого значения: " + $scope.maxLength;
}
},
function(value){
if(false){
return $scope.error;
}
}
];
var count = validateFunctions.length;
for (var i = 0; i < count; i++) {
var errorMessage = validateFunctions[i](value);
if(errorMessage){
return errorMessage;
}
}
};
var handleError = function(errorMessage){
if(errorMessage){
$scope.isShowError = true;
$scope.popover.error.content = errorMessage;
} else {
$scope.isShowError = false;
var input = element[0].querySelector('.popover-place');
if ($scope.popover.selected == "error"){
$timeout(function(){
angular.element(input).triggerHandler('triggerPopover');
$scope.popover.selected = undefined;
},1);
}
}
};
$scope.validateInput = function(){
if ($scope.required=='true' && !$scope.ngModel){
$scope.isShowError = true;
}
};
$scope.$watch('ngModel', function(newValue, oldValue){
if (newValue === oldValue){
return true;
}
if ($scope.inputKind !== "dfDate" && $scope.inputKind !== "dfINNP" && $scope.inputKind !== "dfINNL" && $scope.firstValidateExist !== false){
handleError(validate(newValue));
}
if (newValue !== "" && $scope.firstValidateExist !== true){
$scope.firstValidateExist = true;
}
});
//javascript api
utils.apiGet($scope, "getInputKind", "inputKind");
utils.apiGet($scope, "getMaxLength", "maxLength");
utils.apiGet($scope, "getMinLength", "minLength");
utils.apiGet($scope, "getValue", "ngModel");
utils.apiGet($scope, "isEnabled", "enabled");
utils.apiGet($scope, "isElementValid", "isValid");
utils.apiGet($scope, "isReadOnly", "readOnly");
utils.apiGet($scope, "isRequired", "required");
utils.apiGet($scope, "isVisible", "visible");
utils.apiSet($scope, "setCaption", "caption");
utils.apiSet($scope, "disableElement", "enabled", false);
utils.apiSet($scope, "enableElement", "enabled", true);
utils.apiSet($scope, "hideElement", "visible", false);
utils.apiSet($scope, "setMinLength", "minLength");
utils.apiSet($scope, "setMaxLength", "maxLength");
utils.apiSet($scope, "setRequired", "required");
utils.apiSet($scope, "setValue", "ngModel");
utils.apiSet($scope, "showElement", "visible", true);
}
},
controller: function ($scope, $element, $attrs) {
var initMask = function(){
var FieldValid = function (){
$scope.isValid = true;
$scope.isShowError = false;
var input = $element[0].querySelector('.popover-place');
if ($scope.popover.selected == "error"){
$timeout(function(){
angular.element(input).triggerHandler('triggerPopover');
$scope.popover.selected = undefined;
},1);
}
$scope.popover.error.content = $scope.error;
$scope.$digest();
};
if ($scope.inputMask){
var maskFormating = $scope.inputMask.replace(/\?/g,"_");
maskFormating = maskFormating.replace(/'#/g,"Z");
maskFormating = maskFormating.replace(/'U/g,"C");
maskFormating = maskFormating.replace(/'L/g,"V");
maskFormating = maskFormating.replace(/'Б/g,"B");
maskFormating = maskFormating.replace(/'A/g,"N");
maskFormating = maskFormating.replace(/'_/g,"M");
$.extend($.inputmask.defaults.definitions, {
'#': {
validator: "[0-9]",
cardinality: 1
},
'U': {
validator: "[A-Za-zйцукенгшщзхъфывапролджэячсмитьбюёЙЦУКЕНГШЩЗХЪФЫВАПРОЛДЖЭЯЧСМИТЬБЮЁ]",
cardinality: 1,
casing: "upper"
},
'L': {
validator: "[A-Za-zйцукенгшщзхъфывапролджэячсмитьбюёЙЦУКЕНГШЩЗХЪФЫВАПРОЛДЖЭЯЧСМИТЬБЮЁ]",
cardinality: 1,
casing: "lower"
},
'Б': {
validator: "[йцукенгшщзхъфывапролджэячсмитьбюёЙЦУКЕНГШЩЗХЪФЫВАПРОЛДЖЭЯЧСМИТЬБЮЁ]",
cardinality: 1
},
'A': {
validator: "[A-Za-zйцукенгшщзхъфывапролджэячсмитьбюёЙЦУКЕНГШЩЗХЪФЫВАПРОЛДЖЭЯЧСМИТЬБЮЁ0-9]",
cardinality: 1
},
'_': {
validator: "[A-Za-zйцукенгшщзхъфывапролджэячсмитьбюёЙЦУКЕНГШЩЗХЪФЫВАПРОЛДЖЭЯЧСМИТЬБЮЁ]",
cardinality: 1
},
"Z": {
validator: "[#]",
cardinality: 1
},
"C": {
validator: "[U]",
cardinality: 1
},
"V": {
validator: "[L]",
cardinality: 1
},
"B": {
validator: "[Б]",
cardinality: 1
},
"N": {
validator: "[A]",
cardinality: 1
},
"M": {
validator: "[?]",
cardinality: 1
}
});
$scope.maskForInput = {
'mask': maskFormating,
'showMaskOnFocus' : true,
'showMaskOnHover' : false,
'autoUnmask': true,
'onUnMask': function (maskedValue,unmaskedValue) {
$scope.text = maskedValue;
},
"oncomplete": function () {
if ($scope.onValid){
$scope.onValid();
}
}
};
$scope.inputMaskKind = 'mask';
$scope.inputKindField = "text";
return true;
}
switch ($scope.inputKind){
case "dfFloat":
$scope.maskForInput = {
'alias': "decimal",
'groupSeparator': " ",
'autoGroup': true,
'rightAlign': false,
'radixPoint': ".",
'showMaskOnFocus' : true,
'showMaskOnHover' : true,
'skipRadixDance' : true
};
$scope.inputMaskKind = 'mask';
$scope.inputKindField = "text";
break;
case "dfPassword":
$scope.inputKindField = "password";
break;
case "dfCyrCharOnly":
$scope.maskForInput = {
'regex': "[йцукенгшщзхъфывапролджэячсмитьбюёЙЦУКЕНГШЩЗХЪФЫВАПРОЛДЖЭЯЧСМИТЬБЮЁ]+"
};
$scope.inputKindField = "text";
$scope.inputMaskKind = 'Regex';
break;
case "dfDate":
$scope.maskForInput = {
'mask': "d.m.y",
'showMaskOnFocus' : true,
'showMaskOnHover' : false,
'clearMaskOnLostFocus' : true,
"oncomplete": function () {
var value = $element.find('input')[0].value;
var m = /(\d{2}).(\d{2}).(\d{4})/.exec(value);
m[2] -= 1;
var d = new Date(parseInt(m[3]),parseInt(m[2]),parseInt(m[1]));
if ((m[3] == d.getFullYear()) && (m[2] == d.getMonth()) && (m[1] == d.getDate())){
FieldValid();
} else {
$scope.isValid = false;
$scope.isShowError = true;
$scope.popover.error.content = "Указанная дата некорректна";
$scope.$digest();
}
},
"oncleared": function () {
FieldValid();
}
};
$scope.inputKindField = "text";
$scope.inputMaskKind = 'mask';
break;
case "dfDigitsOnly":
$scope.maskForInput = {
'regex': "[0-9]+"
};
$scope.inputKindField = "text";
$scope.inputMaskKind = 'Regex';
break;
case "dfEmail":
$scope.maskForInput = {
'regex': "[a-zA-Z0-9._%-]+@[a-zA-Z0-9-]+\\.[a-zA-Z]{2,4}"
};
$scope.inputKindField = "text";
$scope.inputMaskKind = 'Regex';
break;
case "dfFIO":
$scope.maskForInput = {
'regex': "[йцукенгшщзхъфывапролджэячсмитьбюёЙЦУКЕНГШЩЗХЪФЫВАПРОЛДЖЭЯЧСМИТЬБЮЁ]+(-[йцукенгшщзхъфывапролджэячсмитьбюёЙЦУКЕНГШЩЗХЪФЫВАПРОЛДЖЭЯЧСМИТЬБЮЁ]+){0,1} [йцукенгшщзхъфывапролджэячсмитьбюёЙЦУКЕНГШЩЗХЪФЫВАПРОЛДЖЭЯЧСМИТЬБЮЁ]+ [йцукенгшщзхъфывапролджэячсмитьбюёЙЦУКЕНГШЩЗХЪФЫВАПРОЛДЖЭЯЧСМИТЬБЮЁ]+"
};
$scope.inputKindField = "text";
$scope.inputMaskKind = 'Regex';
break;
case "dfINNP":
case "dfINNL":
var checkINN = function (INN){
var arrayWeights = INN.length === 10 ? [2,4,10,3,5,9,4,6,8,0] : [3,7,2,4,10,3,5,9,4,6,8,0];
var controlAmount = 0;
var count = INN.length == 10 ? 10: 11;
for (var i=0;i<count;i++){
var weight = INN.length === 10 ? arrayWeights[i] : arrayWeights[i+1]
controlAmount += parseInt(INN[i]) * weight;
}
var controlNumber = controlAmount % 11;
controlNumber = controlNumber > 9 ? controlNumber % 10: controlNumber;
if (INN.length === 10){
return Boolean(parseInt(controlNumber) === parseInt(INN[9]));
} else {
if (parseInt(controlNumber) !== parseInt(INN[10])){ return false}
controlAmount = 0;
for (var i=0;i<INN.length;i++){
controlAmount += parseInt(INN[i]) * arrayWeights[i];
}
controlNumber = controlAmount % 11;
controlNumber = controlNumber > 9 ? controlNumber % 10: controlNumber;
return Boolean(parseInt(controlNumber) === parseInt(INN[11]));
}
}
$scope.maskForInput = {
'showMaskOnFocus' : true,
'showMaskOnHover' : false,
'clearMaskOnLostFocus' : true,
"oncomplete": function () {
var value = $element.find('input')[0].value.replace(/[_\.]/g,"");
if (checkINN(value)===true){
FieldValid();
} else {
$scope.isValid = false;
$scope.isShowError = true;
$scope.popover.error.content = "Указанный ИНН некорректен";
$scope.$digest();
}
},
"oncleared": function () {
FieldValid();
}
};
$scope.maskForInput.mask = $scope.inputKind === "dfINNP" ? "999999999999" : "9999999999";
$scope.inputKindField = "text";
$scope.inputMaskKind = 'mask';
break;
case "dfInteger":
$scope.maskForInput = {
'alias': "decimal",
'groupSeparator': " ",
'autoGroup': true,
'rightAlign': false,
'digits': "0",
'showMaskOnFocus' : true,
'showMaskOnHover' : true,
'skipRadixDance' : true
};
$scope.inputMaskKind = 'mask';
$scope.inputKindField = "text";
break;
case "dfKPP":
$scope.maskForInput = {
'mask': "999999999"
};
$scope.inputMaskKind = 'mask';
$scope.inputKindField = "text";
break;
case "dfLatCharOnly":
$scope.maskForInput = {
'regex': "[a-zA-Z]+"
};
$scope.inputKindField = "text";
$scope.inputMaskKind = 'Regex';
break;
case "dfLatFIO":
$scope.maskForInput = {
'regex': "([a-zA-Z]+(-[a-zA-Z]+){0,1} )+"
};
$scope.inputKindField = "text";
$scope.inputMaskKind = 'Regex';
break;
case "dfLatSurname":
$scope.maskForInput = {
'regex': "([a-zA-Z]+(-[a-zA-Z]+){0,1}){1}"
};
$scope.inputKindField = "text";
$scope.inputMaskKind = 'Regex';
break;
default:
$scope.inputKindField = "text";
break;
}
if ($scope.maskForInput) {
$scope.maskForInput.autoUnmask = true;
$scope.maskForInput.onUnMask = function (maskedValue,unmaskedValue) {$scope.text = maskedValue;}
}
if ($scope.inputFilterRX){
$scope.maskForInput = {
'regex': $scope.inputFilterRX + "+"
};
$scope.inputMaskKind = 'Regex';
$scope.inputKindField = "text";
}
};
initMask();
$scope.setInputMask = function (value){
$scope.inputMask = value;
$scope.inputKind = undefined;
$attrs.inputMask = $attrs.inputMask === undefined ? $scope.inputMask : angular.noop();
initMask();
$timeout(function(){
$element.find('input').inputmask('mask',$scope.maskForInput);
},1);
};
$scope.getInputMask = function (){
return $scope.inputMask;
};
$scope.clearInputMask = function (){
if ($scope.inputMask){
$scope.inputMask = undefined;
initMask();
$timeout(function(){
$element.find('input').inputmask('remove');
},1);
}
};
$scope.setInputKind = function (value){
$scope.inputKind = value;
$scope.inputMask = undefined;
$attrs.inputKind = $attrs.inputKind === undefined ? $scope.inputKind : angular.noop();
if (value !== "dfNone"){
initMask();
$timeout(function(){
$element.find('input').inputmask('mask',$scope.maskForInput);
},1);
} else {
$element.find('input').inputmask('remove');
}
};
$scope.setInputFilterRX = function (value){
$scope.inputFilterRX = value;
$scope.inputKind = undefined;
$scope.inputMask = undefined;
$attrs.inputFilterRX = $attrs.inputFilterRX === undefined ? $scope.inputFilterRX : angular.noop();
initMask();
$timeout(function(){
$element.find('input').inputmask('mask',$scope.maskForInput);
},1);
};
$scope.checkValueRX = function (){
if (!$scope.ngModel){
return true;
}
$timeout(function(){
$element.find('input').inputmask('mask',$scope.maskForInput);
},1);
};
$scope.getText = function (){
if ($scope.inputKind || $scope.inputMask){
return $.inputmask.format($scope.ngModel,$scope.maskForInput);
} else {
return $scope.ngModel;
}
};
$scope.setReadOnly = function (value){
$scope.readOnly = value;
if (value === true){
$element.find('input').attr('readonly',"readonly");
} else {
$element.find('input').removeAttr("readonly");
}
};
}
}
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment