~ubuntu-branches/ubuntu/utopic/moodle/utopic

« back to all changes in this revision

Viewing changes to lib/form/form.js

  • Committer: Package Import Robot
  • Author(s): Thijs Kinkhorst
  • Date: 2014-05-12 16:10:38 UTC
  • mfrom: (36.1.3 sid)
  • Revision ID: package-import@ubuntu.com-20140512161038-puyqf65k4e0s8ytz
Tags: 2.6.3-1
New upstream release.

Show diffs side-by-side

added added

removed removed

Lines of Context:
41
41
        };
42
42
        dependencyManager.prototype = {
43
43
            _form : null,
44
 
            _depElements : [],
45
 
            _nameCollections : [],
 
44
            _locks : [],
 
45
            _hides : [],
 
46
            _dirty : [],
 
47
            _nameCollections : null,
 
48
            _fileinputs : null,
46
49
            initializer : function(config) {
47
50
                var i = 0, nodeName;
48
51
                this._form = Y.one('#'+formid);
49
52
                for (i in dependencies) {
50
 
                    this._depElements[i] = this.elementsByName(i);
51
 
                    if (this._depElements[i].size() == 0) {
 
53
                    var elements = this.elementsByName(i);
 
54
                    if (elements.size() == 0) {
52
55
                        continue;
53
56
                    }
54
 
                    this._depElements[i].each(function(node){
 
57
                    elements.each(function(node){
55
58
                        nodeName = node.get('nodeName').toUpperCase();
56
59
                        if (nodeName == 'INPUT') {
57
60
                            if (node.getAttribute('type').match(/^(button|submit|radio|checkbox)$/)) {
58
 
                                node.on('click', this.checkDependencies, this);
 
61
                                node.on('click', this.updateEventDependencies, this);
59
62
                            } else {
60
 
                                node.on('blur', this.checkDependencies, this);
 
63
                                node.on('blur', this.updateEventDependencies, this);
61
64
                            }
62
 
                            node.on('change', this.checkDependencies, this);
 
65
                            node.on('change', this.updateEventDependencies, this);
63
66
                        } else if (nodeName == 'SELECT') {
64
 
                            node.on('change', this.checkDependencies, this);
 
67
                            node.on('change', this.updateEventDependencies, this);
65
68
                        } else {
66
 
                            node.on('click', this.checkDependencies, this);
67
 
                            node.on('blur', this.checkDependencies, this);
68
 
                            node.on('change', this.checkDependencies, this);
 
69
                            node.on('click', this.updateEventDependencies, this);
 
70
                            node.on('blur', this.updateEventDependencies, this);
 
71
                            node.on('change', this.updateEventDependencies, this);
69
72
                        }
70
73
                    }, this);
71
74
                }
73
76
                    if (input.getAttribute('type')=='reset') {
74
77
                        input.on('click', function(){
75
78
                            this._form.reset();
76
 
                            this.checkDependencies();
 
79
                            this.updateAllDependencies();
77
80
                        }, this);
78
81
                    }
79
82
                }, this);
80
83
 
81
 
                return this.checkDependencies(null);
 
84
                return this.updateAllDependencies();
 
85
            },
 
86
            /**
 
87
             * Initializes the mapping from element name to YUI NodeList
 
88
             */
 
89
            initElementsByName : function() {
 
90
                var names = [];
 
91
                // Collect element names
 
92
                for (var i in dependencies) {
 
93
                    names[i] = new Y.NodeList();
 
94
                    for (var condition in dependencies[i]) {
 
95
                        for (var value in dependencies[i][condition]) {
 
96
                            for (var ei in dependencies[i][condition][value]) {
 
97
                                names[dependencies[i][condition][value][ei]] = new Y.NodeList();
 
98
                            }
 
99
                        }
 
100
                    }
 
101
                }
 
102
                // Locate elements for each name
 
103
                this._form.get('elements').each(function(node){
 
104
                    var name = node.getAttribute('name');
 
105
                    if (names[name]) {
 
106
                        names[name].push(node);
 
107
                    }
 
108
                });
 
109
                this._nameCollections = names;
82
110
            },
83
111
            /**
84
112
             * Gets all elements in the form by their name and returns
85
113
             * a YUI NodeList
86
 
             * @return Y.NodeList
 
114
             *
 
115
             * @param {string} name The form element name.
 
116
             * @return {Y.NodeList}
87
117
             */
88
118
            elementsByName : function(name) {
 
119
                if (!this._nameCollections) {
 
120
                    this.initElementsByName();
 
121
                }
89
122
                if (!this._nameCollections[name]) {
90
 
                    var elements = [];
91
 
                    this._form.get('elements').each(function(){
92
 
                        if (this.getAttribute('name') == name) {
93
 
                            elements.push(this);
94
 
                        }
95
 
                    });
96
 
                    this._nameCollections[name] = new Y.NodeList(elements);
 
123
                    return new Y.NodeList();
97
124
                }
98
125
                return this._nameCollections[name];
99
126
            },
103
130
             *
104
131
             * Changes are made by functions title _dependency_{dependencytype}
105
132
             * and more can easily be introduced by defining further functions.
 
133
             *
 
134
             * @param {EventFacade | null} e The event, if any.
 
135
             * @param {string} name The form element name to check dependencies against.
106
136
             */
107
 
            checkDependencies : function(e) {
108
 
                var tolock = [],
109
 
                    tohide = [],
110
 
                    dependon, condition, value,
111
 
                    lock, hide, checkfunction, result;
112
 
                for (dependon in dependencies) {
113
 
                    if (this._depElements[dependon].size() == 0) {
114
 
                        continue;
115
 
                    }
116
 
                    for (condition in dependencies[dependon]) {
117
 
                        for (value in dependencies[dependon][condition]) {
118
 
                            lock = false;
119
 
                            hide = false;
120
 
                            checkfunction = '_dependency_'+condition;
121
 
                            if (Y.Lang.isFunction(this[checkfunction])) {
122
 
                                result = this[checkfunction].apply(this, [this._depElements[dependon], value, e]);
123
 
                            } else {
124
 
                                result = this._dependency_default(this._depElements[dependon], value, e);
125
 
                            }
126
 
                            lock = result.lock || false;
127
 
                            hide = result.hide || false;
128
 
                            for (var ei in dependencies[dependon][condition][value]) {
129
 
                                var eltolock = dependencies[dependon][condition][value][ei];
130
 
                                if (hide) {
131
 
                                    tohide[eltolock] = true;
132
 
                                }
133
 
                                if (tolock[eltolock] != null) {
134
 
                                    tolock[eltolock] = lock || tolock[eltolock];
135
 
                                } else {
136
 
                                    tolock[eltolock] = lock;
137
 
                                }
138
 
                            }
 
137
            checkDependencies : function(e, dependon) {
 
138
                var tohide = [],
 
139
                    tolock = [],
 
140
                    condition, value, lock, hide,
 
141
                    checkfunction, result, elements;
 
142
                if (!dependencies[dependon]) {
 
143
                    return true;
 
144
                }
 
145
                elements = this.elementsByName(dependon);
 
146
                for (condition in dependencies[dependon]) {
 
147
                    for (value in dependencies[dependon][condition]) {
 
148
                        checkfunction = '_dependency_'+condition;
 
149
                        if (Y.Lang.isFunction(this[checkfunction])) {
 
150
                            result = this[checkfunction].apply(this, [elements, value, e]);
 
151
                        } else {
 
152
                            result = this._dependency_default(elements, value, e);
 
153
                        }
 
154
                        lock = result.lock || false;
 
155
                        hide = result.hide || false;
 
156
                        for (var ei in dependencies[dependon][condition][value]) {
 
157
                            var eltolock = dependencies[dependon][condition][value][ei];
 
158
                            tohide[eltolock] = tohide[eltolock] || hide;
 
159
                            tolock[eltolock] = tolock[eltolock] || lock;
139
160
                        }
140
161
                    }
141
162
                }
142
163
                for (var el in tolock) {
143
 
                    this._disableElement(el, tolock[el]);
144
 
                    if (tohide.propertyIsEnumerable(el)) {
145
 
                        this._hideElement(el, tohide[el]);
 
164
                    var needsupdate = false;
 
165
                    if (tolock[el]) {
 
166
                        this._locks[el] = this._locks[el] || [];
 
167
                        if (!this._locks[el][dependon]) {
 
168
                            this._locks[el][dependon] = true;
 
169
                            needsupdate = true;
 
170
                        }
 
171
                    } else if (this._locks[el] && this._locks[el][dependon]) {
 
172
                        delete this._locks[el][dependon];
 
173
                        needsupdate = true;
 
174
                    }
 
175
                    if (tohide[el]) {
 
176
                        this._hides[el] = this._hides[el] || [];
 
177
                        if (!this._hides[el][dependon]) {
 
178
                            this._hides[el][dependon] = true;
 
179
                            needsupdate = true;
 
180
                        }
 
181
                    } else if (this._hides[el] && this._hides[el][dependon]) {
 
182
                        delete this._hides[el][dependon];
 
183
                        needsupdate = true;
 
184
                    }
 
185
                    if (needsupdate) {
 
186
                        this._dirty[el] = true;
146
187
                    }
147
188
                }
148
189
                return true;
149
190
            },
150
191
            /**
151
 
             * Disabled all form elements with the given name
 
192
             * Update all dependencies in form
 
193
             */
 
194
            updateAllDependencies : function() {
 
195
                for (var el in dependencies) {
 
196
                    this.checkDependencies(null, el);
 
197
                }
 
198
                this.updateForm();
 
199
            },
 
200
            /**
 
201
             * Update dependencies associated with event
 
202
             *
 
203
             * @param {Event} e The event.
 
204
             */
 
205
            updateEventDependencies : function(e) {
 
206
                var el = e.target.getAttribute('name');
 
207
                this.checkDependencies(e, el);
 
208
                this.updateForm();
 
209
            },
 
210
            /**
 
211
             * Flush pending changes to the form
 
212
             */
 
213
            updateForm : function() {
 
214
                for (var el in this._dirty) {
 
215
                    if (this._locks[el]) {
 
216
                        var locked = !this._isObjectEmpty(this._locks[el]);
 
217
                        this._disableElement(el, locked);
 
218
                    }
 
219
                    if (this._hides[el]) {
 
220
                        var hidden = !this._isObjectEmpty(this._hides[el]);
 
221
                        this._hideElement(el, hidden);
 
222
                    }
 
223
                }
 
224
                this._dirty = [];
 
225
            },
 
226
            /**
 
227
             * Disables or enables all form elements with the given name
 
228
             *
 
229
             * @param {string} name The form element name.
 
230
             * @param {boolean} disabled True to disable, false to enable.
152
231
             */
153
232
            _disableElement : function(name, disabled) {
154
233
                var els = this.elementsByName(name);
155
 
                var form = this;
156
 
                els.each(function(){
 
234
                var filepicker = this.isFilePicker(name);
 
235
                els.each(function(node){
157
236
                    if (disabled) {
158
 
                        this.setAttribute('disabled', 'disabled');
 
237
                        node.setAttribute('disabled', 'disabled');
159
238
                    } else {
160
 
                        this.removeAttribute('disabled');
 
239
                        node.removeAttribute('disabled');
161
240
                    }
162
241
 
163
242
                    // Extra code to disable filepicker or filemanager form elements
164
 
                    var fitem = this.ancestor('.fitem');
165
 
                    if (fitem && (fitem.hasClass('fitem_ffilemanager') || fitem.hasClass('fitem_ffilepicker'))) {
166
 
                        if (disabled){
167
 
                            fitem.addClass('disabled');
168
 
                        } else {
169
 
                            fitem.removeClass('disabled');
 
243
                    if (filepicker) {
 
244
                        var fitem = node.ancestor('.fitem');
 
245
                        if (fitem) {
 
246
                            if (disabled){
 
247
                                fitem.addClass('disabled');
 
248
                            } else {
 
249
                                fitem.removeClass('disabled');
 
250
                            }
170
251
                        }
171
252
                    }
172
253
                })
173
254
            },
174
255
            /**
175
 
             * Hides all elements with the given name.
 
256
             * Hides or shows all form elements with the given name.
 
257
             *
 
258
             * @param {string} name The form element name.
 
259
             * @param {boolean} disabled True to hide, false to show.
176
260
             */
177
261
            _hideElement : function(name, hidden) {
178
262
                var els = this.elementsByName(name);
179
 
                els.each(function(){
180
 
                    var e = els.ancestor('.fitem');
 
263
                els.each(function(node){
 
264
                    var e = node.ancestor('.fitem');
181
265
                    if (e) {
182
266
                        e.setStyles({
183
267
                            display : (hidden)?'none':''
185
269
                    }
186
270
                });
187
271
            },
 
272
            /**
 
273
             * Is the form element inside a filepicker or filemanager?
 
274
             *
 
275
             * @param {string} el The form element name.
 
276
             * @return {boolean}
 
277
             */
 
278
            isFilePicker : function(el) {
 
279
                if (!this._fileinputs) {
 
280
                    var fileinputs = [];
 
281
                    var els = this._form.all('.fitem.fitem_ffilepicker input,.fitem.fitem_ffilemanager input');
 
282
                    els.each(function(node){
 
283
                        fileinputs[node.getAttribute('name')] = true;
 
284
                    });
 
285
                    this._fileinputs = fileinputs;
 
286
                }
 
287
                return this._fileinputs[el] || false;
 
288
            },
 
289
            /**
 
290
             * Check if the object is empty
 
291
             *
 
292
             * @param {object} obj
 
293
             * @return {boolean}
 
294
             */
 
295
            _isObjectEmpty : function(obj) {
 
296
                for(var prop in obj) {
 
297
                    if(obj.hasOwnProperty(prop))
 
298
                        return false;
 
299
                }
 
300
                return true;
 
301
            },
188
302
            _dependency_notchecked : function(elements, value) {
189
303
                var lock = false;
190
304
                elements.each(function(){
365
479
 */
366
480
M.form.updateFormState = function(formid) {
367
481
    if (formid in M.form.dependencyManagers) {
368
 
        M.form.dependencyManagers[formid].checkDependencies(null);
 
482
        M.form.dependencyManagers[formid].updateAllDependencies();
369
483
    }
370
484
};