'use strict';
var _ = require('libs/underscore'),
+ smartxmlTransformations = require('smartxml/transformations'),
metadataKey = 'wlxml.metadata';
-var methods = {
- getMetadata: function() {
- return this.getData(metadataKey) || [];
- }
+var Row = function(key, value, metadata) {
+ this.key = key || '';
+ this.value = value || '';
+ this.metadata = metadata;
};
-var transformations = {
- addMetadataRow: function(row) {
- this.setMetadataRow(null, row);
+_.extend(Row.prototype, {
+ ChangeProperty: smartxmlTransformations.createContextTransformation({
+ impl: function(t, rowIndex, propName, value) {
+ var row = this.getMetadata().at(rowIndex);
+ if(row.getValue() === value) {
+ return;
+ }
+ t.rowIndex = rowIndex;
+ t.propName = propName;
+ t.oldValue = row[propName];
+ row[propName] = value;
+ this.triggerChangeEvent('metadataChanged', {row:row});
+ },
+ undo: function(t) {
+ var row = this.getMetadata().at(t.rowIndex);
+ row[t.propName] = t.oldValue;
+ this.triggerChangeEvent('metadataChanged', {row:row});
+ }
+ }),
+
+ setKey: function(key) {
+ return this.metadata.node.transform(this.ChangeProperty, [this.getIndex(), 'key', key]);
+ },
+ getKey: function() {
+ return this.key;
},
+ setValue: function(value) {
+ return this.metadata.node.transform(this.ChangeProperty, [this.getIndex(), 'value', value]);
+ },
+ getValue: function() {
+ return this.value;
+ },
+ remove: function() {
+ this.metadata.remove(this);
+ },
+ getIndex: function() {
+ return this.metadata.indexOf(this);
+ }
+});
+
+
+var Metadata = function(node) {
+ this._rows = [];
+ Object.defineProperty(this, 'length', {
+ get: function() {
+ return this._rows.length;
+ }
+ });
+ this.node = node;
+};
+
+_.extend(Metadata.prototype, {
+ Add: smartxmlTransformations.createContextTransformation({
+ impl: function(t, rowDesc) {
+ var metadata = this.getMetadata(),
+ row = new Row(rowDesc.key, rowDesc.value, metadata);
+ metadata._rows.push(row);
+ t.rowIdx = row.getIndex();
+ this.triggerChangeEvent('metadataAdded', {row: row});
+ return row;
+ },
+ undo: function(t) {
+ this.getMetadata().at(t.rowIdx).remove();
+ }
+ }),
- setMetadataRow: function(index, row) {
- var metadata = this.getData(metadataKey) || [];
- if(typeof index !== 'number' || index > metadata.length - 1) {
- metadata.push(row);
- index = metadata.length - 1;
+ Remove: smartxmlTransformations.createContextTransformation({
+ impl: function(t, rowIdx) {
+ var metadata = this.getMetadata();
+ t.rowIdx = rowIdx;
+ t.row = metadata.at(rowIdx);
+ metadata._rows.splice(rowIdx, 1);
+ this.triggerChangeEvent('metadataRemoved', {row: t.row});
+ },
+ undo: function(t) {
+ var metadata = this.getMetadata(),
+ row = new Row(t.row.getKey(), t.row.getValue(), metadata);
+ metadata._rows.splice(t.rowIdx, 0, row);
+ this.triggerChangeEvent('metadataAdded', {row: row});
+ }
+ }),
+
+ _iter: function(method, callback, key) {
+ return this._rows
+ .filter(function(row) { return !key || row.getKey() === key; })
+ [method](function(row) { return callback(row); });
+ },
+ forEach: function(callback, key) {
+ return this._iter('forEach', callback, key);
+ },
+ some: function(callback, key) {
+ return this._iter('some', callback, key);
+ },
+ add: function(rowDesc, options) {
+ var row;
+ options = _.extend({undoable: true}, options);
+ if(options.undoable) {
+ return this.node.transform(this.Add, [rowDesc]);
} else {
- metadata[index] = _.extend(metadata[index], row);
+ row = new Row(rowDesc.key, rowDesc.value, this);
+ this._rows.push(row);
+ return row;
+ }
+ },
+ at: function(idx) {
+ return this._rows[idx];
+ },
+ indexOf: function(row) {
+ var idx = this._rows.indexOf(row);
+ if(idx !== -1) {
+ return idx;
}
- this.setData(metadataKey, metadata);
- this.triggerChangeEvent('metadataChange', {index: index});
+ return undefined;
+ },
+ remove: function(row) {
+ var idx = this.indexOf(row);
+ if(typeof idx !== 'undefined') {
+ this.node.transform(this.Remove, [idx]);
+ }
+ },
+ clone: function(node) {
+ var clone = new Metadata(node);
+ this._rows.forEach(function(row) {
+ clone._rows.push(new Row(row.getKey(), row.getValue(), clone));
+ });
+ return clone;
}
-};
+});
+
return {
elementNode: {
- methods: methods,
- transformations: transformations,
+ methods: {
+ getMetadata: function() {
+ if(!this.getData(metadataKey)) {
+ this.setData(metadataKey, new Metadata(this));
+ }
+ return this.getData(metadataKey);
+ }
+ }
}
};