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.addButton = this.dom.find('button.add');
18 this.description = this.dom.find('.description');
21 this.addButton.on('click', function(e) {
24 this.trigger('newItemRequested');
25 //_.last(this.itemViews).editStart();
28 this.modePills.find('a').on('click', function(e) {
31 this.setMode($(e.target).parent().attr('mode'));
34 this.mode = 'initial';
36 var dropTargets = this.dom.find('.placeholder-top');
38 dropTargets.on('dragend', function() {
39 dropTargets.removeClass('dragged');
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()) {
53 if(!this.allowDropAt(first, true)) {
56 dropTargets.addClass('active');
59 dropTargets.on('dragleave', function() {
60 dropTargets.removeClass('active');
63 dropTargets.on('dragover', function(e) {
65 e.originalEvent.dataTransfer.dropEffect = 'move';
68 dropTargets.on('drop', function(e) {
69 var vid = e.originalEvent.dataTransfer.getData('text');
70 var droppedItem = $('[vid='+vid+']').data('viewInstance');
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()) {
83 this.trigger(this.mode === 'initial' ? 'moveItem' : 'moveAnswer', droppedItem.item, first.item, 'before');
84 dropTargets.removeClass('active');
88 _.extend(OrderExerciseView.prototype, Backbone.Events, {
89 addItem: function(item) {
90 var view = new ItemView(item, this);
91 view.on('edit', function(text) {
92 this.trigger('itemEdited', item, text);
94 view.on('receivedDrop', function(droppedItem) {
95 this.trigger(this.mode === 'initial' ? 'moveItem' : 'moveAnswer', droppedItem.item, item, 'after');
97 view.on('dragStarted', function(view) {
98 this.draggedView = view;
100 this.list.append(view.dom);
101 this.itemViews.push(view);
103 if(this.mode === 'correct') {
104 this.setMode(this.mode);
107 clearItems: function() {
109 this.itemViews.forEach(function(view) {
114 setMode: function(mode) {
115 this.modePills.find('li').removeClass('active');
116 this.modePills.find('[mode='+mode+']').addClass('active');
118 this.list.children().detach();
120 if(this.mode === 'initial') {
121 this.itemViews.forEach(function(itemView) {
122 this.list.append(itemView.dom);
125 this.itemViews.slice(0)
126 .sort(function(view1, view2) {
127 if(view1.item.getAnswer() > view2.item.getAnswer()) {
132 .forEach(function(itemView) {
133 this.list.append(itemView.dom);
137 allowDropAt: function(view, up) {
138 var arr = [this.draggedView.dom[0]];
140 arr.push(this.draggedView.dom.prev()[0]);
142 return !_.contains(arr, view.dom[0]);
146 var ItemView = function(item, exerciseView) {
148 this.exerciseView = exerciseView;
149 this.dom = $(_.template(viewItemTemplate)());
150 this.content = this.dom.find('.content');
153 var dropTargets = this.dom.find('.placeholder'),
154 dragSources = this.dom.find('.handle');
156 dragSources.on('dragstart', function(e) {
157 this.dom.addClass('dragged');
158 e.originalEvent.dataTransfer.setData('text', this.dom.attr('vid'));
159 e.originalEvent.effectAllowed = 'move';
160 this.trigger('dragStarted', this);
164 dropTargets.on('dragend', function() {
165 this.dom.removeClass('dragged');
168 dropTargets.on('dragenter', function() {
169 if(!this.exerciseView.allowDropAt(this)) {
172 dropTargets.addClass('active');
175 dropTargets.on('dragleave', function() {
176 dropTargets.removeClass('active');
179 dropTargets.on('dragover', function(e) {
181 e.originalEvent.dataTransfer.dropEffect = 'move';
184 dropTargets.on('drop', function(e) {
185 var vid = e.originalEvent.dataTransfer.getData('text');
186 var droppedItem = $('[vid='+vid+']').data('viewInstance');
188 this.trigger('receivedDrop', droppedItem);
191 var content = this.content;
192 this.container = exerciseView.element.createContainer(item.node.contents(), {
193 resetBackground: true,
194 manages: function(node, originaParent) {
195 return item.node.sameNode(node.parent() || originaParent);
200 this.dom.data('viewInstance', this);
201 this.dom.attr('vid', _.uniqueId());
204 _.extend(ItemView.prototype, Backbone.Events, {
206 this.container.remove();
210 return OrderExerciseView;