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');
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);
93 view.on('receivedDrop', function(droppedItem) {
94 this.trigger(this.mode === 'initial' ? 'moveItem' : 'moveAnswer', droppedItem.item, item, 'after');
96 view.on('dragStarted', function(view) {
97 this.draggedView = view;
99 this.list.append(view.dom);
100 this.itemViews.push(view);
102 if(this.mode === 'correct') {
103 this.setMode(this.mode);
106 clearItems: function() {
108 this.itemViews.forEach(function(view) {
113 setMode: function(mode) {
114 this.modePills.find('li').removeClass('active');
115 this.modePills.find('[mode='+mode+']').addClass('active');
117 this.list.children().detach();
119 if(this.mode === 'initial') {
120 this.itemViews.forEach(function(itemView) {
121 this.list.append(itemView.dom);
124 this.itemViews.slice(0)
125 .sort(function(view1, view2) {
126 if(view1.item.getAnswer() > view2.item.getAnswer()) {
131 .forEach(function(itemView) {
132 this.list.append(itemView.dom);
136 allowDropAt: function(view, up) {
137 var arr = [this.draggedView.dom[0]];
139 arr.push(this.draggedView.dom.prev()[0]);
141 return !_.contains(arr, view.dom[0]);
145 var ItemView = function(item, exerciseView) {
147 this.exerciseView = exerciseView;
148 this.dom = $(_.template(viewItemTemplate)());
149 this.content = this.dom.find('.content');
152 var dropTargets = this.dom.find('.placeholder'),
153 dragSources = this.dom.find('.wrapper');
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);
163 dropTargets.on('dragend', function() {
164 this.dom.removeClass('dragged');
167 dropTargets.on('dragenter', function() {
168 if(!this.exerciseView.allowDropAt(this)) {
171 dropTargets.addClass('active');
174 dropTargets.on('dragleave', function() {
175 dropTargets.removeClass('active');
178 dropTargets.on('dragover', function(e) {
180 e.originalEvent.dataTransfer.dropEffect = 'move';
183 dropTargets.on('drop', function(e) {
184 var vid = e.originalEvent.dataTransfer.getData('text');
185 var droppedItem = $('[vid='+vid+']').data('viewInstance');
187 this.trigger('receivedDrop', droppedItem);
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);
199 this.dom.data('viewInstance', this);
200 this.dom.attr('vid', _.uniqueId());
203 _.extend(ItemView.prototype, Backbone.Events, {
205 this.container.remove();
209 return OrderExerciseView;