18434e57aa4534a3d77d4ac66ba12f54148d4fbb
[fnpeditor.git] / src / editor / plugins / core / metadataEditor / view.js
1 define([
2 'libs/jquery',
3 'libs/underscore',
4 'libs/text!./templates/main.html',
5 'libs/text!./templates/item.html',
6 'views/openSelect/openSelect',
7 'views/attachments/attachments'
8 ], function($, _, mainTemplate, itemTemplate, OpenSelectView, attachments) {
9
10 'use strict';
11 /* globals gettext */
12
13
14 var View = function(node, metadataConfig) {
15     this.node = node;
16     this.metadataConfig = metadataConfig;
17     this.dom = $(_.template(mainTemplate)());
18     this.adding = false;
19
20     var metaTable = this.metaTable = this.dom.find('table');
21     
22     this.dom.find('.rng-module-metadataEditor-addBtn').click(function() {
23         this.adding = true;
24         this.node.document.transaction(function() {
25             this.node.getMetadata().add('','');
26         }.bind(this), {
27             metadata: {
28                 description: gettext('Add metadata row')
29             }
30         });
31     }.bind(this));
32     
33     this.metaTable.on('click', '.rng-visualEditor-metaRemoveBtn', function(e) {
34         this.node.document.transaction(function() {
35             $(e.target).closest('tr').data('row').remove();
36         }, {
37             metadata: {
38                 description: gettext('Remove metadata row')
39             }
40         });
41     }.bind(this));
42     
43     this.metaTable.on('keydown', '[contenteditable]', function(e) {
44         /* globals document */
45         if(e.which === 13) {
46             if($(document.activeElement).hasClass('rng-module-metadataEditor-metaItemKey')) {
47                 metaTable.find('.rng-module-metadataEditor-metaItemValue').focus();
48             } else {
49                 var input = $('<input>');
50                 input.appendTo('body').focus();
51                 this.dom.find('.rng-module-metadataEditor-addBtn').focus();
52                 input.remove();
53             }
54             e.preventDefault();
55         }
56     }.bind(this));
57
58     this.metaTable.on('keyup', '[contenteditable]', _.throttle(function(e) {
59         if(e.which !== 13) {
60             var editable = $(e.target),
61                 toSet = editable.text(),
62                 row = editable.parents('tr').data('row'),
63                 isKey = _.last(editable.attr('class').split('-')) === 'metaItemKey',
64                 method = isKey ? 'setKey' : 'setValue';
65             row.metadata.node.document.transaction(function() {
66                 row[method](toSet);
67             }, {
68                 metadata: {
69                     description: gettext('Metadata edit')
70                 }
71             });
72         }
73     }, 500));
74
75     this.setMetadata(this.node); //
76
77     this.node.document.on('change', this.handleEvent, this);
78 };
79
80 _.extend(View.prototype, {
81     close: function() {
82         this.node.document.off('change', this.handleEvent);
83     },
84     handleEvent: function(event) {
85         if(event.type === 'metadataAdded' && event.meta.node.sameNode(this.node)) {
86             this.addMetadataRow(event.meta.row);
87         }
88         if(event.type === 'metadataChanged' && event.meta.node.sameNode(this.node)) {
89             this.updateMetadataRow(event.meta.row);
90         }
91         if(event.type === 'metadataRemoved' && event.meta.node.sameNode(this.node)) {
92             this.removeMetadataRow(event.meta.row);
93         }
94         if(event.type === 'nodeDetached' && event.meta.node.containsNode(this.node)) {
95             this.setMetadata(null);
96         }
97     },
98     getValuesForKey: function(key) {
99         var toret = [];
100         this.metadataConfig.some(function(configRow) {
101             if(configRow.key === key) {
102                 toret = configRow.values || [];
103                 return true;
104             }
105         });
106         return toret;
107     },
108     getIsFileForKey: function(key) {
109         var toret = false;
110         this.metadataConfig.some(function(configRow) {
111             if (configRow.key == key) {
112                 toret = configRow.isFile || false;
113                 return true
114             }
115         });
116         return toret;
117     },
118     setMetadata: function(node) {
119         this.dom.find('.rng-module-metadataEditor-addBtn').attr('disabled', !node);
120         if(!node) {
121             this.metaTable.html('');
122             return;
123         }
124         var view = this,
125             metadata = node.getMetadata();
126         this.metaTable.find('tr').remove();
127         metadata.forEach(function(row) {
128             view.addMetadataRow(row);
129         });
130     },
131     addMetadataRow: function(row) {
132         console.log(row);
133         var newRow = $(_.template(itemTemplate)({key: row.getKey() || '', value: row.getValue() || ''}));
134         newRow.appendTo(this.metaTable);
135         newRow.data('row', row);
136
137         var keySelectView = new OpenSelectView({
138             value: row.getKey() || '',
139             inputTemplate: _.template('<div class="openInput rng-module-metadataEditor-metaItemKey" contentEditable="true"><%= value %></div>')({value: row.getKey() || '' }),
140             setInput: function(inputDOM, value) {
141                 if(inputDOM.text() !== value) {
142                     inputDOM.text(value);
143                     row.setKey(value);
144                 }
145                 valueSelectView.clearItems();
146                 this.getValuesForKey(value).forEach(function(value) {
147                     valueSelectView.addItem(value);
148                 });
149                 
150             }.bind(this)
151         });
152         newRow.find('td:first').append(keySelectView.el).data('view', keySelectView);
153
154
155         var valueSelectView = new OpenSelectView({
156             value: row.getValue(),
157             inputTemplate: _.template('<div class="openInput rng-module-metadataEditor-metaItemValue" contentEditable="true"><%= value %></div>')({value: row.getValue() || '' }),
158             maxHeight: '300px',
159             maxWidth: '100px',
160             setInput: function(inputDOM, value) {
161                 if(inputDOM.text() !== value) {
162                     inputDOM.text(value);
163                     row.setValue(value);
164                 }
165             }
166         });
167         newRow.find('td:nth-child(2)').append(valueSelectView.el).data('view', valueSelectView);
168
169         if (this.getIsFileForKey(row.getKey())) {
170             var el = $("<a href='#-' class='attachment-library' style='float: right'>" + gettext('attachments') + "</a>");
171             el.on('click', function() {
172                 attachments.select(function(v) {
173                     valueSelectView.setInput(v);
174                 });
175                 return false;
176             });
177             newRow.find('td:nth-child(2)').append(el);
178         }
179
180
181         this.metadataConfig.forEach(function(configRow) {
182             keySelectView.addItem(configRow.key);
183             if(row.getKey() === configRow.key) {
184                 (configRow.values || []).forEach(function(value) {
185                     valueSelectView.addItem(value);
186                 });
187             }
188         });
189
190         if(this.adding) {
191             $(newRow.find('td div')[0]).focus();
192             this.adding = false;
193         }
194         return newRow;
195     },
196     updateMetadataRow: function(row) {
197         this._getRowTr(row, function(tr) {
198             var tds = tr.find('td'),
199                 keyTd = $(tds[0]),
200                 valueTd = $(tds[1]);
201
202             keyTd.data('view').setInput(row.getKey());
203             valueTd.data('view').setInput(row.getValue());
204         });
205     },
206     removeMetadataRow: function(row) {
207         this._getRowTr(row, function(tr) {
208             tr.remove();
209         });
210     },
211     _getRowTr: function(row, callback) {
212         this.metaTable.find('tr').each(function() {
213             var tr = $(this);
214             if(tr.data('row') === row) {
215                 callback(tr);
216                 return false;
217             }
218         });
219     }
220 });
221
222
223 return View;
224
225
226 });