Passed
Push — master ( f76276...ca99e2 )
by Stiofan
03:29
created

assets/js/invoice-front.js   F

Complexity

Total Complexity 77
Complexity/F 3.08

Size

Lines of Code 343
Function Count 25

Duplication

Duplicated Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
nc 1536
dl 0
loc 343
rs 3.8125
c 1
b 0
f 0
wmc 77
mnd 4
bc 70
fnc 25
bpm 2.8
cpm 3.08
noi 26

5 Functions

Rating   Name   Duplication   Size   Complexity  
A invoice-front.js ➔ wpinvBlock 0 11 3
B invoice-front.js ➔ jQuery 0 259 1
A invoice-front.js ➔ wpinvUnblock 0 3 1
C invoice-front.js ➔ wpinvRemoveQueryVar 0 32 8
B invoice-front.js ➔ wpi_buy 0 25 1

How to fix   Complexity   

Complexity

Complex classes like assets/js/invoice-front.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
// make sure ajaxurl is defined
2
if (typeof ajaxurl === 'undefined' || ajaxurl === null) {
0 ignored issues
show
Bug introduced by
The variable ajaxurl seems to be never declared. If this is a global, consider adding a /** global: ajaxurl */ 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...
3
    // variable is undefined or null
4
    ajaxurl = WPInv.ajax_url;
0 ignored issues
show
Bug introduced by
The variable WPInv seems to be never declared. If this is a global, consider adding a /** global: WPInv */ 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...
Bug introduced by
The variable ajaxurl 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.ajaxurl.
Loading history...
5
}
6
window.wpiSubmit = typeof window.wpiSubmit !== 'undefined' ? window.wpiSubmit : true;
7
jQuery(function($) {
8
    var valid = false;
9
    $('#wpinv_checkout_form').on('submit', function(e) {
10
        var $form = $(this).closest('#wpinv_checkout_form');
11
        $('.wpinv_errors').remove();
12
        if (valid) {
13
            return true;
14
        }
15
        e.preventDefault();
16
        wpinvBlock($form);
17
        var data = $form.serialize();
18
        data = wpinvRemoveQueryVar(data, 'action');
19
        data = wpinvRemoveQueryVar(data, 'wpinv_ajax');
20
        $.post(ajaxurl, data + '&action=wpinv_checkout', function(res) {
0 ignored issues
show
Bug introduced by
The variable ajaxurl does not seem to be initialized in case typeof ajaxurl === "und...ed" || ajaxurl === null on line 2 is false. Are you sure the function post handles undefined variables?
Loading history...
21
            if (res && typeof res == 'object' && res.success) {
22
                valid = true;
23
                var data = new Object();
24
                data.form = $form;
25
                data.totals = res.data;
26
                jQuery('body').trigger('wpinv_checkout_submit', data);
27
                if (window.wpiSubmit) {
28
                    $form.submit();
29
                }
30
            } else {
31
                $form.unblock();
32
                if (res && res.search("wpinv_adddress_confirm") !== -1) {
33
                    $('#wpinv_adddress_confirm').show();
34
                }
35
                $('#wpinv_purchase_submit', $form).before(res);
36
            }
37
        });
38
        return false;
39
    });
40
    var elB = $('#wpinv-fields');
41
    $('#wpinv_country', elB).change(function(e) {
0 ignored issues
show
Unused Code introduced by
The parameter e 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...
42
        $('.wpinv_errors').remove();
43
        wpinvBlock(jQuery('#wpinv_state_box'));
44
        var $this = $(this);
0 ignored issues
show
Unused Code introduced by
The variable $this seems to be never used. Consider removing it.
Loading history...
45
        data = {
0 ignored issues
show
Bug introduced by
The variable data 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.data.
Loading history...
46
            action: 'wpinv_get_states_field',
47
            country: $(this).val(),
48
            field_name: 'wpinv_state',
49
        };
50
        $.post(ajaxurl, data, function(response) {
0 ignored issues
show
Bug introduced by
The variable ajaxurl does not seem to be initialized in case typeof ajaxurl === "und...ed" || ajaxurl === null on line 2 is false. Are you sure the function post handles undefined variables?
Loading history...
51
            if ('nostates' === response) {
52
                var text_field = '<input type="text" required="required" class="wpi-input required" id="wpinv_state" name="wpinv_state">';
53
                $('#wpinv_state', elB).replaceWith(text_field);
54
            } else {
55
                $('#wpinv_state', elB).replaceWith(response);
56
                var changeState = function() {
57
                    console.log('69 : wpinv_recalculate_taxes(' + $(this).val() + ')');
0 ignored issues
show
Debugging Code introduced by
console.log looks like debug code. Are you sure you do not want to remove it?
Loading history...
58
                    wpinv_recalculate_taxes($(this).val());
59
                };
60
                $("#wpinv_state").unbind("change", changeState);
61
                $("#wpinv_state").bind("change", changeState);
62
            }
63
            $('#wpinv_state', elB).find('option[value=""]').remove();
64
            $('#wpinv_state', elB).addClass('form-control wpi-input required');
65
        }).done(function(data) {
0 ignored issues
show
Unused Code introduced by
The parameter data 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...
66
            jQuery('#wpinv_state_box').unblock();
67
            console.log('78 : wpinv_recalculate_taxes()');
0 ignored issues
show
Debugging Code introduced by
console.log looks like debug code. Are you sure you do not want to remove it?
Loading history...
68
            wpinv_recalculate_taxes();
69
        });
70
        return false;
71
    });
72
    $('select#wpinv_state', elB).change(function(e) {
0 ignored issues
show
Unused Code introduced by
The parameter e 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...
73
        $('.wpinv_errors').remove();
74
        console.log('86 : wpinv_recalculate_taxes()');
0 ignored issues
show
Debugging Code introduced by
console.log looks like debug code. Are you sure you do not want to remove it?
Loading history...
75
        wpinv_recalculate_taxes($(this).val());
76
    });
77
    var WPInv_Checkout = {
78
        checkout_form: $('form#wpinv_checkout_form'),
79
        init: function() {
80
            if (!$(this.checkout_form).length) {
81
                return;
82
            }
83
            // Payment methods
84
            this.checkout_form.on('click', 'input[name="wpi-gateway"]', this.payment_method_selected);
85
            this.init_payment_methods();
86
            //this.recalculate_taxes();
87
        },
88
        init_payment_methods: function() {
89
            var $checkout_form = this.checkout_form;
90
            var $payment_methods = $('.wpi-payment_methods input[name="wpi-gateway"]');
91
            // If there is one method, we can hide the radio input
92
            if (1 === $payment_methods.length) {
93
                $payment_methods.eq(0).hide();
94
            }
95
            // If there are none selected, select the first.
96
            if (0 === $payment_methods.filter(':checked').length) {
97
                $payment_methods.eq(0).prop('checked', true);
98
            }
99
            // Trigger click event for selected method
100
            $payment_methods.filter(':checked').eq(0).trigger('click');
101
            // Validate and apply a discount
102
            $checkout_form.on('click', '#wpi-apply-discount', this.applyDiscount);
103
            // Prevent the checkout form from submitting when hitting enter key in the discount field
104
            $checkout_form.on('keypress', '#wpinv_discount_code', function(event) {
105
                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...
106
                    return false;
107
                }
108
            });
109
            // Apply the discount when hitting enter key in the discount field instead
110
            $checkout_form.on('keyup', '#wpinv_discount_code', function(event) {
111
                if (event.keyCode == '13') {
112
                    $('#wpi-apply-discount', $checkout_form).trigger('click');
113
                }
114
            });
115
            // Remove a discount
116
            $(document.body).on('click', '.wpi-discount-remove', this.removeDiscount);
117
        },
118
        payment_method_selected: function() {
119
            if ($('.wpi-payment_methods input.wpi-pmethod').length > 1) {
120
                var target_payment_box = $('div.payment_box.' + $(this).attr('ID'));
121
                if ($(this).is(':checked') && !target_payment_box.is(':visible')) {
122
                    $('div.payment_box').filter(':visible').slideUp(250);
123
                    if ($(this).is(':checked')) {
124
                        var content = $('div.payment_box.' + $(this).attr('ID')).html();
125
                        content = content ? content.trim() : '';
126
                        if (content) {
127
                            $('div.payment_box.' + $(this).attr('ID')).slideDown(250);
128
                        }
129
                    }
130
                }
131
            } else {
132
                $('div.payment_box').show();
133
            }
134
            $('#wpinv_payment_mode_select').attr('data-gateway', $(this).val());
135
            if ($(this).data('button-text')) {
136
                $('#wpinv-payment-button').val($(this).data('button-text'));
137
            } else {
138
                $('#wpinv-payment-button').val($('#wpinv-payment-button').data('value'));
139
            }
140
        },
141
        applyDiscount: function(e) {
142
            e.preventDefault();
143
            var $this = $(this),
144
                $box = $this.closest('.panel-body'),
145
                discount_code = $('#wpinv_discount_code', $box).val(),
146
                $msg = $('.wpinv-discount-msg', $box),
147
                $msgS = $('.alert-success', $msg),
148
                $msgF = $('.alert-error', $msg);
149
            if (discount_code == '') {
150
                $('#wpinv_discount_code', $box).focus();
151
                return false;
152
            }
153
            var data = {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
154
                action: 'wpinv_apply_discount',
155
                code: discount_code,
156
                _nonce: WPInv.nonce
0 ignored issues
show
Bug introduced by
The variable WPInv seems to be never declared. If this is a global, consider adding a /** global: WPInv */ 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...
157
            };
158
            $('.wpinv_errors').remove();
159
            $msg.hide();
160
            $msgS.hide().find('.wpi-msg').html('');
161
            $msgF.hide().find('.wpi-msg').html('');
162
            wpinvBlock($box);
163
            $.ajax({
164
                type: "POST",
165
                data: data,
166
                dataType: "json",
167
                url: WPInv.ajax_url,
168
                xhrFields: {
169
                    withCredentials: true
170
                },
171
                success: function(res) {
172
                    wpinvUnblock($box);
173
                    var success = false;
174
                    if (res && typeof res == 'object') {
175
                        if (res.success) {
176
                            success = true;
177
                            jQuery('#wpinv_checkout_cart_form', $this.checkout_form).replaceWith(res.data.html);
178
                            jQuery('.wpinv-chdeckout-total').text(res.data.total);
179
                            $('#wpinv_discount_code', $box).val('');
180
                            //console.log('217 : wpinv_recalculate_taxes()');
181
                            //wpinv_recalculate_taxes();
182
                            if (res.data.free) {
183
                                $('#wpinv_payment_mode_select', $this.checkout_form).hide();
184
                                gw = 'manual';
0 ignored issues
show
Bug introduced by
The variable gw 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.gw.
Loading history...
185
                            } else {
186
                                $('#wpinv_payment_mode_select', $this.checkout_form).show();
187
                                gw = $('#wpinv_payment_mode_select', $this.checkout_form).attr('data-gateway');
188
                            }
189
                            $('.wpi-payment_methods .wpi-pmethod[value="' + gw + '"]', $this.checkout_form).prop('checked', true);
190
                            $(document.body).trigger('wpinv_discount_applied', [res]);
191
                        }
192
                        if (res.msg) {
193
                            $msg.show();
194
                            if (success) {
195
                                $msgS.show().find('.wpi-msg').html(res.msg);
196
                            } else {
197
                                $msgF.show().find('.wpi-msg').html(res.msg);
198
                            }
199
                        }
200
                    }
201
                }
202
            }).fail(function(res) {
203
                wpinvUnblock($box);
204
                if (window.console && window.console.log) {
205
                    console.log(res);
0 ignored issues
show
Debugging Code introduced by
console.log looks like debug code. Are you sure you do not want to remove it?
Loading history...
206
                }
207
            });
208
            return false;
209
        },
210
        removeDiscount: function(e) {
211
            e.preventDefault();
212
            var $this = $(this),
213
                $block = $this.closest('#wpinv_checkout_cart_wrap'),
214
                discount_code = $this.data('code');
215
            if (discount_code == '') {
216
                return false;
217
            }
218
            var data = {
219
                action: 'wpinv_remove_discount',
220
                code: discount_code,
221
                _nonce: WPInv.nonce
0 ignored issues
show
Bug introduced by
The variable WPInv seems to be never declared. If this is a global, consider adding a /** global: WPInv */ 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...
222
            };
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
223
            wpinvBlock($block);
224
            $.ajax({
225
                type: "POST",
226
                data: data,
227
                dataType: "json",
228
                url: WPInv.ajax_url,
229
                xhrFields: {
230
                    withCredentials: true
231
                },
232
                success: function(res) {
233
                    if (res && typeof res == 'object') {
234
                        if (res.success) {
235
                            jQuery('#wpinv_checkout_cart_form', $this.checkout_form).replaceWith(res.data.html);
236
                            jQuery('.wpinv-chdeckout-total').text(res.data.total);
237
                            if (res.data.free) {
238
                                $('#wpinv_payment_mode_select', $this.checkout_form).hide();
239
                                gw = 'manual';
0 ignored issues
show
Bug introduced by
The variable gw 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.gw.
Loading history...
240
                            } else {
241
                                $('#wpinv_payment_mode_select', $this.checkout_form).show();
242
                                gw = $('#wpinv_payment_mode_select', $this.checkout_form).attr('data-gateway');
243
                            }
244
                            $('input[name="wpi-gateway"][value="' + gw + '"]', $this.checkout_form).prop('checked', true);
245
                            //console.log('291 : wpinv_recalculate_taxes()');
246
                            //wpinv_recalculate_taxes();
247
                            $(document.body).trigger('wpinv_discount_removed', [res]);
248
                        }
249
                    }
250
                }
251
            }).fail(function(res) {
252
                wpinvUnblock($block);
253
                if (window.console && window.console.log) {
254
                    console.log(res);
0 ignored issues
show
Debugging Code introduced by
console.log looks like debug code. Are you sure you do not want to remove it?
Loading history...
255
                }
256
            });
257
            return false;
258
        },
259
        recalculate_taxes: function() {
260
            console.log('308 : wpinv_recalculate_taxes()');
0 ignored issues
show
Debugging Code introduced by
console.log looks like debug code. Are you sure you do not want to remove it?
Loading history...
261
            wpinv_recalculate_taxes();
262
        }
263
    }
264
    WPInv_Checkout.init();
265
});
266
267
function wpinvBlock(el, message) {
268
    message = typeof message != 'undefined' && message !== '' ? '&nbsp;' + message : '';
269
    el.block({
270
        message: '<i class="fa fa-refresh fa-spin"></i>' + message,
271
        overlayCSS: {
272
            background: '#fff',
273
            opacity: 0.6
274
        },
275
        ignoreIfBlocked: true
276
    });
277
}
278
279
function wpinvUnblock(el) {
280
    el.unblock();
281
}
282
283
function wpinvRemoveQueryVar(url, parameter) {
284
    //prefer to use l.search if you have a location/link object
285
    var urlparts = url.split('?');
286
    var urlparts2 = url.split('&');
287
    if (urlparts.length >= 2) {
288
        var prefix = encodeURIComponent(parameter) + '=';
289
        var pars = urlparts[1].split(/[&;]/g);
290
        //reverse iteration as may be destructive
291
        for (var i = pars.length; i-- > 0;) {
292
            //idiom for string.startsWith
293
            if (pars[i].lastIndexOf(prefix, 0) !== -1) {
294
                pars.splice(i, 1);
295
            }
296
        }
297
        url = urlparts[0] + (pars.length > 0 ? '?' + pars.join('&') : "");
298
        return url;
299
    } else if (urlparts2.length >= 2) {
300
        var prefix = encodeURIComponent(parameter) + '=';
0 ignored issues
show
Comprehensibility Naming Best Practice introduced by
The variable prefix already seems to be declared on line 288. 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...
301
        var pars = url.split(/[&;]/g);
0 ignored issues
show
Comprehensibility Naming Best Practice introduced by
The variable pars already seems to be declared on line 289. 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...
302
        //reverse iteration as may be destructive
303
        for (var i = pars.length; i-- > 0;) {
0 ignored issues
show
Comprehensibility Naming Best Practice introduced by
The variable i already seems to be declared on line 291. 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...
304
            //idiom for string.startsWith
305
            if (pars[i].lastIndexOf(prefix, 0) !== -1) {
306
                pars.splice(i, 1);
307
            }
308
        }
309
        url = pars.join('&');
310
        return url;
311
    } else {
312
        return url;
313
    }
314
}
315
316
/**
317
 * Allow a invoice to be created for items via ajax.
318
 * @param items This is a comma separated and pipe separated for quantity eg:  item_id|quantity,item_id|quantity,item_id|quantity
319
 */
320
function wpi_buy(items,$post_id){
321
    var $nonce = jQuery('#wpinv_buy_nonce').val();
322
    jQuery.ajax({
323
        url : ajaxurl,
0 ignored issues
show
Bug introduced by
The variable ajaxurl does not seem to be initialized in case typeof ajaxurl === "und...ed" || ajaxurl === null on line 2 is false. Are you sure this can never be the case?
Loading history...
324
        type : 'post',
325
        data : {
326
            action : 'wpinv_buy_items',
327
            items : items,
328
            post_id : $post_id,
329
            wpinv_buy_nonce : $nonce
330
        },
331
        success : function( res ) {
332
            console.log(res);
0 ignored issues
show
Debugging Code introduced by
console.log looks like debug code. Are you sure you do not want to remove it?
Loading history...
333
            if (typeof res == 'object' && res) {
334
                if (res.success) {
335
                    window.location.href = res.success;
336
                    return;
337
                }
338
                if (res.error) {
339
                    alert(res.error);
340
                }
341
            }
342
        }
343
    });
344
}