Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
/**
2
 * This file contains the Block Region class used by the drag and drop manager.
3
 *
4
 * Provides drag and drop functionality for blocks.
5
 *
6
 * @module moodle-core-blockdraganddrop
7
 */
8
 
9
/**
10
 * Constructs a new block region object.
11
 *
12
 * @namespace M.core.blockdraganddrop
13
 * @class BlockRegion
14
 * @constructor
15
 * @extends Base
16
 */
17
BLOCKREGION = function() {
18
    BLOCKREGION.superclass.constructor.apply(this, arguments);
19
};
20
BLOCKREGION.prototype = {
21
    /**
22
     * Called during the initialisation process of the object.
23
     * @method initializer
24
     */
25
    initializer: function() {
26
        var node = this.get('node');
27
        Y.log('Block region `' + this.get('region') + '` initialising', 'info');
28
        if (!node) {
29
            Y.log('block region known about but no HTML structure found for it. Guessing structure.', 'warn');
30
            node = this.create_and_add_node();
31
        }
32
        var body = Y.one('body'),
33
            hasblocks = node.all('.' + CSS.BLOCK).size() > 0,
34
            hasregionclass = this.get_has_region_class();
35
        this.set('hasblocks', hasblocks);
36
        if (!body.hasClass(hasregionclass)) {
37
            body.addClass(hasregionclass);
38
        }
39
        body.addClass((hasblocks) ? this.get_used_region_class() : this.get_empty_region_class());
40
        body.removeClass((hasblocks) ? this.get_empty_region_class() : this.get_used_region_class());
41
    },
42
    /**
43
     * Creates a generic block region node and adds it to the DOM at the best guess location.
44
     * Any calling of this method is an unfortunate circumstance.
45
     * @method create_and_add_node
46
     * @return Node The newly created Node
47
     */
48
    create_and_add_node: function() {
49
        var c = Y.Node.create,
50
            region = this.get('region'),
51
            node = c('<div id="block-region-' + region + '" data-droptarget="1"></div>')
52
                .addClass(CSS.BLOCKREGION)
53
                .setData('blockregion', region),
54
            regions = this.get('manager').get('regions'),
55
            i,
56
            haspre = false,
57
            haspost = false,
58
            added = false,
59
            pre,
60
            post;
61
 
62
        for (i in regions) {
63
            if (regions[i].match(/(pre|left)/)) {
64
                haspre = regions[i];
65
            } else if (regions[i].match(/(post|right)/)) {
66
                haspost = regions[i];
67
            }
68
        }
69
 
70
        if (haspre !== false && haspost !== false) {
71
            if (region === haspre) {
72
                post = Y.one('#block-region-' + haspost);
73
                if (post) {
74
                    post.insert(node, 'before');
75
                    added = true;
76
                }
77
            } else {
78
                pre = Y.one('#block-region-' + haspre);
79
                if (pre) {
80
                    pre.insert(node, 'after');
81
                    added = true;
82
                }
83
            }
84
        }
85
        if (added === false) {
86
            Y.one('body').append(node);
87
        }
88
        this.set('node', node);
89
 
90
        return node;
91
    },
92
 
93
    /**
94
     * Change the move icons to enhanced drag handles and changes the cursor to a move icon when over the header.
95
     * @param M.core.dragdrop the block manager
96
     * @method change_block_move_icons
97
     */
98
    change_block_move_icons: function(manager) {
99
        var handle;
100
        this.get('node').all('.' + CSS.BLOCK + ' a.' + CSS.EDITINGMOVE).each(function(moveicon) {
101
            moveicon.setStyle('cursor', 'move');
102
            handle = manager.get_drag_handle(moveicon.getAttribute('title'), '', 'icon', true);
103
            // Dragdrop module assigns this with a button role by default.
104
            // However, the block move icon is part of a menubar, so it should have a menuitem role.
105
            handle.setAttribute('role', 'menuitem');
106
            moveicon.replace(handle);
107
        });
108
    },
109
 
110
    /**
111
     * Returns the class name on the body that signifies the document knows about this region.
112
     * @method get_has_region_class
113
     * @return String
114
     */
115
    get_has_region_class: function() {
116
        return 'has-region-' + this.get('region');
117
    },
118
 
119
    /**
120
     * Returns the class name to use on the body if the region contains no blocks.
121
     * @method get_empty_region_class
122
     * @return String
123
     */
124
    get_empty_region_class: function() {
125
        return 'empty-region-' + this.get('region');
126
    },
127
 
128
    /**
129
     * Returns the class name to use on the body if the region contains blocks.
130
     * @method get_used_region_class
131
     * @return String
132
     */
133
    get_used_region_class: function() {
134
        return 'used-region-' + this.get('region');
135
    },
136
 
137
    /**
138
     * Returns the node to use as the drop target for this region.
139
     * @method get_droptarget
140
     * @return Node
141
     */
142
    get_droptarget: function() {
143
        var node = this.get('node');
144
        if (node.test('[data-droptarget="1"]')) {
145
            return node;
146
        }
147
        return node.one('[data-droptarget="1"]');
148
    },
149
 
150
    /**
151
     * Enables the block region so that we can be sure the user can see it.
152
     * This is done even if it is empty.
153
     * @method enable
154
     */
155
    enable: function() {
156
        Y.one('body').addClass(this.get_used_region_class()).removeClass(this.get_empty_region_class());
157
    },
158
 
159
    /**
160
     * Disables the region if it contains no blocks, essentially hiding it from the user.
161
     * @method disable_if_required
162
     */
163
    disable_if_required: function() {
164
        if (this.get('node').all('.' + CSS.BLOCK).size() === 0) {
165
            Y.one('body').addClass(this.get_empty_region_class()).removeClass(this.get_used_region_class());
166
        }
167
    }
168
};
169
Y.extend(BLOCKREGION, Y.Base, BLOCKREGION.prototype, {
170
    NAME: 'core-blocks-dragdrop-blockregion',
171
    ATTRS: {
172
 
173
        /**
174
         * The drag and drop manager that created this block region instance.
175
         * @attribute manager
176
         * @type M.core.blockdraganddrop.Manager
177
         * @writeOnce
178
         */
179
        manager: {
180
            // Can only be set during initialisation and must be set then.
181
            writeOnce: 'initOnly',
182
            validator: function(value) {
183
                return Y.Lang.isObject(value) && value instanceof MANAGER;
184
            }
185
        },
186
 
187
        /**
188
         * The name of the block region this object represents.
189
         * @attribute region
190
         * @type String
191
         * @writeOnce
192
         */
193
        region: {
194
            // Can only be set during initialisation and must be set then.
195
            writeOnce: 'initOnly',
196
            validator: function(value) {
197
                return Y.Lang.isString(value);
198
            }
199
        },
200
 
201
        /**
202
         * The node the block region HTML starts at.s
203
         * @attribute region
204
         * @type Y.Node
205
         */
206
        node: {
207
            validator: function(value) {
208
                return Y.Lang.isObject(value) || Y.Lang.isNull(value);
209
            }
210
        },
211
 
212
        /**
213
         * True if the block region currently contains blocks.
214
         * @attribute hasblocks
215
         * @type Boolean
216
         * @default false
217
         */
218
        hasblocks: {
219
            value: false,
220
            validator: function(value) {
221
                return Y.Lang.isBoolean(value);
222
            }
223
        }
224
    }
225
});