1 define(function(require) {
4 var $ = require('libs/jquery');
6 var _ = require('libs/underscore'),
7 Backbone = require('libs/backbone'),
8 viewTemplate = require('libs/text!./view.html'),
9 viewItemTemplate = require('libs/text!./viewItem.html');
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.description = this.dom.find('.description');
20 this.modePills.find('a').on('click', function(e) {
23 this.setMode($(e.target).parent().attr('mode'));
26 this.mode = 'initial';
28 var dropTargets = this.dom.find('.placeholder-top');
30 dropTargets.on('dragend', function() {
31 dropTargets.removeClass('dragged');
34 dropTargets.on('dragenter', function() {
35 var first = this.itemViews[0];
36 if(this.mode === 'correct') {
37 first = this.itemViews.slice(0)
38 .sort(function(view1, view2) {
39 if(view1.item.getAnswer() > view2.item.getAnswer()) {
45 if(!this.allowDropAt(first, true)) {
48 dropTargets.addClass('active');
51 dropTargets.on('dragleave', function() {
52 dropTargets.removeClass('active');
55 dropTargets.on('dragover', function(e) {
57 e.originalEvent.dataTransfer.dropEffect = 'move';
60 dropTargets.on('drop', function(e) {
61 var vid = e.originalEvent.dataTransfer.getData('text');
62 var droppedItem = $('[vid='+vid+']').data('viewInstance');
64 var first = this.itemViews[0];
65 if(this.mode === 'correct') {
66 first = this.itemViews.slice(0)
67 .sort(function(view1, view2) {
68 if(view1.item.getAnswer() > view2.item.getAnswer()) {
75 this.trigger(this.mode === 'initial' ? 'moveItem' : 'moveAnswer', droppedItem.item, first.item, 'before');
76 dropTargets.removeClass('active');
80 _.extend(OrderExerciseView.prototype, Backbone.Events, {
81 addItem: function(item) {
82 var view = new ItemView(item, this);
83 view.on('receivedDrop', function(droppedItem) {
84 this.trigger(this.mode === 'initial' ? 'moveItem' : 'moveAnswer', droppedItem.item, item, 'after');
86 view.on('dragStarted', function(view) {
87 this.draggedView = view;
89 this.list.append(view.dom);
90 this.itemViews.push(view);
92 if(this.mode === 'correct') {
93 this.setMode(this.mode);
96 clearItems: function() {
98 this.itemViews.forEach(function(view) {
103 setMode: function(mode) {
104 this.modePills.find('li').removeClass('active');
105 this.modePills.find('[mode='+mode+']').addClass('active');
107 this.list.children().detach();
109 if(this.mode === 'initial') {
110 this.itemViews.forEach(function(itemView) {
111 this.list.append(itemView.dom);
114 this.itemViews.slice(0)
115 .sort(function(view1, view2) {
116 if(view1.item.getAnswer() > view2.item.getAnswer()) {
121 .forEach(function(itemView) {
122 this.list.append(itemView.dom);
126 allowDropAt: function(view, up) {
127 var arr = [this.draggedView.dom[0]];
129 arr.push(this.draggedView.dom.prev()[0]);
131 return !_.contains(arr, view.dom[0]);
135 var ItemView = function(item, exerciseView) {
137 this.exerciseView = exerciseView;
138 this.dom = $(_.template(viewItemTemplate)());
139 this.content = this.dom.find('.content');
142 var dropTargets = this.dom.find('.placeholder'),
143 dragSources = this.dom.find('.handle');
145 dragSources.on('dragstart', function(e) {
146 this.dom.addClass('dragged');
147 e.originalEvent.dataTransfer.setData('text', this.dom.attr('vid'));
148 e.originalEvent.effectAllowed = 'move';
149 this.trigger('dragStarted', this);
153 dropTargets.on('dragend', function() {
154 this.dom.removeClass('dragged');
157 dropTargets.on('dragenter', function() {
158 if(!this.exerciseView.allowDropAt(this)) {
161 dropTargets.addClass('active');
164 dropTargets.on('dragleave', function() {
165 dropTargets.removeClass('active');
168 dropTargets.on('dragover', function(e) {
170 e.originalEvent.dataTransfer.dropEffect = 'move';
173 dropTargets.on('drop', function(e) {
174 var vid = e.originalEvent.dataTransfer.getData('text');
175 var droppedItem = $('[vid='+vid+']').data('viewInstance');
177 this.trigger('receivedDrop', droppedItem);
180 var content = this.content;
181 this.container = exerciseView.element.createContainer(item.node.contents(), {
182 resetBackground: true,
183 manages: function(node, originaParent) {
184 return item.node.sameNode(node.parent() || originaParent);
189 this.dom.data('viewInstance', this);
190 this.dom.attr('vid', _.uniqueId());
193 _.extend(ItemView.prototype, Backbone.Events, {
195 this.container.remove();
199 return OrderExerciseView;