13693261870
2022-09-16 354b3dbfbffb3df45212a2a44dbbf48b4acc2594
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
<!DOCTYPE html>
<html>
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  <title>The source code</title>
  <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
  <script type="text/javascript" src="../resources/prettify/prettify.js"></script>
  <style type="text/css">
    .highlight { display: block; background-color: #ddd; }
  </style>
  <script type="text/javascript">
    function highlight() {
      document.getElementById(location.hash.replace(/#/, "")).className = "highlight";
    }
  </script>
</head>
<body onload="prettyPrint(); highlight();">
  <pre class="prettyprint lang-js">Ext.define('Ext.rtl.dom.Element_scroll', {
    override: 'Ext.dom.Element',
 
    rtlGetScroll: function() {
        var me = this,
            dom = me.dom,
            doc = document,
            body = doc.body,
            scroll = me.getScroll(),
            // The left value returned from getScroll() may be a negative number.  In rtl
            // mode left should always be reported as a positive number of pixels from the
            // right, so use the absolute value of left.
            left = Math.abs(scroll.left),
            isDocOrBody = (dom === doc || dom === body);
 
        if (isDocOrBody ? (3 &amp; me._rtlDocScrollFlag) : (me._rtlScrollFlag === 1)) {
            // If the browser reports scrollLeft as the number of pixels from left
            // (same as ltr) we need to convert it to a rtl position by subtracting it
            // from scrollWidth
            if (isDocOrBody) {
                dom = body;
            }
            
            left = dom.scrollWidth - left -
                (isDocOrBody ? Ext.Element.getViewportWidth() : dom.clientWidth);
        }
        scroll.left = left;
 
        return scroll;
    },
    
    rtlGetScrollLeft: function() {
        return this.rtlGetScroll().left;
    },
    
    rtlSetScrollLeft: function(left){
        var me = this;
 
        me.dom.scrollLeft = me.rtlNormalizeScrollLeft(left);
        return me;
    },
 
    rtlScrollTo: function(side, value, animate) {
        if (side === 'left') {
            value = this.rtlNormalizeScrollLeft(value);
        }
 
        return this.scrollTo(side, value, animate);
    },
 
    rtlScrollBy: function(deltaX, deltaY, animate) {
        var me = this,
            dom = me.dom,
            left, maxScroll;
 
        // Extract args if deltas were passed as an Array.
        if (deltaX.length) {
            animate = deltaY;
            deltaY = deltaX[1];
            deltaX = deltaX[0];
        } else if (typeof deltaX != 'number') { // or an object
            animate = deltaY;
            deltaY = deltaX.y;
            deltaX = deltaX.x;
        }
       
        if (deltaX) {
            left = me.rtlNormalizeScrollLeft(
                me.constrainScrollLeft(me.rtlGetScrollLeft() + deltaX)
            ); 
 
            me.scrollTo('left', left, animate);
        }
        if (deltaY) {
            me.scrollTo('top', me.constrainScrollTop(dom.scrollTop + deltaY), animate);
        }
 
        return me;
    },
 
    rtlScroll: function(direction, distance, animate) {
        if (!this.isScrollable()) {
            return false;
        }
        var me = this,
            side = direction === 'r' || direction === 'l' ? 'left' : 'top',
            scrolled = false,
            currentScroll, constrainedScroll;
 
        if (direction === 'r') {
            distance = -distance;
        }
 
        if (side === 'left') {
            currentScroll = me.rtlGetScrollLeft();
            constrainedScroll = me.constrainScrollLeft(currentScroll + distance);
        } else {
            currentScroll = me.dom.scrollTop;
            constrainedScroll = me.constrainScrollTop(currentScroll + distance);
        }
 
        if (constrainedScroll !== currentScroll) {
            this.rtlScrollTo(side, constrainedScroll, animate);
            scrolled = true;
        }
 
        return scrolled;
    },
 
    rtlNormalizeScrollLeft: function(left){
        var dom = this.dom,
            flag = this._rtlScrollFlag;
            
        if (flag === 0) {
            left = -left;
        } else if (flag === 1) {
            left = dom.scrollWidth - left - dom.clientWidth;
        }
        return left;
    }
    
}, function() {
    var Element = this;
 
    /*
     * Sets a _rtlScrollFlag property on the Element class prototype indicating how the
     * browser reports scrollLeft on overflowing rtl elements.  This method cannot be used
     * reliably on the documentElement or document.body because the behavior of these
     * elements can be different from other elements in some browsers.
     * 
     * 0: offset from right (negative number) - firefox
     * 1: offset from left (positive number) - IE6, IE7, IE6 - IE9 quirks, and Webkit
     * 2: offset from right (positive number) - IE8 - IE10 &amp; IE10 quirks
     */
    function cacheRtlScrollFlag() {
        var el = Ext.getBody().createChild({
            tag: 'div',
            style: 'direction:rtl;position:absolute;overflow:auto;height:100px;width:100px;',
            children: [{
                tag: 'div',
                style: 'height:30px;width:150px;'
            }]
        }),
        dom = el.dom,
        flag = 2;
 
        if (dom.scrollLeft === 50) {
            flag = 1;
        } else {
            dom.scrollLeft = -1;
            if (dom.scrollLeft) {
                flag = 0;
            }
        }
 
        el.remove();
        Element.prototype._rtlScrollFlag = flag;
    }
 
    /*
     * scrollLeft on the document/body is reported differently from ordinary
     * overflowing elements in many browsers (see getRtlScrollFlag).There are 2
     * separate things we have to detect:
     * 1. The element that overflows - when the document overflows some browsers
     * set scrollLeft on the document body (webkit and IE quirks), while other
     * browsers set scrollLeft on the documentElement (all other supported browsers
     * at the time of this writing).
     * 2. The scrollLeft of the overflowing document/body can be one of the
     * following:
     *    a. number of pixels offset from right expressed as a negative number
     *       (Webkit, Firefox)
     *    b. number of pixels offset from right expressed as a positive number
     *       (IE8 - IE10 strict mode, and IE10 quirks mode.
     *    c. number of pixels offset from left expressed as a positive number
     *       (IE6 - IE9 quirks mode, and IE6/IE7 strict mode.
     *
     * The following logic feture detects the handling of scrollLeft and sets the 
     * _rtlDocScrollFlag property on this class' prototype as a bit flag which has 
     * the following values:
     * 
     * 0 - docEl, negative right
     * 1 - docEl, positive left
     * 2 - docEl, positive right
     * 4 - body, negative right
     * 5 - body, positive left
     */
    function cacheRtlDocScrollFlag() {
        var doc = document,
            docEl = doc.documentElement,
            body = doc.body,
            // flag defaults to body, negative right (webkit) so no detection needed
            // is needed for this scenario
            flag = 4,
            bodyStyle = body.style,
            // save the direction property so we can set it back when we are done.
            direction = bodyStyle.direction,
            el = Ext.getBody().createChild(
                '&lt;div style=&quot;height:20000px;width:20000px;&quot;&gt;&lt;/div&gt;'
            ), 
            dom = el.dom,
            ltrRight, rtlRight
 
        bodyStyle.direction = 'ltr';
        ltrRight = dom.getBoundingClientRect().right;
 
        bodyStyle.direction = 'rtl';
        rtlRight = dom.getBoundingClientRect().right;
        
        // when the body has vertical overflow some browser continue to show the
        // vertical scrollbar on the right side of the page even in rtl mode.
        Element.prototype._rtlBodyScrollbarOnRight = (ltrRight === rtlRight);
 
        // First, check if scrollLeft is a non-zero value on the documentElement or
        // body. This means scrollLeft is a positive number offset from the left.
        if (docEl.scrollLeft &gt; 0) {
            // IE6/7 strict
            flag = 1;
        } else if (body.scrollLeft &gt; 0) {
            // IE6 - IE9 quirks
            flag = 5;
        } else {
            // The next step is to attempt to set scrollLeft values, This allows us to
            // test for non-zero values to see if the value was valid (scrollLeft
            // resets to 0 when a non-valid value is set).
            // attempt to set the documentElement's scrollLeft to a negative number
            docEl.scrollLeft = -1;
            if (docEl.scrollLeft) {
                // it worked! we were able to set a negative scroll left on the
                // documentElement (firefox)
                flag = 0;
            } else {
                // attempt to set the documentElement's scrollLeft to a positive number
                docEl.scrollLeft = 1;
                if (docEl.scrollLeft) {
                    // success setting scroll left to a positive number on
                    // documentElement (IE8 strict, IE9 strict, and IE10 quirks)
                    flag = 2;
                }
            }
        }
 
        el.remove();
        if (!direction) {
            // if direction is an empty string, we set it back to &quot;ltr&quot;, because once
            // the direction style on the body element is changed to &quot;rtl&quot; in webkit,
            // it becomes permanent, even after it is set back to &quot;&quot;, unless it is first
            // explicitly set back to &quot;ltr&quot;
            bodyStyle.direction = 'ltr';
            // read the scroll width before setting the direction back to &quot;&quot;.
            // This forces webkit to update its computed direction style to ltr
            body.scrollWidth;
        }
        // set direction back to its original value
        bodyStyle.direction = direction;
        Element.prototype._rtlDocScrollFlag = flag;
    }
 
    Ext.on({
        ready: function() {
            // This function attaches to onReady with a priority of 1000 so that we can
            // detect how the browser reports scrollLeft by manipulating the document/body
            // before any components have been rendered to the page.  
            cacheRtlDocScrollFlag();
            cacheRtlScrollFlag();
        },
        single: true,
        priority: 1001
    });
});
</pre>
</body>
</html>