editor: WrapTextAction plays nice and returns a new document fragment
[fnpeditor.git] / src / fnpjs / actions.js
1 define(function(require) {
2     
3 'use strict';
4
5 var _ = require('libs/underscore'),
6     Backbone = require('libs/backbone'),
7     logging = require('fnpjs/logging/logging');
8
9 var logger = logging.getLogger('fnpjs.actions');
10
11
12 var Action = function(fqName, definition, config, appObject) {
13     this.fqName = fqName;
14     this.definition = definition;
15     this.config = config;
16     this._cache = null;
17     this.appObject = appObject;
18
19     this.params = {};
20 };
21
22 _.extend(Action.prototype, Backbone.Events, {
23     getPluginName: function() {
24         return this.fqName.split('.')[0];
25     },
26     updateParam: function(filter, value) {
27         var changed = false;
28         _.pairs(this.definition.params).forEach(function(pair) {
29             var paramName = pair[0],
30                 paramDesc = pair[1];
31             if(filter(paramDesc, paramName)) {
32                 this.params[paramName] = value;
33                 changed = true;
34             }
35         }.bind(this));
36         if(changed) {
37             this._cache = null;
38             this.trigger('paramsChanged');
39         }
40     },
41     updateContextParam: function(contextName, value) {
42         this.updateParam(function(paramDesc) {
43             return paramDesc.type === 'context' && paramDesc.name === contextName;
44         }, value);
45     },
46     updateKeyParam: function(keyName, toggled) {
47         this.updateParam(function(paramDesc) {
48             return paramDesc.type === 'key' && paramDesc.key === keyName;
49         }, toggled);
50     },
51     updateWidgetParam: function(name, value) {
52         this.updateParam(function(paramDesc, paramName) {
53             return !_.contains(['context', 'key'], paramDesc.type) && paramName === name;
54         }, value);
55     },
56     getState: function() {
57         var gotState;
58         if(!this._cache) {
59             try {
60                 gotState = this.definition.getState.call(this, this.params);
61             } catch(e) {
62                 logger.exception(e);
63                 return;
64             }
65             if(typeof gotState === 'boolean') {
66                 gotState = {allowed: gotState};
67             }
68             this._cache = _.extend({}, this.definition.stateDefaults || {}, gotState);
69         }
70         if(this._cache === false) {
71             this._cache = {allowed: false};
72         }
73         return this._cache;
74     },
75     execute: function(callback) {
76         var state = this.getState();
77         callback = callback || function() {};
78         if(state.allowed) {
79             return state.execute.call(this, callback, this.params, this.appObject);
80         }
81         throw new Error('Execution not allowed');
82     }
83 });
84
85
86 return {
87     Action: Action
88 };
89
90 });