src/assetbundles/src/FieldManipulator.js   F
last analyzed

Complexity

Total Complexity 71
Complexity/F 2.45

Size

Lines of Code 566
Function Count 29

Duplication

Duplicated Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
wmc 71
eloc 268
c 0
b 0
f 0
dl 0
loc 566
rs 2.7199
mnd 42
bc 42
fnc 29
bpm 1.4482
cpm 2.4482
noi 18

How to fix   Complexity   

Complexity

Complex classes like src/assetbundles/src/FieldManipulator.js 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
/**
2
 * Spoon plugin for Craft CMS
3
 *
4
 * @author    Angell & Co
5
 * @copyright Copyright (c) 2018 Angell & Co
6
 * @link      https://angell.io
7
 * @package   Spoon
8
 * @since     3.0.0
9
 */
10
(function($){
11
12
13
    if (typeof Spoon == 'undefined')
14
    {
15
        Spoon = {};
0 ignored issues
show
Bug introduced by
The variable Spoon seems to be never declared. Assigning variables without defining them first makes them global. If this was intended, consider making it explicit like using window.Spoon.
Loading history...
16
    }
17
18
    /**
19
     * Overrides the default Matrix ‘add block’ buttons with our grouped ones
20
     * and keeps them up to date based on the current context.
21
     *
22
     * Also adds any field layouts that may exist for each block type
23
     * in the current context.
24
     */
25
    Spoon.FieldManipulator = Garnish.Base.extend(
0 ignored issues
show
Bug introduced by
The variable Spoon does not seem to be initialized in case typeof Spoon == "undefined" on line 13 is false. Are you sure this can never be the case?
Loading history...
26
        {
27
28
            _handleMatrixInputInitProxy: null,
29
            _handleMatrixInputBlockAddedProxy: null,
30
31
            init: function(settings)
32
            {
33
34
                // Set up
35
                this.setSettings(settings, Spoon.FieldManipulator.defaults);
0 ignored issues
show
Bug introduced by
The variable Spoon does not seem to be initialized in case typeof Spoon == "undefined" on line 13 is false. Are you sure this can never be the case?
Loading history...
36
37
                // Work out if we’re in the 'entrytype' context so we can keep things up to date
38
                if (this.settings.context.split(':')[0] === 'entrytype')
39
                {
40
                    // Listen to entry type switch
41
                    Garnish.on(Craft.EntryTypeSwitcher, 'beforeTypeChange', $.proxy(function(ev)
42
                    {
43
                        this.settings.context = 'entrytype:' + ev.target.$typeSelect.val();
44
                    }, this));
45
                }
46
47
                this._handleMatrixInputInitProxy = $.proxy(this, 'handleMatrixInputInit');
48
                this._handleMatrixInputBlockAddedProxy = $.proxy(this, 'handleMatrixInputBlockAdded');
49
50
                Garnish.on(Craft.MatrixInput, 'afterInit', this._handleMatrixInputInitProxy);
51
                Garnish.on(Craft.MatrixInput, 'blockAdded', this._handleMatrixInputBlockAddedProxy);
52
53
                if (typeof Craft.SuperTable !== "undefined") {
54
                    Garnish.on(Craft.SuperTable.MatrixInputAlt, 'afterInit', this._handleMatrixInputInitProxy);
55
                    Garnish.on(Craft.SuperTable.MatrixInputAlt, 'blockAdded', this._handleMatrixInputBlockAddedProxy);
56
                }
57
58
                // If we are versioned we need to scrape the page as no events will fire
59
                if (this.settings.versioned) {
60
                    Garnish.$doc.find('.matrix-field').each($.proxy(function(idx, matrixField)
61
                    {
62
                        var $matrixField = $(matrixField);
63
64
                        // sort out the button groups
65
                        this.initBlockTypeGroups($matrixField);
66
67
                        // initialize the blocks
68
                        $matrixField.find('> .blocks > .matrixblock').each($.proxy(function(idx, matrixBlock)
69
                        {
70
                            this.initBlocks($(matrixBlock), $matrixField);
71
                        }, this));
72
73
                    }, this));
74
                }
75
            },
76
77
78
            handleMatrixInputInit: function(ev)
79
            {
80
                var $matrixField = ev.target.$container,
81
                    $blocks = ev.target.$blockContainer.children();
82
83
                this.initBlockTypeGroups($matrixField);
84
85
                $blocks.each($.proxy(function(key,block)
86
                {
87
                    this.initBlocks($(block), $matrixField);
88
                }, this));
89
            },
90
91
            handleMatrixInputBlockAdded: function(ev)
92
            {
93
                var $matrixField = ev.target.$container,
94
                    $block = $(ev.$block);
95
96
                this.initBlocks($block, $matrixField);
97
            },
98
99
            initBlockTypeGroups: function($matrixField)
100
            {
101
102
                // check if we’ve already spooned this field
103
                if ( !$matrixField.data('spooned') )
104
                {
105
106
                    // get matrix field handle out of the dom
107
                    var matrixFieldHandle = this._getMatrixFieldName($matrixField);
108
109
                    // Filter by the current matrix field
110
                    var spoonedBlockTypes = [];
111
112
                    // Check current context first
113
                    if (typeof this.settings.blockTypes[this.settings.context] !== "undefined")
114
                    {
115
                        spoonedBlockTypes = $.grep(this.settings.blockTypes[this.settings.context], function(e){ return e.fieldHandle === matrixFieldHandle; });
116
                    }
117
118
                    // Check global context
119
                    if (spoonedBlockTypes.length < 1 && typeof this.settings.blockTypes['global'] !== "undefined")
120
                    {
121
                        spoonedBlockTypes = $.grep(this.settings.blockTypes['global'], function(e){ return e.fieldHandle === matrixFieldHandle; });
122
                    }
123
124
                    // Check we have some config
125
                    if ( spoonedBlockTypes.length >= 1 )
126
                    {
127
128
                        // add some data to tell us we’re spooned
129
                        $matrixField.data('spooned', true);
130
131
                        // store the data for when we loop the blocks themselves so we don’t have to run all this again
132
                        $matrixField.data('spoon-block-types', spoonedBlockTypes);
133
134
                        // Only do the buttons if we’re not versioned
135
                        if (!this.settings.versioned) {
136
137
                            // find the original buttons
138
                            var $origButtons = $matrixField.find('> .buttons').first();
139
140
                            // hide the original ones and start the button spooning process
141
                            $origButtons.addClass('hidden');
142
143
                            // make our own container, not using .buttons as it gets event bindings
144
                            // from MatrixInput.js that we really don't want
145
                            var $spoonedButtonsContainer = $('<div class="buttons-spooned" />').insertAfter($origButtons);
146
147
                            // the main button group
148
                            var $mainButtons = $('<div class="btngroup" />').appendTo($spoonedButtonsContainer);
149
150
                            // the secondary one, used when the container gets too small
151
                            var $secondaryButtons = $('<div class="btn add icon menubtn hidden">' + Craft.t('app', 'Add a block') + '</div>').appendTo($spoonedButtonsContainer),
152
                                $secondaryMenu = $('<div class="menu spoon-secondary-menu" />').appendTo($spoonedButtonsContainer);
153
154
                            // loop each block type config
155
                            for (var i = 0; i < spoonedBlockTypes.length; i++) {
156
157
                                // check if group exists, add if not
158
                                if ($mainButtons.find('[data-spooned-group="' + spoonedBlockTypes[i].groupName + '"]').length === 0) {
159
                                    // main buttons
160
                                    var $mainMenuBtn = $('<div class="btn  menubtn">' + Craft.t('site', spoonedBlockTypes[i]['groupName']) + '</div>').appendTo($mainButtons),
0 ignored issues
show
Unused Code introduced by
The variable $mainMenuBtn seems to be never used. Consider removing it.
Loading history...
161
                                        $mainMenu = $('<div class="menu" data-spooned-group="' + spoonedBlockTypes[i]['groupName'] + '" />').appendTo($mainButtons),
162
                                        $mainUl = $('<ul />').appendTo($mainMenu);
163
164
                                    // single group buttons
165
                                    if (i !== 0) {
166
                                        $('<hr>').appendTo($secondaryMenu);
167
                                    }
168
                                    $('<h6>' + Craft.t('site', spoonedBlockTypes[i]['groupName']) + '</h6>').appendTo($secondaryMenu);
169
                                    var $secondaryUl = $('<ul/>').appendTo($secondaryMenu);
170
                                }
171
172
                                // make a link
173
                                $li = $('<li><a data-type="' + spoonedBlockTypes[i].matrixBlockType.handle + '">' + Craft.t('site', spoonedBlockTypes[i].matrixBlockType.name) + '</a></li>');
0 ignored issues
show
Bug introduced by
The variable $li seems to be never declared. Assigning variables without defining them first makes them global. If this was intended, consider making it explicit like using window.$li.
Loading history...
174
175
                                // add it to the main list
176
                                $li.appendTo($mainUl);
0 ignored issues
show
Bug introduced by
The variable $mainUl seems to not be initialized for all possible execution paths. Are you sure appendTo handles undefined variables?
Loading history...
177
178
                                // add a copy to the secondary one as well
179
                                $li.clone().appendTo($secondaryUl);
0 ignored issues
show
Bug introduced by
The variable $secondaryUl seems to not be initialized for all possible execution paths. Are you sure appendTo handles undefined variables?
Loading history...
180
181
                            }
182
183
                            // make the MenuBtns work
184
                            $mainButtons.find('.menubtn').each(function() {
185
186
                                new Garnish.MenuBtn($(this),
0 ignored issues
show
Unused Code Best Practice introduced by
The object created with new Garnish.MenuBtn($(th...alse,true,None,None))}) is not used but discarded. Consider invoking another function instead of a constructor if you are doing this purely for side effects.
Loading history...
187
                                    {
188
                                        onOptionSelect: function(option) {
189
                                            // find our type and click the correct original btn!
190
                                            var type = $(option).data('type');
191
                                            $origButtons.find('[data-type="' + type + '"]').trigger('click');
192
                                        }
193
                                    });
194
195
                            });
196
197
                            new Garnish.MenuBtn($secondaryButtons,
0 ignored issues
show
Unused Code Best Practice introduced by
The object created with new Garnish.MenuBtn($sec...alse,true,None,None))}) is not used but discarded. Consider invoking another function instead of a constructor if you are doing this purely for side effects.
Loading history...
198
                                {
199
                                    onOptionSelect: function(option) {
200
                                        // find our type and click the correct original btn!
201
                                        var type = $(option).data('type');
202
                                        $origButtons.find('[data-type="' + type + '"]').trigger('click');
203
                                    }
204
                                });
205
206
                            // Bind a resize to the $matrixField so we can work out which groups UI to show
207
                            this.addListener($matrixField, 'resize', $.proxy(function() {
208
                                // Do we know what the button group width is yet?
209
                                if (!$matrixField.data('spoon-main-buttons-width')) {
210
                                    $matrixField.data('spoon-main-buttons-width', $mainButtons.width());
211
212
                                    if (!$matrixField.data('spoon-main-buttons-width')) {
213
                                        return;
214
                                    }
215
                                }
216
217
                                // Check the widths and do the hide/show
218
                                var fieldWidth = $matrixField.width(),
219
                                    mainButtonsWidth = $matrixField.data('spoon-main-buttons-width');
220
                                if (fieldWidth < mainButtonsWidth) {
221
                                    $secondaryButtons.removeClass('hidden');
222
                                    $mainButtons.addClass('hidden');
223
                                } else {
224
                                    $secondaryButtons.addClass('hidden');
225
                                    $mainButtons.removeClass('hidden');
226
                                }
227
228
                            }, this));
229
                        }
230
231
                    }
232
233
                }
234
235
            },
236
237
            initBlocks: function($matrixBlock, $matrixField)
238
            {
239
240
                if ( !$matrixBlock.data('spooned') )
241
                {
242
243
                    // Set this so we don’t re-run this
244
                    $matrixBlock.data('spooned', true);
245
246
                    // Get the cached spooned block types data for this whole field
247
                    var spoonedBlockTypes = $matrixField.data('spoon-block-types');
248
249
                    // Check we have some config
250
                    if ( typeof spoonedBlockTypes !== "undefined" && spoonedBlockTypes.length >= 1 )
251
                    {
252
253
                        // First, sort out the settings menu
254
                        if (!this.settings.versioned) {
255
                            var $settingsBtn = $matrixBlock.find('.actions .settings.menubtn');
256
                            this.initSettingsMenu($settingsBtn, spoonedBlockTypes, $matrixField);
257
                        }
258
259
                        // Second, get the current block’s type out of the dom so we can do the field layout
260
                        var matrixBlockTypeHandle = this._getMatrixBlockTypeHandle($matrixBlock);
261
262
                        // Further filter our spoonedBlockTypes array by the current block’s type
263
                        var spoonedBlockType = $.grep(spoonedBlockTypes, function(e){ return e.matrixBlockType.handle === matrixBlockTypeHandle; });
264
265
                        // Initialize the field layout on the block
266
                        if ( spoonedBlockType.length === 1 && spoonedBlockType[0].fieldLayoutId !== null )
267
                        {
268
                            $matrixBlock.data('spooned-block-type', spoonedBlockType[0]);
269
                            this.initBlockFieldLayout($matrixBlock, $matrixField);
270
                        }
271
                        // If that failed, do another check against the global context
272
                        else if (this.settings.blockTypes.hasOwnProperty('global'))
273
                        {
274
                            var matrixFieldHandle = this._getMatrixFieldName($matrixField);
275
                            spoonedBlockTypes = $.grep(this.settings.blockTypes['global'], function(e){ return e.fieldHandle === matrixFieldHandle; });
276
277
                            if ( spoonedBlockTypes.length >= 1 )
278
                            {
279
                                spoonedBlockType = $.grep(spoonedBlockTypes, function(e){ return e.matrixBlockType.handle === matrixBlockTypeHandle; });
280
281
                                if ( spoonedBlockType.length === 1 && spoonedBlockType[0].fieldLayoutId !== null )
282
                                {
283
                                    $matrixBlock.data('spooned-block-type', spoonedBlockType[0]);
284
                                    this.initBlockFieldLayout($matrixBlock, $matrixField);
285
                                }
286
                                else
287
                                {
288
                                    $matrixBlock.addClass('matrixblock-not-spooned');
289
                                }
290
                            }
291
                            else
292
                            {
293
                                $matrixBlock.addClass('matrixblock-not-spooned');
294
                            }
295
                        }
296
                        else
297
                        {
298
                            $matrixBlock.addClass('matrixblock-not-spooned');
299
                        }
300
301
                    }
302
                    else
303
                    {
304
                        $matrixBlock.addClass('matrixblock-not-spooned');
305
                    }
306
307
                }
308
                else
309
                {
310
                    // Fixes Redactor
311
                    Garnish.$doc.trigger('scroll');
312
                }
313
314
            },
315
316
            initBlockFieldLayout: function($matrixBlock, $matrixField)
317
            {
318
319
                var spoonedBlockType = $matrixBlock.data('spooned-block-type'),
320
                    tabs = spoonedBlockType.fieldLayoutModel.tabs,
321
                    fields = spoonedBlockType.fieldLayoutModel.fields;
322
323
                // Check we have some tabs
324
                // TODO: would be nice to not show the tab nav if there is only one tab
325
                if ( tabs.length >= 1 )
326
                {
327
                    // Add a class so we can style
328
                    $matrixBlock.addClass('matrixblock-spooned');
329
330
                    if (this.settings.versioned) {
331
                        $matrixBlock.addClass('matrixblock-spooned--disabled');
332
                    }
333
334
                    // Get a namespaced id
335
                    var namespace = $matrixField.prop('id') + '-blocks-' + $matrixBlock.data('id'),
336
                        spoonedNamespace = 'spoon-' + namespace;
337
338
                    // Add the tabs container
339
                    var $tabs = $('<ul class="spoon-tabs"/>').appendTo($matrixBlock);
340
341
                    // Make our own fields container and hide the native one, but keep its height
342
                    var $spoonedFields = $('<div class="spoon-fields"/>').css({ 'opacity' : 0 }).appendTo($matrixBlock),
343
                        $fields = $matrixBlock.find('> .fields');
344
                    $fields.css({ 'opacity' : 0 });
345
346
                    // Loop the tabs
347
                    for (var i = 0; i < tabs.length; i++)
348
                    {
349
350
                        // Set up the first one to be active
351
                        var navClasses = '',
352
                            paneClasses = '';
353
354
                        if (i===0)
355
                        {
356
                            navClasses = ' sel';
357
                        }
358
                        else
359
                        {
360
                            paneClasses = ' hidden';
361
                        }
362
363
                        // Add the tab nav, if there is more than one
364
                        if (tabs.length > 1)
365
                        {
366
                            var $tabLi = $('<li/>').appendTo($tabs),
367
                                $tabA = $('<a id="'+spoonedNamespace+'-'+i+'" class="tab'+navClasses+'">'+Craft.t('site', tabs[i].name)+'</a>')
368
                                    .appendTo($tabLi)
369
                                    .data('spooned-tab-target', '#'+spoonedNamespace+'-pane-'+i);
370
                        }
371
372
                        // Make a tab pane
373
                        var $pane = $('<div id="'+spoonedNamespace+'-pane-'+i+'" class="'+paneClasses+'"/>').appendTo($spoonedFields);
374
375
                        // Filter the fields array by their associated tabId and loop over them
376
                        var tabFields = $.grep(fields, function(e){ return e.tabId === tabs[i].id; });
0 ignored issues
show
Bug introduced by
The variable i is changed as part of the for loop for example by i++ on line 347. Only the value of the last iteration will be visible in this function if it is called after the loop.
Loading history...
377
                        for (var n = 0; n < tabFields.length; n++)
378
                        {
379
                            // Move the required field to our new container
380
                            $fields.find('#' + namespace + '-fields-' + tabFields[n].handle + '-field').appendTo($pane);
381
                        }
382
383
                        // Now check for errors and update the tab if needed
384
                        if ($pane.find('.field.has-errors').length > 0 && tabs.length > 1) {
385
                            $tabA.addClass('error');
0 ignored issues
show
Bug introduced by
The variable $tabA seems to not be initialized for all possible execution paths.
Loading history...
386
                            $tabA.append(' <span data-icon="alert" />');
387
                        }
388
389
                    }
390
391
                    // Bind events to tab nav clicks
392
                    if (tabs.length > 1)
393
                    {
394
                        this.addListener($tabs.find('a'), 'click', 'onTabClick');
395
                    }
396
397
                    // Force the fields to be removed from the layout
398
                    $fields.hide();
399
400
                    $spoonedFields.velocity({opacity: 1}, 'fast', $.proxy(function()
401
                    {
402
                        // Re-initialize the Craft UI
403
                        Craft.initUiElements($spoonedFields);
404
                    }, this));
405
406
                }
407
408
            },
409
410
            onTabClick: function(ev)
411
            {
412
413
                ev.preventDefault();
414
                ev.stopPropagation();
415
416
                var $tab = $(ev.target),
417
                    $tabNav = $tab.parent().parent('.spoon-tabs'),
418
                    targetSelector = $tab.data('spooned-tab-target'),
419
                    $target = $(targetSelector);
420
421
                // Toggle tab nav state
422
                $tabNav.find('a.sel').removeClass('sel');
423
                $tab.addClass('sel');
424
425
                // Toggle the pane state
426
                $target.siblings('div').addClass('hidden');
427
                $target.removeClass('hidden');
428
429
            },
430
431
            initSettingsMenu: function($settingsBtn, spoonedBlockTypes, $matrixField)
432
            {
433
                Garnish.requestAnimationFrame($.proxy(function()
434
                {
435
                    // Get the Garnish.MenuBtn object
436
                    var menuBtn = $settingsBtn.data('menubtn') || false;
437
438
                    // If there wasn’t one then fail and try again
439
                    if (!menuBtn)
440
                    {
441
                        this.initSettingsMenu($settingsBtn, spoonedBlockTypes, $matrixField);
442
                        return;
443
                    }
444
445
                    // Get the field handle
446
                    var matrixFieldHandle = this._getMatrixFieldName($matrixField);
447
448
                    // Get the actual menu out of it once we get this far
449
                    var $menu = menuBtn.menu.$container;
450
                    $menu.addClass('spoon-settings-menu');
451
452
                    // Hide all the li’s with add block links in them
453
                    $menu.find('a[data-action="add"]').parents('li').addClass('hidden');
454
455
                    // Remove all the padded classes on hr’s
456
                    $menu.find('hr').removeClass('padded');
457
458
                    // Get the correct ul to play with in the menu container
459
                    var $origUl = $menu.find('a[data-action="add"]').parents('li').parent('ul');
460
461
                    // Loop the given block type data and adjust the menu to match the groups
462
                    for (var i = 0; i < spoonedBlockTypes.length; i++)
463
                    {
464
                        var handle = spoonedBlockTypes[i].matrixBlockType.handle;
465
466
                        // Make a new group ul if needed
467
                        if ( $menu.find('[data-spooned-group="'+spoonedBlockTypes[i].groupName+'"]').length === 0 )
468
                        {
469
                            var nestedSettingsHandles = $.grep(this.settings.nestedSettingsHandles, function(a){ return a === matrixFieldHandle; });
470
                            if (nestedSettingsHandles.length) {
471
                                var $newUl = $('<ul class="padded hidden" data-spooned-group="'+spoonedBlockTypes[i].groupName+'" />');
472
                                if (i!==0)
473
                                {
474
                                    $('<hr/>').insertBefore($origUl);
475
                                }
476
477
                                var $groupHeading = $('<a class="fieldtoggle">' + Craft.t('site', spoonedBlockTypes[i].groupName) + '</a>');
478
                                $groupHeading.insertBefore($origUl);
479
480
                                $newUl.insertBefore($origUl);
481
482
                                this.addListener($groupHeading, 'click', function(event) {
483
                                    var $trigger = $(event.currentTarget),
484
                                        $target = $trigger.next('ul');
485
486
                                    if ($target.hasClass('hidden')) {
487
                                        $target.removeClass('hidden');
488
                                        $trigger.addClass('expanded');
489
                                    } else {
490
                                        $target.addClass('hidden');
491
                                        $trigger.removeClass('expanded');
492
                                    }
493
                                });
494
                            } else {
495
                                var $newUl = $('<ul class="padded" data-spooned-group="'+spoonedBlockTypes[i].groupName+'" />');
0 ignored issues
show
Comprehensibility Naming Best Practice introduced by
The variable $newUl already seems to be declared on line 471. Consider using another variable name or omitting the var keyword.

This check looks for variables that are declared in multiple lines. There may be several reasons for this.

In the simplest case the variable name was reused by mistake. This may lead to very hard to locate bugs.

If you want to reuse a variable for another purpose, consider declaring it at or near the top of your function and just assigning to it subsequently so it is always declared.

Loading history...
496
                                if (i!==0)
497
                                {
498
                                    $('<hr/>').insertBefore($origUl);
499
                                }
500
                                $('<h6>' + Craft.t('site', spoonedBlockTypes[i].groupName) + '</h6>').insertBefore($origUl);
501
                                $newUl.insertBefore($origUl);
502
                            }
503
504
                        }
505
506
                        // Add the li
507
                        var $li = $menu.find('a[data-type="'+handle+'"]').parents('li');
508
509
                        $newUl.append($li);
0 ignored issues
show
Bug introduced by
The variable $newUl seems to not be initialized for all possible execution paths.
Loading history...
510
                        $li.removeClass('hidden');
511
                    }
512
513
                }, this));
514
            },
515
516
            /**
517
             * This simply returns a fieldHandle if it can get one or false if not
518
             */
519
            _getMatrixFieldName: function($matrixField)
520
            {
521
522
                var matrixFieldId = $matrixField.parentsUntil('.field').parent().prop('id'),
523
                    parts = matrixFieldId.split("-");
524
525
                // Matrix inside Something (e.g. Super Table) inside Matrix
526
                if (parts.length === 9) {
527
                    var matrixFieldHandle = parts[parts.length-8] + '-' + parts[parts.length-5] + '-' + parts[parts.length-2];
528
                }
529
                // Matrix inside Something (e.g. Super Table)
530
                else if (parts.length === 6) {
531
                    var matrixFieldHandle = parts[parts.length-5] + '-' + parts[parts.length-2];
0 ignored issues
show
Comprehensibility Naming Best Practice introduced by
The variable matrixFieldHandle already seems to be declared on line 527. Consider using another variable name or omitting the var keyword.

This check looks for variables that are declared in multiple lines. There may be several reasons for this.

In the simplest case the variable name was reused by mistake. This may lead to very hard to locate bugs.

If you want to reuse a variable for another purpose, consider declaring it at or near the top of your function and just assigning to it subsequently so it is always declared.

Loading history...
532
                }
533
                // Normal Matrix
534
                else if (parts.length === 3) {
535
                    var matrixFieldHandle = parts[parts.length-2];
0 ignored issues
show
Comprehensibility Naming Best Practice introduced by
The variable matrixFieldHandle already seems to be declared on line 527. Consider using another variable name or omitting the var keyword.

This check looks for variables that are declared in multiple lines. There may be several reasons for this.

In the simplest case the variable name was reused by mistake. This may lead to very hard to locate bugs.

If you want to reuse a variable for another purpose, consider declaring it at or near the top of your function and just assigning to it subsequently so it is always declared.

Loading history...
536
                }
537
538
                if ( matrixFieldHandle !== '' )
0 ignored issues
show
Bug introduced by
The variable matrixFieldHandle does not seem to be initialized in case parts.length === 3 on line 534 is false. Are you sure this can never be the case?
Loading history...
539
                {
540
                    return matrixFieldHandle;
541
                }
542
                else
543
                {
0 ignored issues
show
Comprehensibility introduced by
else is not necessary here since all if branches return, consider removing it to reduce nesting and make code more readable.
Loading history...
544
                    return false;
545
                }
546
            },
547
548
            /**
549
             * Returns the block type handle for a given $matrixBlock
550
             */
551
            _getMatrixBlockTypeHandle: function($matrixBlock)
552
            {
553
                var blockTypeHandle = $matrixBlock.data('type');
554
555
                if ( typeof blockTypeHandle == 'string' )
556
                {
557
                    return blockTypeHandle;
558
                }
559
                else
560
                {
0 ignored issues
show
Comprehensibility introduced by
else is not necessary here since all if branches return, consider removing it to reduce nesting and make code more readable.
Loading history...
561
                    return false;
562
                }
563
            }
564
565
        },
566
        {
567
            defaults: {
568
                blockTypes: null,
569
                context: false,
570
                versioned: false,
571
                nestedSettingsHandles: []
572
            }
573
        });
574
575
})(jQuery);
576