MDL-41987 Javascript: Tidy up YUI documentation
[moodle.git] / course / yui / src / management / js / item.js
blob97b75f2fa789692768531db41b742207fbb96e98
1 /**
2  * A managed course.
3  *
4  * @namespace M.course.management
5  * @class Item
6  * @constructor
7  * @extends Base
8  */
9 function Item() {
10     Item.superclass.constructor.apply(this, arguments);
12 Item.NAME = 'moodle-course-management-item';
13 Item.CSS_PREFIX = 'management-item';
14 Item.ATTRS = {
15     /**
16      * The node for this item.
17      * @attribute node
18      * @type Node
19      */
20     node : {},
22     /**
23      * The management console.
24      * @attribute console
25      * @type Console
26      */
27     console : {},
29     /**
30      * Describes the type of this item. Should be set by the extending class.
31      * @attribute itemname
32      * @type {String}
33      * @default item
34      */
35     itemname : {
36         value : 'item'
37     }
39 Item.prototype = {
40     /**
41      * The highlight timeout for this item if there is one.
42      * @property highlighttimeout
43      * @protected
44      * @type Timeout
45      * @default null
46      */
47     highlighttimeout : null,
49     /**
50      * Checks and parses an AJAX response for an item.
51      *
52      * @method checkAjaxResponse
53      * @protected
54      * @param {Number} transactionid The transaction ID of the AJAX request (unique)
55      * @param {Object} response The response from the AJAX request.
56      * @param {Object} args The arguments given to the request.
57      * @return {Object|Boolean}
58      */
59     checkAjaxResponse : function(transactionid, response, args) {
60         if (response.status !== 200) {
61             Y.log('Error: AJAX response resulted in non 200 status.', 'error', 'Item.checkAjaxResponse');
62             return false;
63         }
64         if (transactionid === null || args === null) {
65             Y.log('Error: Invalid AJAX response details provided.', 'error', 'Item.checkAjaxResponse');
66             return false;
67         }
68         var outcome = Y.JSON.parse(response.responseText);
69         if (outcome.error !== false) {
70             new M.core.exception(outcome);
71         }
72         if (outcome.outcome === false) {
73             return false;
74         }
75         return outcome;
76     },
78     /**
79      * Moves an item up by one.
80      *
81      * @method moveup
82      * @param {Number} transactionid The transaction ID of the AJAX request (unique)
83      * @param {Object} response The response from the AJAX request.
84      * @param {Object} args The arguments given to the request.
85      * @return {Boolean}
86      */
87     moveup : function(transactionid, response, args) {
88         var node,
89             nodeup,
90             nodedown,
91             previous,
92             previousup,
93             previousdown,
94             tmpnode,
95             outcome = this.checkAjaxResponse(transactionid, response, args);
96         if (outcome === false) {
97             Y.log('AJAX request to move '+this.get('itemname')+' up failed by outcome.', 'warn', 'moodle-course-management');
98             return false;
99         }
100         node = this.get('node');
101         previous = node.previous('.listitem');
102         if (previous) {
103             previous.insert(node, 'before');
104             previousup = previous.one(' > div a.action-moveup');
105             nodedown = node.one(' > div a.action-movedown');
106             if (!previousup || !nodedown) {
107                 // We can have two situations here:
108                 //   1. previousup is not set and nodedown is not set. This happens when there are only two courses.
109                 //   2. nodedown is not set. This happens when they are moving the bottom course up.
110                 // node up and previous down should always be there. They would be required to trigger the action.
111                 nodeup = node.one(' > div a.action-moveup');
112                 previousdown = previous.one(' > div a.action-movedown');
113                 if (!previousup && !nodedown) {
114                     // Ok, must be two courses. We need to switch the up and down icons.
115                     tmpnode = Y.Node.create('<a style="visibility:hidden;">&nbsp;</a>');
116                     previousdown.replace(tmpnode);
117                     nodeup.replace(previousdown);
118                     tmpnode.replace(nodeup);
119                     tmpnode.destroy();
120                 } else if (!nodedown) {
121                     // previous down needs to be given to node.
122                     nodeup.insert(previousdown, 'after');
123                 }
124             }
125             nodeup = node.one(' > div a.action-moveup');
126             if (nodeup) {
127                 // Try to re-focus on up.
128                 nodeup.focus();
129             } else {
130                 // If we can't focus up we're at the bottom, try to focus on up.
131                 nodedown = node.one(' > div a.action-movedown');
132                 if (nodedown) {
133                     nodedown.focus();
134                 }
135             }
136             this.updated(true);
137             Y.log('Success: '+this.get('itemname')+' moved up by AJAX.', 'info', 'moodle-course-management');
138         } else {
139             // Aha it succeeded but this is the top item in the list. Pagination is in play!
140             // Refresh to update the state of things.
141             Y.log(this.get('itemname')+' cannot be moved up as its the top item on this page.', 'info', 'moodle-course-management');
142             window.location.reload();
143         }
144     },
146     /**
147      * Moves an item down by one.
148      *
149      * @method movedown
150      * @param {Number} transactionid The transaction ID of the AJAX request (unique)
151      * @param {Object} response The response from the AJAX request.
152      * @param {Object} args The arguments given to the request.
153      * @return {Boolean}
154      */
155     movedown : function(transactionid, response, args) {
156         var node,
157             next,
158             nodeup,
159             nodedown,
160             nextup,
161             nextdown,
162             tmpnode,
163             outcome = this.checkAjaxResponse(transactionid, response, args);
164         if (outcome === false) {
165             Y.log('AJAX request to move '+this.get('itemname')+' down failed by outcome.', 'warn', 'moodle-course-management');
166             return false;
167         }
168         node = this.get('node');
169         next = node.next('.listitem');
170         if (next) {
171             node.insert(next, 'before');
172             nextdown = next.one(' > div a.action-movedown');
173             nodeup = node.one(' > div a.action-moveup');
174             if (!nextdown || !nodeup) {
175                 // next up and node down should always be there. They would be required to trigger the action.
176                 nextup = next.one(' > div a.action-moveup');
177                 nodedown = node.one(' > div a.action-movedown');
178                 if (!nextdown && !nodeup) {
179                     // We can have two situations here:
180                     //   1. nextdown is not set and nodeup is not set. This happens when there are only two courses.
181                     //   2. nodeup is not set. This happens when we are moving the first course down.
182                     // Ok, must be two courses. We need to switch the up and down icons.
183                     tmpnode = Y.Node.create('<a style="visibility:hidden;">&nbsp;</a>');
184                     nextup.replace(tmpnode);
185                     nodedown.replace(nextup);
186                     tmpnode.replace(nodedown);
187                     tmpnode.destroy();
188                 } else if (!nodeup) {
189                     // next up needs to be given to node.
190                     nodedown.insert(nextup, 'before');
191                 }
192             }
193             nodedown = node.one(' > div a.action-movedown');
194             if (nodedown) {
195                 // Try to ensure the up is focused again.
196                 nodedown.focus();
197             } else {
198                 // If we can't focus up we're at the top, try to focus on down.
199                 nodeup = node.one(' > div a.action-moveup');
200                 if (nodeup) {
201                     nodeup.focus();
202                 }
203             }
204             this.updated(true);
205             Y.log('Success: '+this.get('itemname')+' moved down by AJAX.', 'info', 'moodle-course-management');
206         } else {
207             // Aha it succeeded but this is the bottom item in the list. Pagination is in play!
208             // Refresh to update the state of things.
209             Y.log(this.get('itemname')+' cannot be moved down as its the top item on this page.', 'info', 'moodle-course-management');
210             window.location.reload();
211         }
212     },
214     /**
215      * Makes an item visible.
216      *
217      * @method show
218      * @param {Number} transactionid The transaction ID of the AJAX request (unique)
219      * @param {Object} response The response from the AJAX request.
220      * @param {Object} args The arguments given to the request.
221      * @return {Boolean}
222      */
223     show : function(transactionid, response, args) {
224         var outcome = this.checkAjaxResponse(transactionid, response, args),
225             hidebtn;
226         if (outcome === false) {
227             Y.log('AJAX request to show '+this.get('itemname')+' by outcome.', 'warn', 'moodle-course-management');
228             return false;
229         }
231         this.markVisible();
232         hidebtn = this.get('node').one('a[data-action=hide]');
233         if (hidebtn) {
234             hidebtn.focus();
235         }
236         this.updated();
237         Y.log('Success: '+this.get('itemname')+' made visible by AJAX.', 'info', 'moodle-course-management');
238     },
240     /**
241      * Marks the item as visible
242      * @method markVisible
243      */
244     markVisible : function() {
245         this.get('node').setAttribute('data-visible', '1');
246         Y.log('Marked '+this.get('itemname')+' as visible', 'info', 'moodle-course-management');
247         return true;
248     },
250     /**
251      * Hides an item.
252      *
253      * @method hide
254      * @param {Number} transactionid The transaction ID of the AJAX request (unique)
255      * @param {Object} response The response from the AJAX request.
256      * @param {Object} args The arguments given to the request.
257      * @return {Boolean}
258      */
259     hide : function(transactionid, response, args) {
260         var outcome = this.checkAjaxResponse(transactionid, response, args),
261             showbtn;
262         if (outcome === false) {
263             Y.log('AJAX request to hide '+this.get('itemname')+' by outcome.', 'warn', 'moodle-course-management');
264             return false;
265         }
266         this.markHidden();
267         showbtn = this.get('node').one('a[data-action=show]');
268         if (showbtn) {
269             showbtn.focus();
270         }
271         this.updated();
272         Y.log('Success: '+this.get('itemname')+' made hidden by AJAX.', 'info', 'moodle-course-management');
273     },
275     /**
276      * Marks the item as hidden.
277      * @method makeHidden
278      */
279     markHidden : function() {
280         this.get('node').setAttribute('data-visible', '0');
281         Y.log('Marked '+this.get('itemname')+' as hidden', 'info', 'moodle-course-management');
282         return true;
283     },
285     /**
286      * Called when ever a node is updated.
287      *
288      * @method updated
289      * @param {Boolean} moved True if this item was moved.
290      */
291     updated : function(moved) {
292         if (moved) {
293             this.highlight();
294         }
295     },
297     /**
298      * Highlights this option for a breif time.
299      *
300      * @method highlight
301      */
302     highlight : function() {
303         var node = this.get('node');
304         node.siblings('.highlight').removeClass('highlight');
305         node.addClass('highlight');
306         if (this.highlighttimeout) {
307             window.clearTimeout(this.highlighttimeout);
308         }
309         this.highlighttimeout = window.setTimeout(function(){
310             node.removeClass('highlight');
311         }, 2500);
312     }
314 Y.extend(Item, Y.Base, Item.prototype);