Test Setup Failed
Push — master ( d60e73...a71a5d )
by
unknown
04:37 queued 10s
created

src/Oro/Bundle/UIBundle/Resources/public/js/app/views/input-widget/number.js   B

Complexity

Total Complexity 36
Complexity/F 2.77

Size

Lines of Code 167
Function Count 13

Duplication

Duplicated Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 0
wmc 36
nc 1024
mnd 2
bc 28
fnc 13
dl 0
loc 167
rs 8.8
bpm 2.1538
cpm 2.7692
noi 2
c 0
b 0
f 0
1
define(function(require) {
2
    'use strict';
3
4
    var NumberInputWidgetView;
5
    var AbstractInputWidgetView = require('oroui/js/app/views/input-widget/abstract');
6
    var localeSettings = require('orolocale/js/locale-settings');
7
    var _ = require('underscore');
8
    var $ = require('jquery');
9
10
    var decimalSeparator = localeSettings.getNumberFormats('decimal').decimal_separator_symbol;
11
12
    NumberInputWidgetView = AbstractInputWidgetView.extend({
13
        events: {
14
            input: '_normalizeNumberFieldValue',
15
            change: '_normalizeNumberFieldValue',
16
            keypress: '_addFraction'
17
        },
18
19
        precision: null,
20
21
        type: null,
22
23
        pattern: null,
24
25
        allowZero: true,
26
27
        /**
28
         * @inheritDoc
29
         */
30
        constructor: function NumberInputWidgetView() {
31
            NumberInputWidgetView.__super__.constructor.apply(this, arguments);
32
        },
33
34
        findContainer: function() {
35
            return this.$el;
36
        },
37
38
        initializeWidget: function() {
39
            this._setPrecision();
40
            this._setAttr();
41
            this.trigger('input');
42
        },
43
44
        disposeWidget: function() {
45
            this._restoreAttr();
46
            return NumberInputWidgetView.__super__.disposeWidget.apply(this, arguments);
47
        },
48
49
        _setPrecision: function() {
50
            var precision = this.$el.data('precision');
51
            this.precision = _.isUndefined(precision) ? null : precision;
52
        },
53
54
        _setAttr: function() {
55
            this._rememberAttr();
56
            this.$el.attr('type', _.isDesktop() && this.precision !== null ? 'text' : 'number')
57
                .attr('pattern', this.precision === 0 ? '[0-9]*' : '');
58
        },
59
60
        _rememberAttr: function() {
61
            this.pattern = this.$el.attr('pattern');
62
            this.type = this.$el.attr('type');
63
        },
64
65
        _restoreAttr: function() {
66
            this.$el.attr('type', this.type);
67
            if (this.pattern) {
68
                this.$el.attr('pattern', this.pattern);
69
            } else {
70
                this.$el.removeAttr('pattern');
71
            }
72
        },
73
74
        _useFilter: function() {
75
            return this.$el.attr('type') !== 'number';
76
        },
77
78
        _addFraction: function(event) {
79
            if (!this._useFilter()) {
80
                return;
81
            }
82
83
            var field = this.el;
84
            var originalValue = field.value;
85
86
            // set fixed length start
87
            var keyName = event.key || String.fromCharCode(event.which);
88
            if (this.precision > 0 && decimalSeparator === keyName &&
0 ignored issues
show
Complexity Best Practice introduced by
There is no return statement if this.precision > 0 && de... === field.value.length is false. Are you sure this is correct? If so, consider adding return; explicitly.

This check looks for functions where a return statement is found in some execution paths, but not in all.

Consider this little piece of code

function isBig(a) {
    if (a > 5000) {
        return "yes";
    }
}

console.log(isBig(5001)); //returns yes
console.log(isBig(42)); //returns undefined

The function isBig will only return a specific value when its parameter is bigger than 5000. In any other case, it will implicitly return undefined.

This behaviour may not be what you had intended. In any case, you can add a return undefined to the other execution path to make the return value explicit.

Loading history...
89
                field.value.length && field.selectionStart === field.value.length) {
90
                field.value = parseInt(field.value).toFixed(this.precision);
91
92
                if (decimalSeparator !== '.') {
93
                    field.value = field.value.replace('.', decimalSeparator);
94
                }
95
96
                if (!_.isUndefined(field.selectionStart)) {
97
                    field.selectionEnd = field.value.length;
98
                    field.selectionStart = field.value.length - this.precision;
99
                }
100
101
                this._triggerEventOnValueChange(event, originalValue);
102
103
                event.stopPropagation();
104
                event.preventDefault();
105
                return false;
106
            }
107
            // set fixed length end
108
        },
109
110
        _normalizeNumberFieldValue: function(event) {
111
            if (!this._useFilter()) {
112
                return;
113
            }
114
115
            var field = this.el;
116
            var originalValue = field.value;
117
            if (_.isUndefined(field.value)) {
118
                return;
119
            }
120
121
            // Prevent multi zero value
122
            if (this.allowZero) {
123
                field.value = field.value.replace(/^0(\d)*/g, '0');
124
            }
125
126
            // filter value start
127
            if (this.precision === 0 && !this.allowZero) {
128
                field.value = field.value.replace(/^0*/g, '');
129
            }
130
131
            field.value = field.value.replace(/(?!\.)[?:\D+]/g, '');// clear not allowed symbols
132
133
            if (field.value[0] === decimalSeparator && this.precision > 0) {
134
                field.value = '0' + field.value;
135
            }
136
            // filter value end
137
138
            // validate value start
139
            var regExpString = '^([0-9]*)';
140
            if (this.precision > 0) {
141
                regExpString += '(\\' + decimalSeparator + '{1})?([0-9]{1,' + this.precision + '})?';
142
            }
143
144
            var regExp = new RegExp(regExpString, 'g');
145
            var substitution = field.value.replace(regExp, '');
146
147
            if (!regExp.test(field.value) || substitution.length > 0) {
148
                field.value = field.value.match(regExp).join('');
149
150
                this._triggerEventOnValueChange(event, originalValue);
151
                event.preventDefault();
152
                return false;
153
            } else {
154
                this._triggerEventOnValueChange(event, originalValue);
0 ignored issues
show
Best Practice introduced by
There is no return statement in this branch, but you do return something in other branches. Did you maybe miss it? If you do not want to return anything, consider adding return undefined; explicitly.
Loading history...
155
            }
156
            // validate value end
157
        },
158
159
        _triggerEventOnValueChange: function(event, value) {
160
            var field = event.target;
161
            if (field.value !== value) {
162
                $(field).trigger(event);
163
            }
164
        }
165
    });
166
    return NumberInputWidgetView;
167
});
168