Merge branch 'MDL-67818-check-api-fixes' of https://github.com/brendanheywood/moodle
[moodle.git] / course / yui / src / dragdrop / js / resource.js
1 /**
2  * Resource drag and drop.
3  *
4  * @class M.course.dragdrop.resource
5  * @constructor
6  * @extends M.core.dragdrop
7  */
8 var DRAGRESOURCE = function() {
9     DRAGRESOURCE.superclass.constructor.apply(this, arguments);
10 };
11 Y.extend(DRAGRESOURCE, M.core.dragdrop, {
12     initializer: function() {
13         // Set group for parent class
14         this.groups = ['resource'];
15         this.samenodeclass = CSS.ACTIVITY;
16         this.parentnodeclass = CSS.SECTION;
18         this.samenodelabel = {
19             identifier: 'afterresource',
20             component: 'moodle'
21         };
22         this.parentnodelabel = {
23             identifier: 'totopofsection',
24             component: 'moodle'
25         };
27         // Go through all sections
28         var sectionlistselector = M.course.format.get_section_selector(Y);
29         if (sectionlistselector) {
30             sectionlistselector = '.' + CSS.COURSECONTENT + ' ' + sectionlistselector;
31             this.setup_for_section(sectionlistselector);
33             // Initialise drag & drop for all resources/activities
34             var nodeselector = sectionlistselector.slice(CSS.COURSECONTENT.length + 2) + ' li.' + CSS.ACTIVITY;
35             var del = new Y.DD.Delegate({
36                 container: '.' + CSS.COURSECONTENT,
37                 nodes: nodeselector,
38                 target: true,
39                 handles: ['.' + CSS.EDITINGMOVE],
40                 dragConfig: {groups: this.groups}
41             });
42             del.dd.plug(Y.Plugin.DDProxy, {
43                 // Don't move the node at the end of the drag
44                 moveOnEnd: false,
45                 cloneNode: true
46             });
47             del.dd.plug(Y.Plugin.DDConstrained, {
48                 // Keep it inside the .course-content
49                 constrain: '#' + CSS.PAGECONTENT
50             });
51             del.dd.plug(Y.Plugin.DDWinScroll);
53             M.course.coursebase.register_module(this);
54             M.course.dragres = this;
55         }
56     },
58     /**
59      * Apply dragdrop features to the specified selector or node that refers to section(s)
60      *
61      * @method setup_for_section
62      * @param {String} baseselector The CSS selector or node to limit scope to
63      */
64     setup_for_section: function(baseselector) {
65         Y.Node.all(baseselector).each(function(sectionnode) {
66             var resources = sectionnode.one('.' + CSS.CONTENT + ' ul.' + CSS.SECTION);
67             // See if resources ul exists, if not create one
68             if (!resources) {
69                 resources = Y.Node.create('<ul></ul>');
70                 resources.addClass(CSS.SECTION);
71                 sectionnode.one('.' + CSS.CONTENT + ' div.' + CSS.SUMMARY).insert(resources, 'after');
72             }
73             resources.setAttribute('data-draggroups', this.groups.join(' '));
74             // Define empty ul as droptarget, so that item could be moved to empty list
75             new Y.DD.Drop({
76                 node: resources,
77                 groups: this.groups,
78                 padding: '20 0 20 0'
79             });
81             // Initialise each resource/activity in this section
82             this.setup_for_resource('#' + sectionnode.get('id') + ' li.' + CSS.ACTIVITY);
83         }, this);
84     },
86     /**
87      * Apply dragdrop features to the specified selector or node that refers to resource(s)
88      *
89      * @method setup_for_resource
90      * @param {String} baseselector The CSS selector or node to limit scope to
91      */
92     setup_for_resource: function(baseselector) {
93         Y.Node.all(baseselector).each(function(resourcesnode) {
94             var draggroups = resourcesnode.getData('draggroups');
95             if (!draggroups) {
96                 // This Drop Node has not been set up. Configure it now.
97                 resourcesnode.setAttribute('data-draggroups', this.groups.join(' '));
98                 // Define empty ul as droptarget, so that item could be moved to empty list
99                 new Y.DD.Drop({
100                     node: resourcesnode,
101                     groups: this.groups,
102                     padding: '20 0 20 0'
103                 });
104             }
106             // Replace move icons
107             var move = resourcesnode.one('a.' + CSS.EDITINGMOVE);
108             if (move) {
109                 var sr = move.getData('sectionreturn');
110                 move.replace(this.get_drag_handle(M.util.get_string('movecoursemodule', 'moodle'),
111                              CSS.EDITINGMOVE, CSS.ICONCLASS, true).setAttribute('data-sectionreturn', sr));
112             }
113         }, this);
114     },
116     drag_start: function(e) {
117         // Get our drag object
118         var drag = e.target;
119         if (drag.get('dragNode') === drag.get('node')) {
120             // We do not want to modify the contents of the real node.
121             // They will be the same during a keyboard drag and drop.
122             return;
123         }
124         drag.get('dragNode').setContent(drag.get('node').get('innerHTML'));
125         drag.get('dragNode').all('img.iconsmall').setStyle('vertical-align', 'baseline');
126     },
128     drag_dropmiss: function(e) {
129         // Missed the target, but we assume the user intended to drop it
130         // on the last last ghost node location, e.drag and e.drop should be
131         // prepared by global_drag_dropmiss parent so simulate drop_hit(e).
132         this.drop_hit(e);
133     },
135     drop_hit: function(e) {
136         var drag = e.drag;
137         // Get a reference to our drag node
138         var dragnode = drag.get('node');
139         var dropnode = e.drop.get('node');
141         // Add spinner if it not there
142         var actionarea = dragnode.one(CSS.ACTIONAREA);
143         var spinner = M.util.add_spinner(Y, actionarea);
145         var params = {};
147         // Handle any variables which we must pass back through to
148         var pageparams = this.get('config').pageparams;
149         var varname;
150         for (varname in pageparams) {
151             params[varname] = pageparams[varname];
152         }
154         // Prepare request parameters
155         params.sesskey = M.cfg.sesskey;
156         params.courseId = this.get('courseid');
157         params['class'] = 'resource';
158         params.field = 'move';
159         params.id = Number(Y.Moodle.core_course.util.cm.getId(dragnode));
160         params.sectionId = Y.Moodle.core_course.util.section.getId(dropnode.ancestor(M.course.format.get_section_wrapper(Y), true));
162         if (dragnode.next()) {
163             params.beforeId = Number(Y.Moodle.core_course.util.cm.getId(dragnode.next()));
164         }
166         // Do AJAX request
167         var uri = M.cfg.wwwroot + this.get('ajaxurl');
169         Y.io(uri, {
170             method: 'POST',
171             data: params,
172             on: {
173                 start: function() {
174                     this.lock_drag_handle(drag, CSS.EDITINGMOVE);
175                     spinner.show();
176                 },
177                 success: function(tid, response) {
178                     var responsetext = Y.JSON.parse(response.responseText);
179                     var params = {element: dragnode, visible: responsetext.visible};
180                     M.course.coursebase.invoke_function('set_visibility_resource_ui', params);
181                     this.unlock_drag_handle(drag, CSS.EDITINGMOVE);
182                     window.setTimeout(function() {
183                         spinner.hide();
184                     }, 250);
185                 },
186                 failure: function(tid, response) {
187                     this.ajax_failure(response);
188                     this.unlock_drag_handle(drag, CSS.SECTIONHANDLE);
189                     spinner.hide();
190                     // TODO: revert nodes location
191                 }
192             },
193             context: this
194         });
195     }
196 }, {
197     NAME: 'course-dragdrop-resource',
198     ATTRS: {
199         courseid: {
200             value: null
201         },
202         ajaxurl: {
203             value: 0
204         },
205         config: {
206             value: 0
207         }
208     }
209 });
211 M.course = M.course || {};
212 M.course.init_resource_dragdrop = function(params) {
213     new DRAGRESOURCE(params);
214 };