Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
/**
2
 * JavaScript for form editing date conditions.
3
 *
4
 * @module moodle-availability_date-form
5
 */
6
M.availability_date = M.availability_date || {};
7
 
8
/**
9
 * @class M.availability_date.form
10
 * @extends M.core_availability.plugin
11
 */
12
M.availability_date.form = Y.Object(M.core_availability.plugin);
13
 
14
/**
15
 * Initialises this plugin.
16
 *
17
 * Because the date fields are complex depending on Moodle calendar settings,
18
 * we create the HTML for these fields in PHP and pass it to this method.
19
 *
20
 * @method initInner
21
 * @param {String} html HTML to use for date fields
22
 * @param {Number} defaultTime Time value that corresponds to initial fields
23
 */
24
M.availability_date.form.initInner = function(html, defaultTime) {
25
    this.html = html;
26
    this.defaultTime = defaultTime;
27
};
28
 
29
M.availability_date.form.getNode = function(json) {
30
    var html = '<span class="col-form-label pr-3">' +
31
                    M.util.get_string('direction_before', 'availability_date') + '</span> <span class="availability-group">' +
32
            '<label><span class="accesshide">' + M.util.get_string('direction_label', 'availability_date') + ' </span>' +
33
            '<select name="direction" class="custom-select">' +
34
            '<option value="&gt;=">' + M.util.get_string('direction_from', 'availability_date') + '</option>' +
35
            '<option value="&lt;">' + M.util.get_string('direction_until', 'availability_date') + '</option>' +
36
            '</select></label></span> ' + this.html;
37
    var node = Y.Node.create('<span>' + html + '</span>');
38
 
39
    // Set initial value if non-default.
40
    if (json.t !== undefined) {
41
        node.setData('time', json.t);
42
        // Disable everything.
43
        node.all('select:not([name=direction])').each(function(select) {
44
            select.set('disabled', true);
45
        });
46
 
47
        var url = M.cfg.wwwroot + '/availability/condition/date/ajax.php?action=fromtime' +
48
            '&time=' + json.t;
49
        Y.io(url, {on: {
50
            success: function(id, response) {
51
                var fields = Y.JSON.parse(response.responseText);
52
                for (var field in fields) {
53
                    var select = node.one('select[name=x\\[' + field + '\\]]');
54
                    select.set('value', '' + fields[field]);
55
                    select.set('disabled', false);
56
                }
57
            },
58
            failure: function() {
59
                window.alert(M.util.get_string('ajaxerror', 'availability_date'));
60
            }
61
        }});
62
    } else {
63
        // Set default time that corresponds to the HTML selectors.
64
        node.setData('time', this.defaultTime);
65
    }
66
    if (json.nodeUID === undefined) {
67
        var miliTime = new Date();
68
        json.nodeUID = miliTime.getTime();
69
    }
70
    node.setData('nodeUID', json.nodeUID);
71
    if (json.d !== undefined) {
72
        node.one('select[name=direction]').set('value', json.d);
73
    }
74
 
75
    // Add event handlers (first time only).
76
    if (!M.availability_date.form.addedEvents) {
77
        M.availability_date.form.addedEvents = true;
78
 
79
        var root = Y.one('.availability-field');
80
        root.delegate('change', function() {
81
            // For the direction, just update the form fields.
82
            M.core_availability.form.update();
83
        }, '.availability_date select[name=direction]');
84
 
85
        root.delegate('change', function() {
86
            // Update time using AJAX call from root node.
87
            M.availability_date.form.updateTime(this.ancestor('span.availability_date'));
88
        }, '.availability_date select:not([name=direction])');
89
    }
90
 
91
    if (node.one('a[href=#]')) {
92
        // Add the date selector magic.
93
        M.form.dateselector.init_single_date_selector(node);
94
 
95
        // This special handler detects when the date selector changes the year.
96
        var yearSelect = node.one('select[name=x\\[year\\]]');
97
        var oldSet = yearSelect.set;
98
        yearSelect.set = function(name, value) {
99
            oldSet.call(yearSelect, name, value);
100
            if (name === 'selectedIndex') {
101
                // Do this after timeout or the other fields haven't been set yet.
102
                setTimeout(function() {
103
                    M.availability_date.form.updateTime(node);
104
                }, 0);
105
            }
106
        };
107
    }
108
 
109
    return node;
110
};
111
 
112
/**
113
 * Updates time from AJAX. Whenever the field values change, we recompute the
114
 * actual time via an AJAX request to Moodle.
115
 *
116
 * This will set the 'time' data on the node and then update the form, once it
117
 * gets an AJAX response.
118
 *
119
 * @method updateTime
120
 * @param {Y.Node} node Node for plugin controls
121
 */
122
M.availability_date.form.updateTime = function(node) {
123
    // After a change to the date/time we need to recompute the
124
    // actual time using AJAX because it depends on the user's
125
    // time zone and calendar options.
126
    var url = M.cfg.wwwroot + '/availability/condition/date/ajax.php?action=totime' +
127
            '&year=' + node.one('select[name=x\\[year\\]]').get('value') +
128
            '&month=' + node.one('select[name=x\\[month\\]]').get('value') +
129
            '&day=' + node.one('select[name=x\\[day\\]]').get('value') +
130
            '&hour=' + node.one('select[name=x\\[hour\\]]').get('value') +
131
            '&minute=' + node.one('select[name=x\\[minute\\]]').get('value');
132
    Y.io(url, {on: {
133
        success: function(id, response) {
134
            node.setData('time', response.responseText);
135
            M.core_availability.form.update();
136
        },
137
        failure: function() {
138
            window.alert(M.util.get_string('ajaxerror', 'availability_date'));
139
        }
140
    }});
141
};
142
 
143
M.availability_date.form.fillValue = function(value, node) {
144
    value.d = node.one('select[name=direction]').get('value');
145
    value.t = parseInt(node.getData('time'), 10);
146
    value.nodeUID = node.getData('nodeUID');
147
};
148
 
149
/**
150
 * List out Date node value in the same branch.
151
 *
152
 * This will go through all array node and list nodes that are sibling of the current node.
153
 *
154
 * @method findAllDateSiblings
155
 * @param {Array} tree Tree items to convert
156
 * @param {Number} nodeUIDToFind node UID to find.
157
 * @return {Array|null} array of surrounding date avaiability values
158
 */
159
M.availability_date.form.findAllDateSiblings = function(tree, nodeUIDToFind) {
160
    var itemValue = null;
161
    var siblingsFinderRecursive = function(itemsTree) {
162
        var dateSiblings = [];
163
        var nodeFound = false;
164
        var index;
165
        var childDates;
166
        var currentOp = itemsTree.op !== undefined ? itemsTree.op : null;
167
        if (itemsTree.c !== undefined) {
168
            var children = itemsTree.c;
169
            for (index = 0; index < children.length; index++) {
170
                itemValue = children.at(index);
171
                if (itemValue.type === undefined) {
172
                    childDates = siblingsFinderRecursive(itemValue);
173
                    if (childDates) {
174
                        return childDates;
175
                    }
176
                }
177
                if (itemValue.type === 'date') {
178
                    // We go through all tree node, if we meet the current node then we add all nodes in the current branch.
179
                    if (nodeUIDToFind === itemValue.nodeUID) {
180
                        nodeFound = true;
181
                    } else if (currentOp === '&') {
182
                        dateSiblings.push(itemValue);
183
                    }
184
                }
185
            }
186
            if (nodeFound) {
187
                return dateSiblings;
188
            }
189
        }
190
        return null;
191
    };
192
    return siblingsFinderRecursive(tree);
193
};
194
 
195
/**
196
 * Check current node.
197
 *
198
 * This will check current date node with all date node in tree node.
199
 *
200
 * @method checkConditionDate
201
 * @param {Y.Node} currentNode The curent node.
202
 *
203
 * @return {boolean} error Return true if the date is conflict.
204
 */
205
M.availability_date.form.checkConditionDate = function(currentNode) {
206
    var error = false;
207
    var currentNodeUID = currentNode.getData('nodeUID');
208
    var currentNodeDirection = currentNode.one('select[name=direction]').get('value');
209
    var currentNodeTime = parseInt(currentNode.getData('time'), 10);
210
    var dateSiblings = M.availability_date.form.findAllDateSiblings(
211
        M.core_availability.form.rootList.getValue(),
212
        currentNodeUID);
213
    if (dateSiblings) {
214
        dateSiblings.forEach(function(dateSibling) {
215
            // Validate if the date is conflict.
216
            if (dateSibling.d === '<') {
217
                if (currentNodeDirection === '>=' && currentNodeTime >= dateSibling.t) {
218
                    error = true;
219
                }
220
            } else {
221
                if (currentNodeDirection === '<' && currentNodeTime <= dateSibling.t) {
222
                    error = true;
223
                }
224
            }
225
            return error;
226
        });
227
    }
228
    return error;
229
};
230
 
231
M.availability_date.form.fillErrors = function(errors, node) {
232
    var error = M.availability_date.form.checkConditionDate(node);
233
    if (error) {
234
        errors.push('availability_date:error_dateconflict');
235
    }
236
};