Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
/**
2
 * Provides the ability to lock the scroll for a page, allowing nested
3
 * locking.
4
 *
5
 * @module moodle-core-lockscroll
6
 */
7
 
8
/**
9
 * Provides the ability to lock the scroll for a page.
10
 *
11
 * This is achieved by applying the class 'lockscroll' to the body Node.
12
 *
13
 * Nested widgets are also supported and the scroll lock is only removed
14
 * when the final plugin instance is disabled.
15
 *
16
 * @class M.core.LockScroll
17
 * @extends Plugin.Base
18
 */
19
Y.namespace('M.core').LockScroll = Y.Base.create('lockScroll', Y.Plugin.Base, [], {
20
 
21
    /**
22
     * Whether the LockScroll has been activated.
23
     *
24
     * @property _enabled
25
     * @type Boolean
26
     * @protected
27
     */
28
    _enabled: false,
29
 
30
    /**
31
     * Handle destruction of the lockScroll instance, including disabling
32
     * of the current instance.
33
     *
34
     * @method destructor
35
     */
36
    destructor: function() {
37
        this.disableScrollLock();
38
    },
39
 
40
    /**
41
     * Start locking the page scroll.
42
     *
43
     * This is achieved by applying the lockscroll class to the body Node.
44
     *
45
     * A count of the total number of active, and enabled, lockscroll instances is also kept on
46
     * the body to ensure that premature disabling does not occur.
47
     *
48
     * @method enableScrollLock
49
     * @param {Boolean} forceOnSmallWindow Whether to enable the scroll lock, even for small window sizes.
50
     * @chainable
51
     */
52
    enableScrollLock: function(forceOnSmallWindow) {
53
        if (this.isActive()) {
54
            Y.log('LockScroll already active. Ignoring enable request', 'warn', 'moodle-core-lockscroll');
55
            return;
56
        }
57
 
58
        if (!this.shouldLockScroll(forceOnSmallWindow)) {
59
            Y.log('Dialogue height greater than window height. Ignoring enable request.', 'warn', 'moodle-core-lockscroll');
60
            return;
61
        }
62
 
63
        Y.log('Enabling LockScroll.', 'debug', 'moodle-core-lockscroll');
64
        this._enabled = true;
65
        var body = Y.one(Y.config.doc.body);
66
 
67
        // Get width of body before turning on lockscroll.
68
        var widthBefore = body.getComputedStyle('width');
69
 
70
        // We use a CSS class on the body to handle the actual locking.
71
        body.addClass('lockscroll');
72
 
73
        // Increase the count of active instances - this is used to ensure that we do not
74
        // remove the locking when parent windows are still open.
75
        // Note: We cannot use getData here because data attributes are sandboxed to the instance that created them.
76
        var currentCount = parseInt(body.getAttribute('data-activeScrollLocks'), 10) || 0,
77
            newCount = currentCount + 1;
78
        body.setAttribute('data-activeScrollLocks', newCount);
79
        Y.log("Setting the activeScrollLocks count from " + currentCount + " to " + newCount,
80
                'debug', 'moodle-core-lockscroll');
81
 
82
        // When initially enabled, set the body max-width to its current width. This
83
        // avoids centered elements jumping because the width changes when scrollbars
84
        // disappear.
85
        if (currentCount === 0) {
86
            body.setStyle('maxWidth', widthBefore);
87
        }
88
 
89
        return this;
90
    },
91
 
92
    /**
93
     * Recalculate whether lock scrolling should be on or off.
94
     *
95
     * @method shouldLockScroll
96
     * @param {Boolean} forceOnSmallWindow Whether to enable the scroll lock, even for small window sizes.
97
     * @return boolean
98
     */
99
    shouldLockScroll: function(forceOnSmallWindow) {
100
        var dialogueHeight = this.get('host').get('boundingBox').get('region').height,
101
            // Most modern browsers use win.innerHeight, but some older versions of IE use documentElement.clientHeight.
102
            // We fall back to 0 if neither can be found which has the effect of disabling scroll locking.
103
            windowHeight = Y.config.win.innerHeight || Y.config.doc.documentElement.clientHeight || 0;
104
 
105
        if (!forceOnSmallWindow && dialogueHeight > (windowHeight - 10)) {
106
            return false;
107
        } else {
108
            return true;
109
        }
110
    },
111
 
112
    /**
113
     * Recalculate whether lock scrolling should be on or off because the size of the dialogue changed.
114
     *
115
     * @method updateScrollLock
116
     * @param {Boolean} forceOnSmallWindow Whether to enable the scroll lock, even for small window sizes.
117
     * @chainable
118
     */
119
    updateScrollLock: function(forceOnSmallWindow) {
120
        // Both these functions already check if scroll lock is active and do the right thing.
121
        if (this.shouldLockScroll(forceOnSmallWindow)) {
122
            this.enableScrollLock(forceOnSmallWindow);
123
        } else {
124
            this.disableScrollLock(true);
125
        }
126
 
127
        return this;
128
    },
129
 
130
    /**
131
     * Stop locking the page scroll.
132
     *
133
     * The instance may be disabled but the scroll lock not removed if other instances of the
134
     * plugin are also active.
135
     *
136
     * @method disableScrollLock
137
     * @chainable
138
     */
139
    disableScrollLock: function(force) {
140
        if (this.isActive()) {
141
            Y.log('Disabling LockScroll.', 'debug', 'moodle-core-lockscroll');
142
            this._enabled = false;
143
 
144
            var body = Y.one(Y.config.doc.body);
145
 
146
            // Decrease the count of active instances.
147
            // Note: We cannot use getData here because data attributes are sandboxed to the instance that created them.
148
            var currentCount = parseInt(body.getAttribute('data-activeScrollLocks'), 10) || 1,
149
                newCount = currentCount - 1;
150
 
151
            if (force || currentCount === 1) {
152
                body.removeClass('lockscroll');
153
                body.setStyle('maxWidth', null);
154
            }
155
 
156
            body.setAttribute('data-activeScrollLocks', currentCount - 1);
157
            Y.log("Setting the activeScrollLocks count from " + currentCount + " to " + newCount,
158
                    'debug', 'moodle-core-lockscroll');
159
        }
160
 
161
        return this;
162
    },
163
 
164
    /**
165
     * Return whether scroll locking is active.
166
     *
167
     * @method isActive
168
     * @return Boolean
169
     */
170
    isActive: function() {
171
        return this._enabled;
172
    }
173
 
174
}, {
175
    NS: 'lockScroll',
176
    ATTRS: {
177
    }
178
});