support validate option value before submitting to aria2

This commit is contained in:
MaysWind 2016-06-26 00:26:12 +08:00
parent 05bcc7225d
commit 361ef9cb74
5 changed files with 286 additions and 103 deletions

View file

@ -120,6 +120,11 @@
"Changes to the settings take effect after refreshing page.": "设置将在页面刷新后生效.", "Changes to the settings take effect after refreshing page.": "设置将在页面刷新后生效.",
"Type is illegal!": "类型错误!", "Type is illegal!": "类型错误!",
"Parameter is invalid!": "请求参数无效", "Parameter is invalid!": "请求参数无效",
"Option value cannot be empty!": "参数内容不能为空!",
"Input number is invalid!": "输入的数字无效!",
"Input number is below min value!": "输入的数字小于最小值 {{value}} !",
"Input number is above max value!": "输入的数字大于最大值 {{value}} !",
"Input value is invalid!": "输入的内容无效!",
"format": { "format": {
"longdate": "YYYY年MM月DD日 HH:mm:ss", "longdate": "YYYY年MM月DD日 HH:mm:ss",
"time.millisecond": "{{value}} 毫秒", "time.millisecond": "{{value}} 毫秒",

View file

@ -1,22 +1,41 @@
(function () { (function () {
'use strict'; 'use strict';
angular.module('ariaNg').constant('aria2AllOptions', { angular.module('ariaNg').constant('aria2AllOptions', {
// EXAMPLE:
// 'option name': {
// type: 'string|integer|float|text|boolean|option',
// [suffix: 'Bytes|Milliseconds|Seconds|Minutes|Hours',]
// [defaultValue: '',]
// [readonly: true|false,] //default: false
// [split: '',] //SUPPORT 'text' type
// [showCount: true|false,] //SUPPORT 'text' type, parameter 'split' is required, default: false
// [options: [],] //SUPPORT 'option' type
// [min: 0,] //SUPPORT 'integer', 'float'
// [max: 0,] //SUPPORT 'integer', 'float'
// [pattern: '']
// }
'dir': { 'dir': {
type: 'string' type: 'string',
required: true
}, },
'log': { 'log': {
type: 'string' type: 'string',
required: true
}, },
'max-concurrent-downloads': { 'max-concurrent-downloads': {
type: 'integer', type: 'integer',
defaultValue: '5' defaultValue: '5',
required: true,
min: 1
}, },
'check-integrity': { 'check-integrity': {
type: 'boolean', type: 'boolean',
defaultValue: 'false' defaultValue: 'false',
required: true
}, },
'continue': { 'continue': {
type: 'boolean' type: 'boolean',
required: true
}, },
'all-proxy': { 'all-proxy': {
type: 'string' type: 'string'
@ -30,33 +49,48 @@
'connect-timeout': { 'connect-timeout': {
type: 'integer', type: 'integer',
suffix: 'Seconds', suffix: 'Seconds',
defaultValue: '60' defaultValue: '60',
required: true,
min: 1,
max: 600
}, },
'dry-run': { 'dry-run': {
type: 'boolean', type: 'boolean',
defaultValue: 'false' defaultValue: 'false',
required: true
}, },
'lowest-speed-limit': { 'lowest-speed-limit': {
type: 'string', type: 'string',
suffix: 'Bytes', suffix: 'Bytes',
defaultValue: '0' defaultValue: '0',
required: true,
pattern: '^(0|[1-9]\\d*(K|M)?)$'
}, },
'max-connection-per-server': { 'max-connection-per-server': {
type: 'integer', type: 'integer',
defaultValue: '1' defaultValue: '1',
required: true,
min: 1,
max: 16
}, },
'max-file-not-found': { 'max-file-not-found': {
type: 'integer', type: 'integer',
defaultValue: '0' defaultValue: '0',
required: true,
min: 0
}, },
'max-tries': { 'max-tries': {
type: 'integer', type: 'integer',
defaultValue: '5' defaultValue: '5',
required: true,
min: 0
}, },
'min-split-size': { 'min-split-size': {
type: 'string', type: 'string',
suffix: 'Bytes', suffix: 'Bytes',
defaultValue: '20M' defaultValue: '20M',
required: true,
pattern: '^(0|[1-9]\\d*(K|M)?)$'
}, },
'netrc-path': { 'netrc-path': {
type: 'string', type: 'string',
@ -64,7 +98,8 @@
defaultValue: '$(HOME)/.netrc' defaultValue: '$(HOME)/.netrc'
}, },
'no-netrc': { 'no-netrc': {
type: 'boolean' type: 'boolean',
required: true
}, },
'no-proxy': { 'no-proxy': {
type: 'text', type: 'text',
@ -74,20 +109,26 @@
'proxy-method': { 'proxy-method': {
type: 'option', type: 'option',
options: ['get', 'tunnel'], options: ['get', 'tunnel'],
defaultValue: 'get' defaultValue: 'get',
required: true
}, },
'remote-time': { 'remote-time': {
type: 'boolean', type: 'boolean',
defaultValue: 'false' defaultValue: 'false',
required: true
}, },
'reuse-uri': { 'reuse-uri': {
type: 'boolean', type: 'boolean',
defaultValue: 'true' defaultValue: 'true',
required: true
}, },
'retry-wait': { 'retry-wait': {
type: 'integer', type: 'integer',
suffix: 'Seconds', suffix: 'Seconds',
defaultValue: '0' defaultValue: '0',
required: true,
min: 0,
max: 600
}, },
'server-stat-of': { 'server-stat-of': {
type: 'string' type: 'string'
@ -100,22 +141,29 @@
}, },
'split': { 'split': {
type: 'integer', type: 'integer',
defaultValue: '5' defaultValue: '5',
required: true,
min: 1
}, },
'stream-piece-selector': { 'stream-piece-selector': {
type: 'option', type: 'option',
options: ['default', 'inorder', 'random', 'geom'], options: ['default', 'inorder', 'random', 'geom'],
defaultValue: 'default' defaultValue: 'default',
required: true
}, },
'timeout': { 'timeout': {
type: 'integer', type: 'integer',
suffix: 'Seconds', suffix: 'Seconds',
defaultValue: '60' defaultValue: '60',
required: true,
min: 1,
max: 600
}, },
'uri-selector': { 'uri-selector': {
type: 'option', type: 'option',
options: ['inorder', 'feedback', 'adaptive'], options: ['inorder', 'feedback', 'adaptive'],
defaultValue: 'feedback' defaultValue: 'feedback',
required: true
}, },
'check-certificate': { 'check-certificate': {
type: 'boolean', type: 'boolean',
@ -124,15 +172,18 @@
}, },
'http-accept-gzip': { 'http-accept-gzip': {
type: 'boolean', type: 'boolean',
defaultValue: 'false' defaultValue: 'false',
required: true
}, },
'http-auth-challenge': { 'http-auth-challenge': {
type: 'boolean', type: 'boolean',
defaultValue: 'false' defaultValue: 'false',
required: true
}, },
'http-no-cache': { 'http-no-cache': {
type: 'boolean', type: 'boolean',
defaultValue: 'false' defaultValue: 'false',
required: true
}, },
'http-user': { 'http-user': {
type: 'string' type: 'string'
@ -163,11 +214,13 @@
}, },
'enable-http-keep-alive': { 'enable-http-keep-alive': {
type: 'boolean', type: 'boolean',
defaultValue: 'true' defaultValue: 'true',
required: true
}, },
'enable-http-pipelining': { 'enable-http-pipelining': {
type: 'boolean', type: 'boolean',
defaultValue: 'false' defaultValue: 'false',
required: true
}, },
'header': { 'header': {
type: 'string' type: 'string'
@ -177,7 +230,8 @@
}, },
'use-head': { 'use-head': {
type: 'boolean', type: 'boolean',
defaultValue: 'false' defaultValue: 'false',
required: true
}, },
'user-agent': { 'user-agent': {
type: 'string', type: 'string',
@ -193,7 +247,8 @@
}, },
'ftp-pasv': { 'ftp-pasv': {
type: 'boolean', type: 'boolean',
defaultValue: 'true' defaultValue: 'true',
required: true
}, },
'ftp-proxy': { 'ftp-proxy': {
type: 'string' type: 'string'
@ -207,11 +262,13 @@
'ftp-type': { 'ftp-type': {
type: 'option', type: 'option',
options: ['binary', 'ascii'], options: ['binary', 'ascii'],
defaultValue: 'binary' defaultValue: 'binary',
required: true
}, },
'ftp-reuse-connection': { 'ftp-reuse-connection': {
type: 'boolean', type: 'boolean',
defaultValue: 'true' defaultValue: 'true',
required: true
}, },
'ssh-host-key-md': { 'ssh-host-key-md': {
type: 'string' type: 'string'
@ -227,11 +284,13 @@
}, },
'bt-enable-hook-after-hash-check': { 'bt-enable-hook-after-hash-check': {
type: 'boolean', type: 'boolean',
defaultValue: 'true' defaultValue: 'true',
required: true
}, },
'bt-enable-lpd': { 'bt-enable-lpd': {
type: 'boolean', type: 'boolean',
defaultValue: 'false' defaultValue: 'false',
required: true
}, },
'bt-exclude-tracker': { 'bt-exclude-tracker': {
type: 'text', type: 'text',
@ -243,57 +302,73 @@
}, },
'bt-force-encryption': { 'bt-force-encryption': {
type: 'boolean', type: 'boolean',
defaultValue: 'false' defaultValue: 'false',
required: true
}, },
'bt-hash-check-seed': { 'bt-hash-check-seed': {
type: 'boolean', type: 'boolean',
defaultValue: 'true' defaultValue: 'true',
required: true
}, },
'bt-max-open-files': { 'bt-max-open-files': {
type: 'integer', type: 'integer',
defaultValue: '100' defaultValue: '100',
required: true,
min: 1
}, },
'bt-max-peers': { 'bt-max-peers': {
type: 'integer', type: 'integer',
defaultValue: '55' defaultValue: '55',
required: true,
min: 0
}, },
'bt-metadata-only': { 'bt-metadata-only': {
type: 'boolean', type: 'boolean',
defaultValue: 'false' defaultValue: 'false',
required: true
}, },
'bt-min-crypto-level': { 'bt-min-crypto-level': {
type: 'option', type: 'option',
options: ['plain', 'arc4'], options: ['plain', 'arc4'],
defaultValue: 'plain' defaultValue: 'plain',
required: true
}, },
'bt-prioritize-piece': { 'bt-prioritize-piece': {
type: 'string' type: 'string'
}, },
'bt-remove-unselected-file': { 'bt-remove-unselected-file': {
type: 'boolean', type: 'boolean',
defaultValue: 'false' defaultValue: 'false',
required: true
}, },
'bt-require-crypto': { 'bt-require-crypto': {
type: 'boolean', type: 'boolean',
defaultValue: 'false' defaultValue: 'false',
required: true
}, },
'bt-request-peer-speed-limit': { 'bt-request-peer-speed-limit': {
type: 'string', type: 'string',
suffix: 'Bytes', suffix: 'Bytes',
defaultValue: '50K' defaultValue: '50K',
required: true,
pattern: '^(0|[1-9]\\d*(K|M)?)$'
}, },
'bt-save-metadata': { 'bt-save-metadata': {
type: 'boolean', type: 'boolean',
defaultValue: 'false' defaultValue: 'false',
required: true
}, },
'bt-seed-unverified': { 'bt-seed-unverified': {
type: 'boolean', type: 'boolean',
defaultValue: 'false' defaultValue: 'false',
required: true
}, },
'bt-stop-timeout': { 'bt-stop-timeout': {
type: 'integer', type: 'integer',
suffix: 'Seconds', suffix: 'Seconds',
defaultValue: '0' defaultValue: '0',
required: true,
min: 0
}, },
'bt-tracker': { 'bt-tracker': {
type: 'text', type: 'text',
@ -303,17 +378,25 @@
'bt-tracker-connect-timeout': { 'bt-tracker-connect-timeout': {
type: 'integer', type: 'integer',
suffix: 'Seconds', suffix: 'Seconds',
defaultValue: '60' defaultValue: '60',
required: true,
min: 1,
max: 600
}, },
'bt-tracker-interval': { 'bt-tracker-interval': {
type: 'integer', type: 'integer',
suffix: 'Seconds', suffix: 'Seconds',
defaultValue: '0' defaultValue: '0',
required: true,
min: 0
}, },
'bt-tracker-timeout': { 'bt-tracker-timeout': {
type: 'integer', type: 'integer',
suffix: 'Seconds', suffix: 'Seconds',
defaultValue: '60' defaultValue: '60',
required: true,
min: 1,
max: 600
}, },
'dht-file-path': { 'dht-file-path': {
type: 'string', type: 'string',
@ -326,7 +409,7 @@
defaultValue: '$HOME/.aria2/dht6.dat' defaultValue: '$HOME/.aria2/dht6.dat'
}, },
'dht-listen-port': { 'dht-listen-port': {
type: 'integer', type: 'string',
readonly: true, readonly: true,
defaultValue: '6881-6999' defaultValue: '6881-6999'
}, },
@ -347,12 +430,14 @@
}, },
'enable-peer-exchange': { 'enable-peer-exchange': {
type: 'boolean', type: 'boolean',
defaultValue: 'true' defaultValue: 'true',
required: true
}, },
'follow-torrent': { 'follow-torrent': {
type: 'option', type: 'option',
options: ['true', 'false', 'mem'], options: ['true', 'false', 'mem'],
defaultValue: 'true' defaultValue: 'true',
required: true
}, },
'listen-port': { 'listen-port': {
type: 'integer', type: 'integer',
@ -362,12 +447,16 @@
'max-overall-upload-limit': { 'max-overall-upload-limit': {
type: 'string', type: 'string',
suffix: 'Bytes', suffix: 'Bytes',
defaultValue: '0' defaultValue: '0',
required: true,
pattern: '^(0|[1-9]\\d*(K|M)?)$'
}, },
'max-upload-limit': { 'max-upload-limit': {
type: 'string', type: 'string',
suffix: 'Bytes', suffix: 'Bytes',
defaultValue: '0' defaultValue: '0',
required: true,
pattern: '^(0|[1-9]\\d*(K|M)?)$'
}, },
'peer-id-prefix': { 'peer-id-prefix': {
type: 'string', type: 'string',
@ -376,16 +465,21 @@
}, },
'seed-ratio': { 'seed-ratio': {
type: 'float', type: 'float',
defaultValue: '1.0' defaultValue: '1.0',
required: true,
min: 0
}, },
'seed-time': { 'seed-time': {
type: 'integer', type: 'integer',
suffix: 'Minutes' suffix: 'Minutes',
required: true,
min: 0
}, },
'follow-metalink': { 'follow-metalink': {
type: 'option', type: 'option',
options: ['true', 'false', 'mem'], options: ['true', 'false', 'mem'],
defaultValue: 'true' defaultValue: 'true',
required: true
}, },
'metalink-base-uri': { 'metalink-base-uri': {
type: 'string' type: 'string'
@ -405,11 +499,13 @@
'metalink-preferred-protocol': { 'metalink-preferred-protocol': {
type: 'option', type: 'option',
options: ['http', 'https', 'ftp', 'none'], options: ['http', 'https', 'ftp', 'none'],
defaultValue: 'none' defaultValue: 'none',
required: true
}, },
'metalink-enable-unique-protocol': { 'metalink-enable-unique-protocol': {
type: 'boolean', type: 'boolean',
defaultValue: 'true' defaultValue: 'true',
required: true
}, },
'enable-rpc': { 'enable-rpc': {
type: 'boolean', type: 'boolean',
@ -418,7 +514,8 @@
}, },
'pause-metadata': { 'pause-metadata': {
type: 'boolean', type: 'boolean',
defaultValue: 'false' defaultValue: 'false',
required: true
}, },
'rpc-allow-origin-all': { 'rpc-allow-origin-all': {
type: 'boolean', type: 'boolean',
@ -443,7 +540,8 @@
}, },
'rpc-save-upload-metadata': { 'rpc-save-upload-metadata': {
type: 'boolean', type: 'boolean',
defaultValue: 'false' defaultValue: 'false',
required: true
}, },
'rpc-secure': { 'rpc-secure': {
type: 'boolean', type: 'boolean',
@ -451,23 +549,28 @@
}, },
'allow-overwrite': { 'allow-overwrite': {
type: 'boolean', type: 'boolean',
defaultValue: 'false' defaultValue: 'false',
required: true
}, },
'allow-piece-length-change': { 'allow-piece-length-change': {
type: 'boolean', type: 'boolean',
defaultValue: 'false' defaultValue: 'false',
required: true
}, },
'always-resume': { 'always-resume': {
type: 'boolean', type: 'boolean',
defaultValue: 'true' defaultValue: 'true',
required: true
}, },
'async-dns': { 'async-dns': {
type: 'boolean', type: 'boolean',
defaultValue: 'true' defaultValue: 'true',
required: true
}, },
'auto-file-renaming': { 'auto-file-renaming': {
type: 'boolean', type: 'boolean',
defaultValue: 'true' defaultValue: 'true',
required: true
}, },
'auto-save-interval': { 'auto-save-interval': {
type: 'integer', type: 'integer',
@ -477,7 +580,8 @@
}, },
'conditional-get': { 'conditional-get': {
type: 'boolean', type: 'boolean',
defaultValue: 'false' defaultValue: 'false',
required: true
}, },
'conf-path': { 'conf-path': {
type: 'string', type: 'string',
@ -514,7 +618,8 @@
'download-result': { 'download-result': {
type: 'option', type: 'option',
options: ['default', 'full', 'hide'], options: ['default', 'full', 'hide'],
defaultValue: 'default' defaultValue: 'default',
required: true
}, },
'dscp': { 'dscp': {
type: 'string', type: 'string',
@ -531,7 +636,8 @@
}, },
'enable-mmap': { 'enable-mmap': {
type: 'boolean', type: 'boolean',
defaultValue: 'false' defaultValue: 'false',
required: true
}, },
'event-poll': { 'event-poll': {
type: 'option', type: 'option',
@ -541,15 +647,18 @@
'file-allocation': { 'file-allocation': {
type: 'option', type: 'option',
options: ['none', 'prealloc', 'trunc', 'falloc'], options: ['none', 'prealloc', 'trunc', 'falloc'],
defaultValue: 'prealloc' defaultValue: 'prealloc',
required: true
}, },
'force-save': { 'force-save': {
type: 'boolean', type: 'boolean',
defaultValue: 'false' defaultValue: 'false',
required: true
}, },
'hash-check-only': { 'hash-check-only': {
type: 'boolean', type: 'boolean',
defaultValue: 'false' defaultValue: 'false',
required: true
}, },
'human-readable': { 'human-readable': {
type: 'boolean', type: 'boolean',
@ -558,16 +667,22 @@
}, },
'max-download-result': { 'max-download-result': {
type: 'integer', type: 'integer',
defaultValue: '1000' defaultValue: '1000',
required: true,
min: 0
}, },
'max-mmap-limit': { 'max-mmap-limit': {
type: 'string', type: 'string',
suffix: 'Bytes', suffix: 'Bytes',
defaultValue: '9223372036854775807' defaultValue: '9223372036854775807',
required: true,
pattern: '^(0|[1-9]\\d*(K|M)?)$'
}, },
'max-resume-failure-tries': { 'max-resume-failure-tries': {
type: 'integer', type: 'integer',
defaultValue: '0' defaultValue: '0',
required: true,
min: 0
}, },
'min-tls-version': { 'min-tls-version': {
type: 'option', type: 'option',
@ -578,15 +693,19 @@
'log-level': { 'log-level': {
type: 'option', type: 'option',
options: ['debug', 'info', 'notice', 'warn', 'error'], options: ['debug', 'info', 'notice', 'warn', 'error'],
defaultValue: 'debug' defaultValue: 'debug',
required: true
}, },
'optimize-concurrent-downloads': { 'optimize-concurrent-downloads': {
type: 'string', type: 'string',
defaultValue: 'false' defaultValue: 'false'
}, },
'piece-length': { 'piece-length': {
type: 'integer', type: 'string',
defaultValue: '1M' suffix: 'Bytes',
defaultValue: '1M',
required: true,
pattern: '^(0|[1-9]\\d*M?)$'
}, },
'show-console-readout': { 'show-console-readout': {
type: 'boolean', type: 'boolean',
@ -602,12 +721,16 @@
'max-overall-download-limit': { 'max-overall-download-limit': {
type: 'string', type: 'string',
suffix: 'Bytes', suffix: 'Bytes',
defaultValue: '0' defaultValue: '0',
required: true,
pattern: '^(0|[1-9]\\d*(K|M)?)$'
}, },
'max-download-limit': { 'max-download-limit': {
type: 'string', type: 'string',
suffix: 'Bytes', suffix: 'Bytes',
defaultValue: '0' defaultValue: '0',
required: true,
pattern: '^(0|[1-9]\\d*(K|M)?)$'
}, },
'no-conf': { 'no-conf': {
type: 'boolean', type: 'boolean',
@ -616,11 +739,14 @@
'no-file-allocation-limit': { 'no-file-allocation-limit': {
type: 'string', type: 'string',
suffix: 'Bytes', suffix: 'Bytes',
defaultValue: '5M' defaultValue: '5M',
required: true,
pattern: '^(0|[1-9]\\d*(K|M)?)$'
}, },
'parameterized-uri': { 'parameterized-uri': {
type: 'boolean', type: 'boolean',
defaultValue: 'false' defaultValue: 'false',
required: true
}, },
'quiet': { 'quiet': {
type: 'boolean', type: 'boolean',
@ -629,10 +755,12 @@
}, },
'realtime-chunk-checksum': { 'realtime-chunk-checksum': {
type: 'boolean', type: 'boolean',
defaultValue: 'true' defaultValue: 'true',
required: true
}, },
'remove-control-file': { 'remove-control-file': {
type: 'boolean' type: 'boolean',
required: true
}, },
'save-session': { 'save-session': {
type: 'string' type: 'string'

View file

@ -7,7 +7,8 @@
optionStorageKey: 'Options', optionStorageKey: 'Options',
globalStatStorageCapacity: 120, globalStatStorageCapacity: 120,
taskStatStorageCapacity: 300, taskStatStorageCapacity: 300,
lazySaveTimeout: 500 lazySaveTimeout: 500,
errorTooltipDelay: 200
}).constant('ariaNgDefaultOptions', { }).constant('ariaNgDefaultOptions', {
language: 'en', language: 'en',
rpcHost: '', rpcHost: '',

View file

@ -124,6 +124,11 @@
'Changes to the settings take effect after refreshing page.': 'Changes to the settings take effect after refreshing page.', 'Changes to the settings take effect after refreshing page.': 'Changes to the settings take effect after refreshing page.',
'Type is illegal!': 'Type is illegal!', 'Type is illegal!': 'Type is illegal!',
'Parameter is invalid!': 'Parameter is invalid!', 'Parameter is invalid!': 'Parameter is invalid!',
'Option value cannot be empty!': 'Option value cannot be empty!',
'Input number is invalid!': 'Input number is invalid!',
'Input number is below min value!': 'Input number is below min value {{value}}!',
'Input number is above max value!': 'Input number is above max value {{value}}!',
'Input value is invalid!': 'Input value is invalid!',
'format': { 'format': {
'longdate': 'MM/DD/YYYY HH:mm:ss', 'longdate': 'MM/DD/YYYY HH:mm:ss',
'time.millisecond': '{{value}} Millisecond', 'time.millisecond': '{{value}} Millisecond',

View file

@ -1,7 +1,7 @@
(function () { (function () {
'use strict'; 'use strict';
angular.module('ariaNg').directive('ngSetting', ['$timeout', 'ariaNgConstants', function ($timeout, ariaNgConstants) { angular.module('ariaNg').directive('ngSetting', ['$timeout', '$translate', 'ariaNgConstants', function ($timeout, $translate, ariaNgConstants) {
return { return {
restrict: 'E', restrict: 'E',
templateUrl: 'views/setting.html', templateUrl: 'views/setting.html',
@ -16,26 +16,26 @@
link: function (scope, element, attrs, ngModel) { link: function (scope, element, attrs, ngModel) {
var pendingSaveRequest = null; var pendingSaveRequest = null;
var options = { var options = {
lazySaveTimeout: ariaNgConstants.lazySaveTimeout lazySaveTimeout: ariaNgConstants.lazySaveTimeout,
errorTooltipDelay: ariaNgConstants.errorTooltipDelay
}; };
angular.extend(options, attrs); angular.extend(options, attrs);
scope.optionStatus = (function () {
var value = 'ready';
var destroyTooltip = function () { var destroyTooltip = function () {
angular.element(element).tooltip('destroy'); angular.element(element).tooltip('destroy');
}; };
var showTooltip = function (cause, type) { var showTooltip = function (cause, type, causeParams) {
if (!cause) { if (!cause) {
return; return;
} }
$timeout(function () {
angular.element(element).tooltip({ angular.element(element).tooltip({
title: cause, title: $translate.instant(cause, causeParams),
trigger: 'focus', trigger: 'focus',
placement: 'auto top',
container: element, container: element,
template: template:
'<div class="tooltip' + (type ? ' tooltip-' + type : '') + '" role="tooltip">' + '<div class="tooltip' + (type ? ' tooltip-' + type : '') + '" role="tooltip">' +
@ -43,8 +43,12 @@
'<div class="tooltip-inner"></div>' + '<div class="tooltip-inner"></div>' +
'</div>' '</div>'
}).tooltip('show'); }).tooltip('show');
}, options.errorTooltipDelay);
}; };
scope.optionStatus = (function () {
var value = 'ready';
return { return {
getValue: function () { getValue: function () {
return value; return value;
@ -70,10 +74,10 @@
value = 'failed'; value = 'failed';
showTooltip(cause, 'warning'); showTooltip(cause, 'warning');
}, },
setError: function (cause) { setError: function (cause, causeParams) {
destroyTooltip(); destroyTooltip();
value = 'error'; value = 'error';
showTooltip(cause, 'error'); showTooltip(cause, 'error', causeParams);
}, },
getStatusFeedbackStyle: function () { getStatusFeedbackStyle: function () {
if (value == 'success') { if (value == 'success') {
@ -116,6 +120,10 @@
}; };
scope.changeValue = function (optionValue, lazySave) { scope.changeValue = function (optionValue, lazySave) {
if (pendingSaveRequest) {
$timeout.cancel(pendingSaveRequest);
}
scope.optionValue = optionValue; scope.optionValue = optionValue;
scope.optionStatus.setReady(); scope.optionStatus.setReady();
@ -123,16 +131,52 @@
return; return;
} }
if (scope.option.required && optionValue == '') {
scope.optionStatus.setError('Option value cannot be empty!');
return;
}
if (scope.option.type == 'integer' && !/^-?\d+$/.test(optionValue)) {
scope.optionStatus.setError('Input number is invalid!');
return;
}
if (scope.option.type == 'float' && !/^-?(\d*\.)?\d+$/.test(optionValue)) {
scope.optionStatus.setError('Input number is invalid!');
return;
}
if ((scope.option.type == 'integer' || scope.option.type == 'float') && (!angular.isUndefined(scope.option.min) || !angular.isUndefined(scope.option.max))) {
var number = optionValue;
if (scope.option.type == 'integer') {
number = parseInt(optionValue);
} else if (scope.option.type == 'float') {
number = parseFloat(optionValue);
}
if (!angular.isUndefined(scope.option.min) && number < scope.option.min) {
scope.optionStatus.setError('Input number is below min value!', { value: scope.option.min });
return;
}
if (!angular.isUndefined(scope.option.max) && number > scope.option.max) {
scope.optionStatus.setError('Input number is above max value!', { value: scope.option.max });
return;
}
}
if (!angular.isUndefined(scope.option.pattern) && !(new RegExp(scope.option.pattern).test(optionValue))) {
scope.optionStatus.setError('Input value is invalid!');
return;
}
var data = { var data = {
key: scope.option.key, key: scope.option.key,
value: optionValue, value: optionValue,
optionStatus: scope.optionStatus optionStatus: scope.optionStatus
}; };
if (pendingSaveRequest) {
$timeout.cancel(pendingSaveRequest);
}
var invokeChange = function () { var invokeChange = function () {
scope.optionStatus.setSaving(); scope.optionStatus.setSaving();
scope.onChangeValue(data); scope.onChangeValue(data);