src/js/components/horizontal-scrollbar.js   A
last analyzed

Complexity

Total Complexity 25
Complexity/F 1.79

Size

Lines of Code 140
Function Count 14

Duplication

Duplicated Lines 140
Ratio 100 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
cc 0
c 1
b 0
f 1
nc 16
dl 140
loc 140
rs 10
wmc 25
mnd 2
bc 20
fnc 14
bpm 1.4285
cpm 1.7857
noi 5

8 Functions

Rating   Name   Duplication   Size   Complexity  
A Mivhak.component(ꞌhorizontal-scrollbarꞌ).methods.getDifference 4 4 1
B Mivhak.component(ꞌhorizontal-scrollbarꞌ).methods.doScroll 21 21 5
A Mivhak.component(ꞌhorizontal-scrollbarꞌ).methods.getEditorWidth 3 3 1
B Mivhak.component(ꞌhorizontal-scrollbarꞌ).methods.dragDealer 31 31 1
A Mivhak.component(ꞌhorizontal-scrollbarꞌ).methods.refresh 19 19 1
A Mivhak.component(ꞌhorizontal-scrollbarꞌ).methods.updateState 9 9 1
A Mivhak.component(ꞌhorizontal-scrollbarꞌ).methods.moveBar 5 5 1
A Mivhak.component(ꞌhorizontal-scrollbarꞌ).methods.initialize 13 13 2

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1 View Code Duplication
Mivhak.component('horizontal-scrollbar', {
0 ignored issues
show
Bug introduced by
The variable Mivhak seems to be never declared. If this is a global, consider adding a /** global: Mivhak */ 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...
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
2
    template: '<div class="mivhak-scrollbar mivhak-h-scrollbar"><div class="mivhak-scrollbar-thumb"></div></div>',
3
    props: {
4
        editor: null,
5
        $inner: null,
6
        $outer: null,
7
        mivhakInstance: null,
8
        minWidth: 50,
9
        state: {
10
            a: 0,    // The total width of the editor
11
            b: 0,    // The width of the viewport, excluding padding
12
            c: 0,    // The width of the viewport, including padding
13
            d: 0,    // The calculated width of the thumb
14
            l: 0     // The current left offset of the viewport
15
        },
16
        initialized: false
17
    },
18
    methods: {
19
        initialize: function() {
20
            if(!this.initialized)
21
            {
22
                this.initialized = true;
23
                this.dragDealer();
24
                var $this = this;
25
                $(window).resize(function(){
26
                    if(!$this.mivhakInstance.state.lineWrap)
27
                        $this.refresh();
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
28
                });
29
            }
30
            this.refresh();
31
        },
32
        updateState: function() {
33
            var oldState = $.extend({}, this.state);
34
            this.state.a = this.getEditorWidth();
35
            this.state.b = this.$outer.parent().width();
36
            this.state.c = this.state.b - this.mivhakInstance.options.padding*2;
37
            this.state.d = Math.max(this.state.c*this.state.b/this.state.a,this.minWidth);
38
            this.state.l *=  this.state.a/Math.max(oldState.a,1); // Math.max used to prevent division by zero
39
            return this.state.a !== oldState.a || this.state.b !== oldState.b;
40
        },
41
        refresh: function() {
42
            var $this = this, oldLeft = this.state.l;
43
            raf(function(){
44
                if($this.updateState())
45
                {
46
                    if($this.getDifference() > 0)
47
                    {
48
                        $this.doScroll('left',oldLeft-$this.state.l);
49
                        $this.$el.css({width: $this.state.d + 'px', left: 0});
50
                        $this.moveBar();
51
                    }
52
                    else 
53
                    {
54
                        $this.doScroll('left',$this.state.l);
55
                        $this.$el.css({width: 0});
56
                    }
57
                }
58
            });
59
        },
60
        dragDealer: function(){
61
            var $this = this,
62
                lastPageX;
63
64
            this.$el.on('mousedown.drag', function(e) {
65
                lastPageX = e.pageX;
66
                $this.$el.add(document.body).addClass('mivhak-scrollbar-grabbed');
67
                $(document).on('mousemove.drag', drag).on('mouseup.drag', stop);
68
                return false;
69
            });
70
71
            function drag(e){
72
                var delta = e.pageX - lastPageX,
73
                    didScroll;
74
75
                // Bail if the mouse hasn't moved
76
                if(!delta) return;
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
77
            
78
                lastPageX = e.pageX;
79
                
80
                raf(function(){
81
                    didScroll = $this.doScroll(delta > 0 ? 'right' : 'left', Math.abs(delta*$this.getEditorWidth()/$this.$outer.parent().width()));
82
                    if(0 !== didScroll) $this.moveBar();
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
83
                });
84
            }
85
86
            function stop() {
87
                $this.$el.add(document.body).removeClass('mivhak-scrollbar-grabbed');
88
                $(document).off("mousemove.drag mouseup.drag");
89
            }
90
        },
91
        moveBar: function() {
92
            this.$el.css({
93
                left:  (this.state.b-this.state.d)/(this.state.a-this.state.c)*this.state.l + 'px'
94
            });
95
        },
96
        
97
        /**
98
         * Scrolls the editor element in the direction given, provided that there 
99
         * is remaining scroll space
100
         * @param {string} dir
101
         * @param {int} delta
102
         */
103
        doScroll: function(dir, delta) {
104
            var s = this.state,
105
                remaining,
106
                didScroll;
107
            
108
            if('left' === dir) 
109
            {
110
                remaining = s.l;
111
                didScroll = remaining > 0 ? Math.min(remaining,delta) : 0;
112
                s.l -= didScroll;
113
            }
114
            if('right' === dir) 
115
            {
116
                remaining = this.getDifference() - s.l;
117
                didScroll = remaining > 0 ? Math.min(remaining,delta) : 0;
118
                s.l += didScroll;
119
            }
120
            
121
            this.$inner.find('.ace_content').css({'margin-left': -s.l});
122
            return didScroll;
0 ignored issues
show
Bug introduced by
The variable didScroll does not seem to be initialized in case "left" === dir on line 108 is false. Are you sure this can never be the case?
Loading history...
123
        },
124
        
125
        /**
126
         * Returns the difference between the containing div and the editor div
127
         */
128
        getDifference: function()
129
        {
130
            return this.state.a - this.state.c;
131
        },
132
        
133
        /**
134
         * Calculate the editor's width based on the number of lines
135
         */
136
        getEditorWidth: function() {
137
            return this.$inner.find('.ace_content').width();
138
        }
139
    }
140
});