Completed
Pull Request — develop (#177)
by Wachter
11:57
created

Resources/public/js/components/article-selection/main.js   B

Complexity

Total Complexity 36
Complexity/F 1.71

Size

Lines of Code 300
Function Count 21

Duplication

Duplicated Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 1
Metric Value
wmc 36
dl 0
loc 300
rs 8.8
c 2
b 0
f 1
cc 0
nc 64
mnd 3
bc 35
fnc 21
bpm 1.6666
cpm 1.7142
noi 6

1 Function

Rating   Name   Duplication   Size   Complexity  
B main.js ➔ define 0 293 1
1
/*
2
 * This file is part of Sulu.
3
 *
4
 * (c) MASSIVE ART WebServices GmbH
5
 *
6
 * This source file is subject to the MIT license that is bundled
7
 * with this source code in the file LICENSE.
8
 */
9
10
/**
11
 * Article-Selection content type.
12
 *
13
 * Allows selection of multiple articles.
14
 */
15
define([
16
    'underscore',
17
    'config',
18
    'services/suluwebsite/reference-store',
19
    'text!./overlay.html',
20
    'text!./contentItem.html',
21
    'text!/admin/api/articles/fields'
22
], function(_, Config, referenceStore, overlayTemplate, contentItemTemplate, fieldsResponse) {
23
24
    'use strict';
25
26
    var fields = JSON.parse(fieldsResponse),
27
28
        config = Config.get('sulu_article'),
29
30
        defaults = {
31
            options: {
32
                url: '/admin/api/articles',
33
                eventNamespace: 'sulu.article-selection',
34
                resultKey: 'articles',
35
                dataAttribute: 'article-selection',
36
                dataDefault: [],
37
                hidePositionElement: true,
38
                hideConfigButton: true,
39
                navigateEvent: 'sulu.router.navigate',
40
                translations: {
41
                    noContentSelected: 'sulu_article.selection.no-result'
42
                }
43
            },
44
45
            templates: {
46
                overlay: overlayTemplate,
47
                contentItem: contentItemTemplate
48
            },
49
50
            translations: {
51
                title: 'public.title',
52
                overlayTitle: 'sulu_article.title'
53
            }
54
        },
55
56
        /**
57
         * Handles aura-events.
58
         */
59
        bindCustomEvents = function() {
60
            this.sandbox.on(
61
                'husky.overlay.article-selection.' + this.options.instanceName + '.add.initialized',
62
                initializeList.bind(this)
63
            );
64
65
            this.sandbox.on(
66
                'husky.overlay.article-selection.' + this.options.instanceName + '.add.opened',
67
                updateList.bind(this)
68
            );
69
70
            // adjust position of overlay after column-navigation has initialized
71
            this.sandbox.on('husky.datagrid.article.view.rendered', function() {
72
                this.sandbox.emit('husky.overlay.article-selection.' + this.options.instanceName + '.add.set-position');
73
            }.bind(this));
74
75
            this.sandbox.on('husky.tabs.overlayarticle-selection.' + this.options.instanceName + '.add.item.select', typeChange.bind(this));
76
        },
77
78
        /**
79
         * Initializes list in the overlay
80
         */
81
        initializeList = function() {
82
            this.sandbox.start([
83
                {
84
                    name: 'search@husky',
85
                    options: {
86
                        appearance: 'white small',
87
                        instanceName: this.options.instanceName + '-article-search',
88
                        el: '#article-selection-' + this.options.instanceName + '-search'
89
                    }
90
                },
91
                {
92
                    name: 'datagrid@husky',
93
                    options: {
94
                        el: '#article-selection-' + this.options.instanceName + '-list',
95
                        instanceName: this.options.instanceName,
96
                        url: this.url,
97
                        preselected: this.getData() || [],
98
                        resultKey: this.options.resultKey,
99
                        sortable: false,
100
                        columnOptionsInstanceName: '',
101
                        clickCallback: function(item) {
102
                            this.sandbox.emit('husky.datagrid.' + this.options.instanceName + '.toggle.item', item);
103
                        }.bind(this),
104
                        selectedCounter: true,
105
                        searchInstanceName: this.options.instanceName + '-article-search',
106
                        searchFields: ['id', 'title'],
107
                        paginationOptions: {
108
                            dropdown: {
109
                                limit: 20
110
                            }
111
                        },
112
                        matchings: fields
113
                    }
114
                }
115
            ]);
116
        },
117
118
        /**
119
         * Updates the datagrid when opening the overlay again
120
         */
121
        updateList = function() {
122
            var data = this.getData() || [];
123
124
            this.sandbox.emit('husky.datagrid.' + this.options.instanceName + '.selected.update', data);
125
        },
126
127
        /**
128
         * Handle dom events
129
         */
130
        bindDomEvents = function() {
131
            this.sandbox.dom.on(this.$el, 'click', function() {
132
                return false;
133
            }.bind(this), '.search-icon');
0 ignored issues
show
unused-code introduced by
The call to bind does not seem necessary since the function does not use this. Consider calling it directly.
Loading history...
134
135
            this.sandbox.dom.on(this.$el, 'keydown', function(e) {
136
                if (event.keyCode === 13) {
0 ignored issues
show
Complexity Best Practice introduced by
There is no return statement if event.keyCode === 13 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...
Bug introduced by
The variable event seems to be never declared. If this is a global, consider adding a /** global: event */ 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...
137
                    e.preventDefault();
138
                    e.stopPropagation();
139
140
                    return false;
141
                }
142
            }.bind(this), '.search-input');
0 ignored issues
show
unused-code introduced by
The call to bind does not seem necessary since the function does not use this. Consider calling it directly.
Loading history...
143
        },
144
145
        /**
146
         * Starts the overlay component
147
         */
148
        startOverlay = function() {
149
            var $element = this.sandbox.dom.createElement('<div/>'),
150
                $data = $(this.templates.overlay({instanceName: this.options.instanceName})),
151
                types = config.types,
152
                typeNames = config.typeNames,
153
                tabs = false;
154
            this.sandbox.dom.append(this.$el, $element);
155
156
            // load all for default
157
            var delimiter = (this.options.url.indexOf('?') === -1) ? '?' : '&';
158
            this.url = this.options.url + delimiter + 'locale=' + this.options.locale;
159
160
            if (1 !== typeNames.length) {
161
                tabs = [];
162
                if (config.displayTabAll === true) {
163
                    tabs.push(
164
                        {
165
                            title: 'public.all',
166
                            key: null,
167
                            data: $data
168
                        }
169
                    );
170
                } else {
171
                    // if not all tab is first load only for the first type
172
                    this.url = this.options.url + delimiter + 'locale=' + this.options.locale + '&type=' + typeNames[0];
173
                }
174
175
                // add tab item for each type
176
                _.each(typeNames, function(type) {
177
                    tabs.push(
178
                        {
179
                            title: types[type].title,
180
                            data: $data
181
                        }
182
                    );
183
                }.bind(this));
0 ignored issues
show
unused-code introduced by
The call to bind does not seem necessary since the function does not use this. Consider calling it directly.
Loading history...
184
185
                $data = null;
186
            }
187
188
            this.sandbox.start([
189
                {
190
                    name: 'overlay@husky',
191
                    options: {
192
                        triggerEl: this.$addButton,
193
                        cssClass: 'article-content-overlay',
194
                        el: $element,
195
                        removeOnClose: false,
196
                        container: this.$el,
197
                        instanceName: 'article-selection.' + this.options.instanceName + '.add',
198
                        skin: 'large',
199
                        okCallback: getAddOverlayData.bind(this),
200
                        title: this.translations.overlayTitle,
201
                        tabs: tabs,
202
                        data: $data
203
                    }
204
                }
205
            ]);
206
        },
207
208
        /**
209
         * Retrieve data from datagrid and keep sorting of ids.
210
         */
211
        getAddOverlayData = function() {
212
            var data = [],
213
                oldData = this.getData();
214
215
            this.sandbox.emit('husky.datagrid.' + this.options.instanceName + '.items.get-selected', function(selected) {
216
                this.sandbox.util.foreach(selected, function(item) {
217
                    var index = oldData.indexOf(item);
218
219
                    if (index !== -1) {
220
                        data[index] = item;
221
                    } else {
222
                        data.push(item);
223
                    }
224
                }.bind(this));
0 ignored issues
show
unused-code introduced by
The call to bind does not seem necessary since the function does not use this. Consider calling it directly.
Loading history...
225
            }.bind(this));
226
227
            var keys = Object.keys(data),
228
                result = [],
229
                i, len = keys.length;
230
231
            for (i = 0; i < len; i++) {
232
                result.push(data[keys[i]]);
233
            }
234
235
            this.setData(result);
236
        },
237
238
        typeChange = function(item) {
239
            this.type = null;
240
241
            if (item.name) {
242
                for (var type in config.types) {
243
                    if (config.types.hasOwnProperty(type) && config.types[type].title === item.name) {
244
                        this.type = type;
245
246
                        break;
247
                    }
248
                }
249
            }
250
251
            this.sandbox.emit('husky.datagrid.' + this.options.instanceName + '.url.update', {type: this.type});
252
        };
253
254
    return {
255
256
        defaults: defaults,
257
258
        type: 'itembox',
259
260
        initialize: function() {
261
            // sandbox event handling
262
            bindCustomEvents.call(this);
263
            this.prefillReferenceStore();
264
265
            this.render();
266
267
            // init overlays
268
            startOverlay.call(this);
269
270
            // handle dom events
271
            bindDomEvents.call(this);
272
        },
273
274
        getUrl: function(data) {
275
            var delimiter = (this.options.url.indexOf('?') === -1) ? '?' : '&';
276
277
            return [
278
                this.options.url,
279
                delimiter,
280
                'locale=' + this.options.locale,
281
                '&', this.options.idsParameter, '=', (data || []).join(',')
282
            ].join('');
283
        },
284
285
        getItemContent: function(item) {
286
            return this.templates.contentItem({item: item, locale: this.options.locale});
287
        },
288
289
        sortHandler: function(ids) {
290
            this.setData(ids, false);
291
        },
292
293
        removeHandler: function(id) {
294
            var data = this.getData();
295
            for (var i = -1, length = data.length; ++i < length;) {
296
                if (id === data[i]) {
297
                    data.splice(i, 1);
298
                    break;
299
                }
300
            }
301
302
            this.setData(data, false);
303
        },
304
305
        prefillReferenceStore: function() {
306
            var data = this.getData();
307
            for (var key in data) {
308
                if (data.hasOwnProperty(key)) {
309
                    referenceStore.add('article', data[key]);
310
                }
311
            }
312
        }
313
    };
314
});
315