8905e7a6010667cc458d3b7fbecbe6229cb040eb
[fnpeditor.git] / src / editor / plugins / core / edumed / order / view.js
1 define(function(require) {
2     
3 'use strict';
4 var $ = require('libs/jquery');
5
6 var _ = require('libs/underscore'),
7     Backbone = require('libs/backbone'),
8     viewTemplate = require('libs/text!./view.html'),
9     viewItemTemplate = require('libs/text!./viewItem.html');
10
11
12 var OrderExerciseView = function(element) {
13     this.element = element;
14     this.dom = $(_.template(viewTemplate)());
15     this.modePills = this.dom.find('.modePills');
16     this.list = this.dom.find('ol');
17     this.addButton = this.dom.find('button.add');
18     this.description = this.dom.find('.description');
19     this.itemViews = [];
20
21     this.addButton.on('click', function(e) {
22         e.stopPropagation();
23         e.preventDefault();
24         this.trigger('newItemRequested');
25         //_.last(this.itemViews).editStart();
26     }.bind(this));
27
28     this.modePills.find('a').on('click', function(e) {
29         e.stopPropagation();
30         e.preventDefault();
31         this.setMode($(e.target).parent().attr('mode'));
32     }.bind(this));
33
34     this.mode = 'initial';
35
36     var dropTargets = this.dom.find('.placeholder-top');
37
38     dropTargets.on('dragend', function() {
39         dropTargets.removeClass('dragged');
40     });
41
42     dropTargets.on('dragenter', function() {
43         var first = this.itemViews[0];
44         if(this.mode === 'correct') {
45             first = this.itemViews.slice(0)
46                 .sort(function(view1, view2) {
47                     if(view1.item.getAnswer() > view2.item.getAnswer()) {
48                         return 1;
49                     }
50                     return -1;
51                 })[0];
52         }
53         if(!this.allowDropAt(first, true)) {
54             return;
55         }
56         dropTargets.addClass('active');
57     }.bind(this));
58
59     dropTargets.on('dragleave', function() {
60         dropTargets.removeClass('active');
61     }.bind(this));
62
63     dropTargets.on('dragover', function(e) {
64         e.preventDefault();
65         e.originalEvent.dataTransfer.dropEffect = 'move';
66     });
67
68     dropTargets.on('drop', function(e) {
69         var vid = e.originalEvent.dataTransfer.getData('text');
70         var droppedItem = $('[vid='+vid+']').data('viewInstance');
71
72         var first = this.itemViews[0];
73         if(this.mode === 'correct') {
74             first = this.itemViews.slice(0)
75                 .sort(function(view1, view2) {
76                     if(view1.item.getAnswer() > view2.item.getAnswer()) {
77                         return 1;
78                     }
79                     return -1;
80                 })[0];
81         }
82
83         this.trigger(this.mode === 'initial' ? 'moveItem' : 'moveAnswer', droppedItem.item, first.item, 'before');
84         dropTargets.removeClass('active');
85     }.bind(this));
86 };
87 _.extend(OrderExerciseView.prototype, Backbone.Events, {
88     addItem: function(item) {
89         var view = new ItemView(item, this);
90         view.on('edit', function(text) {
91             this.trigger('itemEdited', item, text);
92         }.bind(this));
93         view.on('receivedDrop', function(droppedItem) {
94             this.trigger(this.mode === 'initial' ? 'moveItem' : 'moveAnswer', droppedItem.item, item, 'after');
95         }.bind(this));
96         view.on('dragStarted', function(view) {
97             this.draggedView = view;
98         }.bind(this));
99         this.list.append(view.dom);
100         this.itemViews.push(view);
101
102         if(this.mode === 'correct') {
103             this.setMode(this.mode);
104         }
105     },
106     clearItems: function() {
107         this.list.empty();
108         this.itemViews.forEach(function(view) {
109             view.remove();
110         });
111         this.itemViews = [];
112     },
113     setMode: function(mode) {
114         this.modePills.find('li').removeClass('active');
115         this.modePills.find('[mode='+mode+']').addClass('active');
116         this.mode = mode;
117         this.list.children().detach();
118
119         if(this.mode === 'initial') {
120             this.itemViews.forEach(function(itemView) {
121                 this.list.append(itemView.dom);
122             }.bind(this));
123         } else {
124             this.itemViews.slice(0)
125                 .sort(function(view1, view2) {
126                     if(view1.item.getAnswer() > view2.item.getAnswer()) {
127                         return 1;
128                     }
129                     return -1;
130                 })
131                 .forEach(function(itemView) {
132                     this.list.append(itemView.dom);
133                 }.bind(this));
134         }
135     },
136     allowDropAt: function(view, up) {
137         var arr = [this.draggedView.dom[0]];
138         if(!up) {
139             arr.push(this.draggedView.dom.prev()[0]);
140         }
141         return !_.contains(arr, view.dom[0]);
142     }
143 });
144
145 var ItemView = function(item, exerciseView) {
146     this.item = item;
147     this.exerciseView = exerciseView;
148     this.dom = $(_.template(viewItemTemplate)());
149     this.content = this.dom.find('.content');
150
151
152     var dropTargets = this.dom.find('.placeholder'),
153         dragSources = this.dom.find('.wrapper');
154
155     dragSources.on('dragstart', function(e) {
156         this.dom.addClass('dragged');
157         e.originalEvent.dataTransfer.setData('text', this.dom.attr('vid'));
158         e.originalEvent.effectAllowed = 'move';
159         this.trigger('dragStarted', this);
160
161     }.bind(this));
162
163     dropTargets.on('dragend', function() {
164         this.dom.removeClass('dragged');
165     });
166
167     dropTargets.on('dragenter', function() {
168         if(!this.exerciseView.allowDropAt(this)) {
169             return;
170         }
171         dropTargets.addClass('active');
172     }.bind(this));
173
174     dropTargets.on('dragleave', function() {
175         dropTargets.removeClass('active');
176     }.bind(this));
177
178     dropTargets.on('dragover', function(e) {
179         e.preventDefault();
180         e.originalEvent.dataTransfer.dropEffect = 'move';
181     });
182
183     dropTargets.on('drop', function(e) {
184         var vid = e.originalEvent.dataTransfer.getData('text');
185         var droppedItem = $('[vid='+vid+']').data('viewInstance');
186         e.preventDefault();
187         this.trigger('receivedDrop', droppedItem);
188     }.bind(this));
189
190     var content = this.content;
191     this.container = exerciseView.element.createContainer(item.node.contents(), {
192         resetBackground: true,
193         manages: function(node, originaParent) {
194             return item.node.sameNode(node.parent() || originaParent);
195         },
196         dom: content
197     });
198
199     this.dom.data('viewInstance', this);
200     this.dom.attr('vid', _.uniqueId());
201 };
202
203 _.extend(ItemView.prototype, Backbone.Events, {
204     remove: function() {
205         this.container.remove();
206     }
207 });
208
209 return OrderExerciseView;
210
211 });
212
213