form-collapsible-sections.js ➔ _getButtonContainer   F
last analyzed

Complexity

Conditions 20

Size

Total Lines 13
Code Lines 12

Duplication

Lines 13
Ratio 100 %

Importance

Changes 0
Metric Value
eloc 12
dl 13
loc 13
rs 0
c 0
b 0
f 0
cc 20

How to fix   Complexity   

Complexity

Complex classes like form-collapsible-sections.js ➔ _getButtonContainer 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
/*! Admin Page Framework - Form Collapsible Sections 1.0.1 */
2 View Code Duplication
( function( $ ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
3
4
    /** global: AdminPageFrameworkScriptFormMain */
5
    /** global: navigator */
6
7
    $( document ).ready( function() {
8
        $( this ).initializeAdminPageFrameworkCollapsibleSections();
9
    });
10
11
    /**
12
     * Gets triggered when a widget of the framework is saved.
13
     * @since    3.7.0
14
     */
15
    $( document ).on( 'admin-page-framework_saved_widget', function( event, oWidget ){
16
        $( oWidget ).initializeAdminPageFrameworkCollapsibleSections();
17
    });
18
19
    $.fn.initializeAdminPageFrameworkCollapsibleSections = function() {
20
21
        // Expand collapsible sections that are set not to collapse by default
22
        $( this ).find( '.admin-page-framework-collapsible-sections-title[data-is_collapsed=\"0\"]' )
23
            .next( '.admin-page-framework-collapsible-sections-content' )
24
            .slideDown( 'fast' );
25
        $( this ).find( '.admin-page-framework-collapsible-section-title[data-is_collapsed=\"0\"]' )
26
            .closest( '.admin-page-framework-section-table' )
27
            .find( 'tbody' )
28
            .slideDown( 'fast' );
29
30
        // Hide collapsible sections of 'section' containers as they are somehow do not get collapsed by default.
31
        $( this ).find( '.admin-page-framework-collapsible-section-title[data-is_collapsed=\"1\"]' )
32
            .closest( '.admin-page-framework-section-table' )
33
            .find( 'tbody' )
34
            .hide();
35
36
        // Bind the click event to the title element.
37
        $( this ).find( '.admin-page-framework-collapsible-sections-title, .admin-page-framework-collapsible-section-title' )
38
            .enableAdminPageFrameworkCollapsibleButton();
39
40
        // Insert the toggle all button.
41
        $( this ).find( '.admin-page-framework-collapsible-title[data-toggle_all_button!=\"0\"]' ).each( function(){$
42
43
            var _oThis        = $( this ); // to access from inside the below each() method.
44
            var _bForSections = $( this ).hasClass( 'admin-page-framework-collapsible-sections-title' );   // or for the 'section' container.
45
            var _isPositions  = $( this ).data( 'toggle_all_button' );
46
            _isPositions  = 1 === _isPositions
47
                ? 'top-right'   // default
48
                : _isPositions;
49
            var _aPositions   = 'string' === typeof _isPositions
50
                ? _isPositions.split( ',' )
51
                : [ 'top-right' ];
52
53
            var _oButton = _getButtonContainer();
54
55
            $.each( _aPositions, function( iIndex, _sPosition ) {
56
57
                // var _oButton = $( $_sToggleAllButtonHTML ); //@deprecated 3.9.0
58
                var _sLeftOrRight = -1 !== jQuery.inArray( _sPosition, [ 'top-right', 'bottom-right', '0' ] )   // if found
59
                    ? 'right'   // default
60
                    : 'left';
61
                _oButton.find( '.admin-page-framework-collapsible-toggle-all-button' ).css( 'float', _sLeftOrRight );
62
63
                var _sTopOrBottom = -1 !== jQuery.inArray( _sPosition, [ 'top-right', 'top-left', '0' ] )   // if found
64
                    ? 'before'   // default
65
                    : 'after';
66
67
                // Insert the button - there are two versions: for the sections container or the section container.
68
                if ( _bForSections ) {
69
                    var _oTargetElement = 'before' === _sTopOrBottom
70
                        ? _oThis
71
                        : _oThis.next( '.admin-page-framework-collapsible-content' );
72
                        _oTargetElement[ _sTopOrBottom ]( _oButton );
73
                } else {    // for 'section' containers
74
                    _oThis.closest( '.admin-page-framework-section' )[ _sTopOrBottom ]( _oButton );
75
                }
76
77
                // Expand or collapse this panel
78
                $( _oButton ).off( 'click' );       // for initially dropped (created) widgets
79
                _oButton.on( 'click', function(){
80
81
                    var _oButtons = _bForSections
82
                        ? $( this ).closest( '.admin-page-framework-sectionset' ).siblings().addBack().find( '> .admin-page-framework-collapsible-toggle-all-button-container' )
83
                        : $( this ).siblings( '.admin-page-framework-collapsible-toggle-all-button-container' ).addBack();
84
                    _oButtons.toggleClass( 'flipped' );
85
                    if ( _bForSections ) {
86
                        _oButton.parent().parent().children().children( '* > .admin-page-framework-collapsible-title' ).each( function() {
87
                            $( this ).trigger( 'click', [ 'by_toggle_all_button' ] );
88
                        } );
89
                    } else {
90
                        _oButton.closest( '.admin-page-framework-sections' ).children( '.admin-page-framework-section' ).children( '.admin-page-framework-section-table' ).children( 'caption' ).children( '.admin-page-framework-collapsible-title' ).each( function() {
91
                            $( this ).trigger( 'click', [ 'by_toggle_all_button' ] );
92
                        } );
93
                    }
94
95
                } );
96
97
            });
98
99
        } );
100
101
        /**
102
         * @since 3.9.0
103
         * @returns {*|define.amd.jQuery|HTMLElement}
104
         * @private
105
         */
106
        function _getButtonContainer() {
107
            var _sDashIconSort = $.fn.compareVersionNumbers( AdminPageFrameworkScriptFormMain.wpVersion, '3.8' ) >= 0
0 ignored issues
show
Bug introduced by
The variable AdminPageFrameworkScriptFormMain seems to be never declared. If this is a global, consider adding a /** global: AdminPageFrameworkScriptFormMain */ 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...
108
                ? 'dashicons dashicons-sort'
109
                : '';
110
            var _sButtonText   = _sDashIconSort ? '' : AdminPageFrameworkScriptFormMain.messages.toggleAll;
111
            var _oButtonInner = $( '<span class="admin-page-framework-collapsible-toggle-all-button button"></span>' );
112
            _oButtonInner.addClass( _sDashIconSort );
113
            _oButtonInner.attr( 'title', AdminPageFrameworkScriptFormMain.messages.toggleAllCollapsibleSections );
114
            _oButtonInner.text( _sButtonText );
115
            var _oButton = $( '<div class="admin-page-framework-collapsible-toggle-all-button-container"></div>' );
116
            _oButton.append( _oButtonInner );
117
            return _oButton;
118
        }
119
120
    }
121
    /**
122
     * Binds the click event to collapsible buttons.
123
     */
124
    $.fn.enableAdminPageFrameworkCollapsibleButton = function() {
125
126
        /**
127
         * Determines whether the passed node element is of a field element.
128
         * If there are fields in the section title area, clicking on those field elements should not collapse/expand the section.
129
         * @return  boolean
130
         */
131
        function _isFieldElement( nodeTarget ) {
132
133
            if ( $( nodeTarget ).hasClass( 'admin-page-framework-collapsible-button' ) ) {
134
                return false;
135
            }
136
            var _sClickedTag = $( nodeTarget ).prop( 'tagName' ).toLowerCase();
137
            if ( -1 !== jQuery.inArray( _sClickedTag, [ 'input', 'label', 'fieldset', 'span' ] ) ) {
138
                return true;
139
            }
140
            return false;
141
142
        }
143
144
        /**
145
         * Unbind the event first.
146
         * This is for widgets as the initial model widgets placed on the left side is dragged-and-dropped to a sidebar definition container.
147
         * Then the event binding will be lost so it needs to be rebound.
148
         */
149
        $( this ).off( 'click' );
150
        $( this ).on( 'click', function( event, sContext ){
151
152
            if ( _isFieldElement( event.target ) ) {
153
                return true;
154
            }
155
156
            // Expand or collapse this panel
157
            var _oThis = $( this );
158
            var _sContainerType = $( this ).hasClass( 'admin-page-framework-collapsible-sections-title' )
159
                ? 'sections'
160
                : 'section';
161
            var _oTargetContent = 'sections' === _sContainerType
162
                ? $( this ).next( '.admin-page-framework-collapsible-content' ).first()
163
                : $( this ).parent().siblings( 'tbody' );
164
            var _sAction = _oTargetContent.is( ':visible' ) ? 'collapse' : 'expand';
165
166
            _oThis.removeClass( 'collapsed' );
167
            _oTargetContent.slideToggle( 'fast', function(){
168
169
                // For Google Chrome, table-caption will animate smoothly for the 'section' containers (not 'sections' container). For FireFox, 'block' is required. For IE both works.
170
                var _bIsChrome = navigator.userAgent.toLowerCase().indexOf('chrome') > -1;
0 ignored issues
show
Bug introduced by
The variable navigator seems to be never declared. If this is a global, consider adding a /** global: navigator */ 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...
171
                if ( 'expand' === _sAction && 'section' === _sContainerType && ! _bIsChrome ) {
172
                    _oTargetContent.css( 'display', 'block' );
173
                }
174
175
                // Update the class selector.
176
                if ( _oTargetContent.is( ':visible' ) ) {
177
                    _oThis.removeClass( 'collapsed' );
178
                } else {
179
                    _oThis.addClass( 'collapsed' );
180
                }
181
182
            } );
183
184
            // If it is triggered from the toggle all button, do not continue.
185
            if ( 'by_toggle_all_button' === sContext ) {
186
                return;
0 ignored issues
show
Comprehensibility Best Practice introduced by
Are you sure this return statement is not missing an argument? If this is intended, consider adding an explicit undefined like return undefined;.
Loading history...
187
            }
188
189
            // If collapse_others_on_expand argument is true, collapse others
190
            if ( 'expand' === _sAction && _oThis.data( 'collapse_others_on_expand' ) ) {
0 ignored issues
show
Complexity Best Practice introduced by
There is no return statement if "expand" === _sAction &&...apse_others_on_expand") 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...
191
                _oThis.parent().parent().children().children( '* > .admin-page-framework-collapsible-content' ).not( _oTargetContent ).slideUp( 'fast', function() {
192
                    $( this ).prev( '.admin-page-framework-collapsible-title' ).addClass( 'collapsed' );
193
                });
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...
194
            }
195
196
        });
197
        
198
    }
199
}( jQuery ));