some other minor changes from milpeer
[fnpeditor.git] / src / editor / plugins / core / edumed / order / element.js
1 define(function(require) {
2     
3 'use strict';
4
5 /* globals gettext */
6
7 var _ = require('libs/underscore');
8
9 var elementBase = require('plugins/core/edumed/elementBase'),
10     OrderExerciseView = require('./view');
11
12 var OrderExerciseElement = Object.create(elementBase);
13 _.extend(OrderExerciseElement, {
14     init: function() {
15         elementBase.init.call(this);
16         
17         this.view = new OrderExerciseView(this, this.wlxmlNode);
18         this._container().append(this.view.dom);
19
20         this.view.on('newItemRequested', function() {
21             this.wlxmlNode.document.transaction(function() {
22                 var textNode = this.wlxmlNode.object.addItem('');
23                 var doc = this.wlxmlNode.document;
24                 return doc.createFragment(doc.CaretFragment, {node: textNode, offset:0});
25             }.bind(this), {
26                 metadata: {
27                     description: gettext('Add item to exercise')
28                 },
29                 success: function(ret) {
30                     this.canvas.select(ret);
31                 }.bind(this)
32             });
33         }.bind(this));
34
35         this.view.on('moveAnswer', function(sourceItem, targetItem, where) {
36             this.wlxmlNode.document.transaction(function() {
37                 sourceItem.setAnswer(targetItem.getAnswer() + (where === 'before' ? 0 : 1));
38             }, {
39                 metadata: {
40                     description: gettext('Change solution')
41                 }
42             });
43         }.bind(this));
44
45         this.view.on('moveItem', function(sourceItem, targetItem, where) {
46             this.wlxmlNode.document.transaction(function() {
47                 targetItem.node[where](sourceItem.node);
48             }, {
49                 metadata: {
50                     description: gettext('Change order')
51                 }
52             });
53             
54         }.bind(this));
55
56         this.view.on('shuffleItems', function () {
57             this.wlxmlNode.document.transaction(function() {
58                 this.shuffleItems();
59             }.bind(this), {
60                 metadata: {
61                     description: gettext('Set random order')
62                 }
63             });
64         }.bind(this));
65
66         var exerciseNode = this.wlxmlNode;
67         this.createContainer(this.wlxmlNode.object.getDescription(), {
68             resetBackground: true,
69             manages: function(node, removedFrom) {
70                 if(node.is('list.orderable') || (removedFrom && removedFrom.is('list.orderable'))) {
71                     return false;
72                 }
73                 return exerciseNode.sameNode(node.parent() || removedFrom); //!n.hasFollowingSibing(this.params.listnode);    
74             },
75             dom: this.view.dom.find('.description')
76         });
77
78         this.reloadView();
79     },
80     onNodeAdded: function(event) {
81         var node = event.meta.node;
82         if(this.wlxmlNode.object.isItemNode(node)) {
83             this.reloadView();
84         }
85     },
86     onNodeAttrChange: function(event) {
87         var node = event.meta.node;
88         if(node.is('item.answer') && node.parent() && node.parent().is('list.orderable')) {
89             this.reloadView();
90         }
91     },
92     onNodeDetached: function(event) {
93         var node = event.meta.node;
94         if(node.is('item.answer') && event.meta.parent && event.meta.parent.is('list.orderable')) {
95             this.reloadView();
96             this.updateNumbers();
97         }
98     },
99     reloadView: function() {
100         this.view.clearItems();
101         this.wlxmlNode.object.getItems().forEach(function(item) {
102             this.view.addItem(item);
103         }.bind(this));
104     },
105     updateNumbers: function () {
106         var answer = 1;
107         this.view.sortedItemViews().forEach(function (itemView) {
108             itemView.item.setAnswer(answer);
109             answer++;
110         })
111     },
112     shuffleItems: function () {
113         var items = this.wlxmlNode.object.getItems();
114         var currentIndex = items.length, randomIndex;
115         while (0 !== currentIndex) {
116             randomIndex = Math.floor(Math.random() * currentIndex);
117             currentIndex -= 1;
118             items[currentIndex].node.after(items[randomIndex].node);
119         }
120         this.reloadView();
121     },
122     getVerticallyFirstTextElement: function() {
123         var toret;
124         this.containers.some(function(container) {
125             toret = container.getVerticallyFirstTextElement();
126             return !!toret;
127         });
128         return toret;
129     }
130 });
131
132 return {tag: 'div', klass: 'exercise.order', prototype: OrderExerciseElement};
133
134 });