Code Duplication    Length = 140-148 lines in 2 locations

src/js/components/vertical-scrollbar.js 1 location

@@ 1-148 (lines=148) @@
1
Mivhak.component('vertical-scrollbar', {
2
    template: '<div class="mivhak-scrollbar mivhak-v-scrollbar"><div class="mivhak-scrollbar-thumb"></div></div>',
3
    props: {
4
        editor: null,
5
        $inner: null,
6
        $outer: null,
7
        mivhakInstance: null,
8
        minHeight: 50,
9
        state: {
10
            a: 0,    // The total height of the editor
11
            b: 0,    // The height of the viewport, excluding padding
12
            c: 0,    // The height of the viewport, including padding
13
            d: 0,    // The calculated thumb height
14
            t: 0     // The current top 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
                this.$inner.on('mousewheel', function(e){$this.onScroll.call(this, e);});
26
                $(window).resize(function(){
27
                    if($this.mivhakInstance.state.lineWrap)
28
                        $this.refresh();
29
                });
30
            }
31
            // Refresh anytime initialize is called
32
            this.refresh();
33
        },
34
        updateState: function() {
35
            var oldState = $.extend({}, this.state);
36
            this.state.a = getEditorHeight(this.$inner);
37
            this.state.b = this.mivhakInstance.state.height;
38
            this.state.c = this.mivhakInstance.state.height-this.mivhakInstance.options.padding*2;
39
            this.state.d = Math.max(this.state.c*this.state.b/this.state.a,this.minHeight);
40
            this.state.t *=  this.state.a/Math.max(oldState.a,1); // Math.max used to prevent division by zero
41
            return this.state.a !== oldState.a || this.state.b !== oldState.b;
42
        },
43
        refresh: function() {
44
            var $this = this, oldTop = this.state.t;
45
            raf(function(){
46
                if($this.updateState())
47
                {
48
                    if($this.getDifference() > 0)
49
                    {
50
                        $this.doScroll('up',oldTop-$this.state.t);
51
                        $this.$el.css({height: $this.state.d + 'px', top: 0});
52
                        $this.moveBar();
53
                    }
54
                    else 
55
                    {
56
                        $this.doScroll('up',$this.state.t);
57
                        $this.$el.css({height: 0});
58
                    }
59
                }
60
            });
61
        },
62
        onScroll: function(e) {
63
            var didScroll;
64
            
65
            if(e.deltaY > 0)
66
                didScroll = this.doScroll('up',e.deltaY*e.deltaFactor);
67
            else
68
                didScroll = this.doScroll('down',-e.deltaY*e.deltaFactor);
69
            
70
            if(0 !== didScroll) {
71
                this.moveBar();
72
                e.preventDefault(); // Only prevent page scroll if the editor can be scrolled
73
            }
74
        },
75
        dragDealer: function(){
76
            var $this = this,
77
                lastPageY;
78
79
            this.$el.on('mousedown.drag', function(e) {
80
                lastPageY = e.pageY;
81
                $this.$el.add(document.body).addClass('mivhak-scrollbar-grabbed');
82
                $(document).on('mousemove.drag', drag).on('mouseup.drag', stop);
83
                return false;
84
            });
85
86
            function drag(e){
87
                var delta = e.pageY - lastPageY,
88
                    didScroll;
89
            
90
                // Bail if the mouse hasn't moved
91
                if(!delta) return;
92
            
93
                lastPageY = e.pageY;
94
                
95
                raf(function(){
96
                    didScroll = $this.doScroll(delta > 0 ? 'down' : 'up', Math.abs(delta*getEditorHeight($this.$inner)/$this.$outer.parent().height()));
97
                    if(0 !== didScroll) $this.moveBar();
98
                });
99
            }
100
101
            function stop() {
102
                $this.$el.add(document.body).removeClass('mivhak-scrollbar-grabbed');
103
                $(document).off("mousemove.drag mouseup.drag");
104
            }
105
        },
106
        moveBar: function() {
107
            this.$el.css({
108
                top:  (this.state.b-this.state.d)/(this.state.a-this.state.c)*this.state.t + 'px'
109
            });
110
        },
111
        
112
        /**
113
         * Scrolls the editor element in the direction given, provided that there 
114
         * is remaining scroll space
115
         * @param {string} dir
116
         * @param {int} delta
117
         */
118
        doScroll: function(dir, delta) {
119
            var s = this.state,
120
                remaining,
121
                didScroll;
122
            
123
            if('up' === dir) 
124
            {
125
                remaining = s.t;
126
                didScroll = remaining > 0 ? Math.min(remaining,delta) : 0;
127
                s.t -= didScroll;
128
            }
129
            if('down' === dir) 
130
            {
131
                remaining = this.getDifference() - s.t;
132
                didScroll = remaining > 0 ? Math.min(remaining,delta) : 0;
133
                s.t += didScroll;
134
            }
135
            
136
            this.$inner.css({top: -s.t});
137
            return didScroll;
138
        },
139
        
140
        /**
141
         * Returns the difference between the containing div and the editor div
142
         */
143
        getDifference: function()
144
        {
145
            return this.state.a - this.state.c;
146
        }
147
    }
148
});

src/js/components/horizontal-scrollbar.js 1 location

@@ 1-140 (lines=140) @@
1
Mivhak.component('horizontal-scrollbar', {
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();
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;
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();
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;
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
});