Wallet/src/js/directives/directives.js
Gustavo Maximiliano Cortez c25a592d1c Fix typo
2016-02-17 10:46:42 -05:00

382 lines
11 KiB
JavaScript

'use strict';
function selectText(element) {
var doc = document;
if (doc.body.createTextRange) { // ms
var range = doc.body.createTextRange();
range.moveToElementText(element);
range.select();
} else if (window.getSelection) {
var selection = window.getSelection();
var range = doc.createRange();
range.selectNodeContents(element);
selection.removeAllRanges();
selection.addRange(range);
}
}
angular.module('copayApp.directives')
.directive('validAddress', ['$rootScope', 'bitcore', 'profileService',
function($rootScope, bitcore, profileService) {
return {
require: 'ngModel',
link: function(scope, elem, attrs, ctrl) {
var URI = bitcore.URI;
var Address = bitcore.Address
var validator = function(value) {
if (!profileService.focusedClient)
return;
var networkName = profileService.focusedClient.credentials.network;
// Regular url
if (/^https?:\/\//.test(value)) {
ctrl.$setValidity('validAddress', true);
return value;
}
// Bip21 uri
if (/^bitcoin:/.test(value)) {
var uri, isAddressValid;
var isUriValid = URI.isValid(value);
if (isUriValid) {
uri = new URI(value);
isAddressValid = Address.isValid(uri.address.toString(), networkName)
}
ctrl.$setValidity('validAddress', isUriValid && isAddressValid);
return value;
}
if (typeof value == 'undefined') {
ctrl.$pristine = true;
return;
}
// Regular Address
ctrl.$setValidity('validAddress', Address.isValid(value, networkName));
return value;
};
ctrl.$parsers.unshift(validator);
ctrl.$formatters.unshift(validator);
}
};
}
])
.directive('validUrl', [
function() {
return {
require: 'ngModel',
link: function(scope, elem, attrs, ctrl) {
var validator = function(value) {
// Regular url
if (/^https?:\/\//.test(value)) {
ctrl.$setValidity('validUrl', true);
return value;
} else {
ctrl.$setValidity('validUrl', false);
return value;
}
};
ctrl.$parsers.unshift(validator);
ctrl.$formatters.unshift(validator);
}
};
}
])
.directive('validAmount', ['configService',
function(configService) {
return {
require: 'ngModel',
link: function(scope, element, attrs, ctrl) {
var val = function(value) {
var settings = configService.getSync().wallet.settings;
var vNum = Number((value * settings.unitToSatoshi).toFixed(0));
if (typeof value == 'undefined' || value == 0) {
ctrl.$pristine = true;
}
if (typeof vNum == "number" && vNum > 0) {
var decimals = Number(settings.unitDecimals);
var sep_index = ('' + value).indexOf('.');
var str_value = ('' + value).substring(sep_index + 1);
if (sep_index > 0 && str_value.length > decimals) {
ctrl.$setValidity('validAmount', false);
} else {
ctrl.$setValidity('validAmount', true);
}
} else {
ctrl.$setValidity('validAmount', false);
}
return value;
}
ctrl.$parsers.unshift(val);
ctrl.$formatters.unshift(val);
}
};
}
])
.directive('walletSecret', function(bitcore) {
return {
require: 'ngModel',
link: function(scope, elem, attrs, ctrl) {
var validator = function(value) {
if (value.length > 0) {
var m = value.match(/^[0-9A-HJ-NP-Za-km-z]{70,80}$/);
ctrl.$setValidity('walletSecret', m ? true : false);
}
return value;
};
ctrl.$parsers.unshift(validator);
}
};
})
.directive('loading', function() {
return {
restrict: 'A',
link: function($scope, element, attr) {
var a = element.html();
var text = attr.loading;
element.on('click', function() {
element.html('<i class="size-21 fi-bitcoin-circle icon-rotate spinner"></i> ' + text + '...');
});
$scope.$watch('loading', function(val) {
if (!val) {
element.html(a);
}
});
}
}
})
.directive('ngFileSelect', function() {
return {
link: function($scope, el) {
el.bind('change', function(e) {
$scope.file = (e.srcElement || e.target).files[0];
$scope.getFile();
});
}
}
})
.directive('contact', ['addressbookService', function(addressbookService) {
return {
restrict: 'E',
link: function(scope, element, attrs) {
var addr = attrs.address;
addressbookService.getLabel(addr, function(label) {
if (label) {
element.append(label);
} else {
element.append(addr);
}
});
}
};
}])
.directive('highlightOnChange', function() {
return {
restrict: 'A',
link: function(scope, element, attrs) {
scope.$watch(attrs.highlightOnChange, function(newValue, oldValue) {
element.addClass('highlight');
setTimeout(function() {
element.removeClass('highlight');
}, 500);
});
}
}
})
.directive('checkStrength', function() {
return {
replace: false,
restrict: 'EACM',
require: 'ngModel',
link: function(scope, element, attrs) {
var MIN_LENGTH = 8;
var MESSAGES = ['Very Weak', 'Very Weak', 'Weak', 'Medium', 'Strong', 'Very Strong'];
var COLOR = ['#dd514c', '#dd514c', '#faa732', '#faa732', '#16A085', '#16A085'];
function evaluateMeter(password) {
var passwordStrength = 0;
var text;
if (password.length > 0) passwordStrength = 1;
if (password.length >= MIN_LENGTH) {
if ((password.match(/[a-z]/)) && (password.match(/[A-Z]/))) {
passwordStrength++;
} else {
text = ', add mixed case';
}
if (password.match(/\d+/)) {
passwordStrength++;
} else {
if (!text) text = ', add numerals';
}
if (password.match(/.[!,@,#,$,%,^,&,*,?,_,~,-,(,)]/)) {
passwordStrength++;
} else {
if (!text) text = ', add punctuation';
}
if (password.length > 12) {
passwordStrength++;
} else {
if (!text) text = ', add characters';
}
} else {
text = ', that\'s short';
}
if (!text) text = '';
return {
strength: passwordStrength,
message: MESSAGES[passwordStrength] + text,
color: COLOR[passwordStrength]
}
}
scope.$watch(attrs.ngModel, function(newValue, oldValue) {
if (newValue && newValue !== '') {
var info = evaluateMeter(newValue);
scope[attrs.checkStrength] = info;
}
});
}
};
})
.directive('showFocus', function($timeout) {
return function(scope, element, attrs) {
scope.$watch(attrs.showFocus,
function(newValue) {
$timeout(function() {
newValue && element[0].focus();
});
}, true);
};
})
.directive('match', function() {
return {
require: 'ngModel',
restrict: 'A',
scope: {
match: '='
},
link: function(scope, elem, attrs, ctrl) {
scope.$watch(function() {
return (ctrl.$pristine && angular.isUndefined(ctrl.$modelValue)) || scope.match === ctrl.$modelValue;
}, function(currentValue) {
ctrl.$setValidity('match', currentValue);
});
}
};
})
.directive('clipCopy', function() {
return {
restrict: 'A',
scope: {
clipCopy: '=clipCopy'
},
link: function(scope, elm) {
// TODO this does not work (FIXME)
elm.attr('tooltip', 'Press Ctrl+C to Copy');
elm.attr('tooltip-placement', 'top');
elm.bind('click', function() {
selectText(elm[0]);
});
}
};
})
.directive('menuToggle', function() {
return {
restrict: 'E',
replace: true,
templateUrl: 'views/includes/menu-toggle.html'
}
})
.directive('logo', function() {
return {
restrict: 'E',
scope: {
width: "@",
negative: "="
},
controller: function($scope) {
$scope.logo_url = $scope.negative ? 'img/logo-negative.svg' : 'img/logo.svg';
},
replace: true,
template: '<img ng-src="{{ logo_url }}" alt="Copay">'
}
})
.directive('availableBalance', function() {
return {
restrict: 'E',
replace: true,
templateUrl: 'views/includes/available-balance.html'
}
})
.directive('fastClick', [ 'isCordova', '$timeout', function(isCordova, $timeout) {
return {
scope: { someCtrlFn: '&callbackFn'},
link: function(scope, element, attrs) {
if (!isCordova) {
element.on('click', function(){
scope.someCtrlFn();
console.log('click real');
});
} else {
var trackingClick = false;
var targetElement = null;
var touchStartX = 0;
var touchStartY = 0;
var touchBoundary = 10;
element.on('touchstart', function(event) {
trackingClick = true;
targetElement = event.target;
touchStartX = event.targetTouches[0].pageX;
touchStartY = event.targetTouches[0].pageY;
return true;
});
element.on('touchend', function(event) {
if (trackingClick) {
scope.someCtrlFn();
event.preventDefault();
}
trackingClick = false;
return false;
});
element.on('touchmove', function(event) {
if (!trackingClick) {
return true;
}
// If the touch has moved, cancel the click tracking
if (targetElement !== event.target
|| (Math.abs(event.changedTouches[0].pageX - touchStartX) > touchBoundary
|| (Math.abs(event.changedTouches[0].pageY - touchStartY) > touchBoundary))) {
trackingClick = false;
targetElement = null;
}
return true;
});
element.on('touchcancel', function() {
trackingClick = false;
targetElement = null;
});
}
}
}
}]);
;