SelectExtended.constructor   F
last analyzed

Complexity

Conditions 15

Size

Total Lines 44
Code Lines 33

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 33
dl 0
loc 44
c 0
b 0
f 0
rs 2.9998
cc 15

How to fix   Complexity   

Complexity

Complex classes like SelectExtended.constructor often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
"use strict";
2
Object.defineProperty(exports, "__esModule", { value: true });
3
const globals_1 = require("../globals/globals");
4
(function (root, factory) {
5
    if (typeof globals_1.define === 'function' && globals_1.define.amd) {
6
        globals_1.define([], factory);
7
    }
8
    else if (typeof module === 'object' && module.exports) {
9
        module.exports = factory();
10
    }
11
    else {
12
        root.SelectExtended = factory();
13
    }
14
}(typeof self !== 'undefined' ? self : this, function () {
0 ignored issues
show
Bug introduced by
The variable self seems to be never declared. If this is a global, consider adding a /** global: self */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
15
    class SelectExtended {
16
        constructor($el, options) {
17
            let that = this;
18
            this.id = SelectExtended.generateId();
19
            this.$select = typeof $el === 'string' ? document.querySelector($el) : $el;
20
            this.placeholder = this.$select.dataset['placeholder'] || '';
21
            if (options) {
22
                this.options = options;
23
                this.options.containerClass = options.containerClass;
24
                this.options.multiSelect = options.multiSelect;
25
                this.options.multiSelectedText = options.multiSelectedText;
26
                this.options.onChange = options.onChange;
27
            }
28
            else {
29
                this.mergeOptions();
30
            }
31
            this.blocked = false;
32
            this.initHtml();
33
            this.initEvents();
34
            let value = '';
35
            Object.defineProperty(this, 'value', {
36
                get: function () {
37
                    if (that.options.multiSelect) {
38
                        let result = [];
39
                        that.$el.querySelectorAll('.select-ext-multi-option').forEach(($opt) => {
40
                            if ($opt.querySelector('input').checked) {
41
                                result.push($opt.querySelector('input').value);
42
                            }
43
                        });
44
                        return result;
45
                    }
46
                    return value;
47
                },
48
                set: function (newValue) {
49
                    value = newValue;
50
                    that.updateValue(value);
51
                    if (typeof that.options.onChange === 'function') {
52
                        that.options.onChange();
53
                    }
54
                }
55
            });
56
            if (!this.options.multiSelect) {
57
                this.value = null;
58
            }
59
        }
60
        mergeOptions() {
61
            let defaults = {
62
                onChange: function () { }
63
            };
64
            this.options = Object.assign(defaults);
65
        }
66
        static generateId() {
67
            if (!SelectExtended.id) {
68
                SelectExtended.id = 0;
69
            }
70
            return SelectExtended.id++;
71
        }
72
        initHtml() {
73
            this.$select.style.display = 'none';
74
            this.$el = document.createElement('div');
75
            this.$el.classList.add('select-ext');
76
            this.$el.classList.add('select-ext-' + this.id);
77
            if (this.options.containerClass) {
78
                this.$el.classList.add(this.options.containerClass);
79
            }
80
            if (this.options.multiSelect) {
81
                this.initMultiSelectHtml();
82
            }
83
            else {
84
                this.$el.appendChild(this.makeCurrentValue());
85
                this.$el.appendChild(this.makeOptionGroup());
86
                this.$select.parentElement.insertBefore(this.$el, this.$select);
87
                this.$el.appendChild(this.$select);
88
            }
89
        }
90
        initEvents() {
91
            let that = this;
92
            that.$value.onclick = function (event) {
0 ignored issues
show
Unused Code introduced by
The parameter event is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
93
                that.blocked = true;
94
                that.$el.classList.toggle('active');
95
                setTimeout(() => {
96
                    that.blocked = false;
97
                }, 50);
98
            };
99
            document.body.addEventListener('click', function (event) {
100
                if (!that.blocked && (!(event.target.closest('.select-ext-' + that.id)))) {
101
                    that.$el.classList.remove('active');
102
                }
103
            });
104
            that.$el.querySelectorAll('.select-ext-option').forEach((option) => {
105
                option.onclick = function () {
106
                    that.value = option.dataset['value'];
107
                    that.valueName = option.innerHTML;
108
                    that.$el.classList.remove('active');
109
                };
110
            });
111
            if (that.options.multiSelect) {
112
                that.selectedCount = 0;
113
                that.$el.querySelectorAll('.select-ext-multi-option').forEach((option) => {
114
                    option.querySelector('input').onclick = function (event) {
0 ignored issues
show
Unused Code introduced by
The parameter event is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
115
                        if (that.checked) {
116
                            that.selectedCount++;
117
                        }
118
                        else {
119
                            that.selectedCount--;
120
                        }
121
                        that.$value.innerHTML = that.options.multiSelectedText + ' ' + that.selectedCount;
122
                        if (that.selectedCount > 0) {
123
                            that.$value.classList.add('active');
124
                        }
125
                        else {
126
                            that.$value.classList.remove('active');
127
                        }
128
                    };
129
                });
130
            }
131
        }
132
        getName() {
133
            return this.$select.name;
134
        }
135
        initMultiSelectHtml() {
136
            // Value
137
            this.$value = document.createElement('div');
138
            this.$value.classList.add('select-ext__value');
139
            this.$el.appendChild(this.$value);
140
            // Make custom group
141
            let $group = document.createElement('div');
142
            $group.classList.add('select-ext__options');
143
            this.$el.appendChild($group);
144
            // Make checkbox options
145
            for (let i = 0; i < this.$select.options.length; i++) {
146
                let $option = this.makeMultiOption(this.$select.options[i].innerHTML, this.$select.options[i].value, this.$select.options[i].dataset['selected']);
147
                $group.appendChild($option);
148
            }
149
            this.$select.parentElement.insertBefore(this.$el, this.$select);
150
            // Remove origin select
151
            this.$select.remove();
152
            setTimeout(() => {
153
                let that = this;
154
                if (that.options.multiSelect) {
155
                    that.selectedCount = 0;
156
                    that.$el.querySelectorAll('.select-ext-multi-option').forEach((option) => {
157
                        if (option.querySelector('input').checked) {
158
                            that.selectedCount++;
159
                        }
160
                    });
161
                    that.$value.innerHTML = that.options.multiSelectedText + ' ' + that.selectedCount;
162
                    if (that.selectedCount > 0) {
163
                        that.$value.classList.add('active');
164
                    }
165
                    else {
166
                        that.$value.classList.remove('active');
167
                    }
168
                }
169
            }, 100);
170
        }
171
        makeMultiOption(name, value, selected) {
172
            let $option = document.createElement('label');
173
            $option.classList.add('select-ext-multi-option');
174
            let $checkbox = document.createElement('input');
175
            $checkbox.type = 'checkbox';
176
            $checkbox.name = this.$select.name + '[]';
177
            $checkbox.value = value;
178
            $checkbox.checked = selected;
179
            let $fishSpan = document.createElement('span');
180
            let $name = document.createElement('span');
181
            $name.innerHTML = name;
182
            $option.appendChild($checkbox);
183
            $option.appendChild($fishSpan);
184
            $option.appendChild($name);
185
            return $option;
186
        }
187
        makeCurrentValue() {
188
            this.$value = document.createElement('div');
189
            this.$value.classList.add('select-ext__value');
190
            return this.$value;
191
        }
192
        makeOptionGroup() {
193
            let $group = document.createElement('div');
194
            $group.classList.add('select-ext__options');
195
            for (let i = 0; i < this.$select.options.length; i++) {
196
                $group.appendChild(SelectExtended.makeOption(this.$select.options[i].value, this.$select.options[i].innerHTML));
197
            }
198
            return $group;
199
        }
200
        updateValue(value) {
201
            if (value === null) {
202
                this.setInactive();
203
                return;
204
            }
205
            let $options = this.$el.querySelectorAll('.select-ext-option');
206
            for (let i = 0; i < $options.length; i++) {
207
                if ($options[i].dataset['value'] === value) {
208
                    this.$select.value = value;
209
                    this.$value.innerHTML = $options[i].innerHTML;
210
                    if (this.$value.innerHTML) {
211
                        this.$value.classList.add('active');
212
                    }
213
                    return;
214
                }
215
            }
216
            this.value = null;
217
        }
218
        setInactive() {
219
            this.$select.selectIndex = -1;
220
            this.$value.innerHTML = this.placeholder;
221
            this.$value.classList.remove('active');
222
        }
223
        static makeOption(value, text) {
224
            let $option = document.createElement('div');
225
            $option.classList.add('select-ext-option');
226
            $option.dataset['value'] = value;
227
            $option.innerHTML = text;
228
            return $option;
229
        }
230
    }
231
    return SelectExtended;
232
}));
233