source: Dev/trunk/src/client/dijit/_editor/_Plugin.js

Last change on this file was 483, checked in by hendrikvanantwerpen, 11 years ago

Added Dojo 1.9.3 release.

File size: 9.2 KB
Line 
1define([
2        "dojo/_base/connect", // connect.connect
3        "dojo/_base/declare", // declare
4        "dojo/_base/lang", // lang.mixin, lang.hitch
5        "../Destroyable",
6        "../form/Button"
7], function(connect, declare, lang, Destroyable, Button){
8
9        // module:
10        //              dijit/_editor/_Plugin
11
12        var _Plugin = declare("dijit._editor._Plugin", Destroyable, {
13                // summary:
14                //              Base class for a "plugin" to the editor, which is usually
15                //              a single button on the Toolbar and some associated code
16
17                constructor: function(args){
18                        // summary:
19                        //              Create the plugin.
20                        // args: Object?
21                        //              Initial settings for any of the attributes.
22
23                        this.params = args || {};
24                        lang.mixin(this, this.params);
25                        this._attrPairNames = {};
26                },
27
28                // editor: [const] dijit.Editor
29                //              Points to the parent editor
30                editor: null,
31
32                // iconClassPrefix: [const] String
33                //              The CSS class name for the button node is formed from `iconClassPrefix` and `command`
34                iconClassPrefix: "dijitEditorIcon",
35
36                // button: dijit/_WidgetBase?
37                //              Pointer to `dijit/form/Button` or other widget (ex: `dijit/form/FilteringSelect`)
38                //              that is added to the toolbar to control this plugin.
39                //              If not specified, will be created on initialization according to `buttonClass`
40                button: null,
41
42                // command: String
43                //              String like "insertUnorderedList", "outdent", "justifyCenter", etc. that represents an editor command.
44                //              Passed to editor.execCommand() if `useDefaultCommand` is true.
45                command: "",
46
47                // useDefaultCommand: Boolean
48                //              If true, this plugin executes by calling Editor.execCommand() with the argument specified in `command`.
49                useDefaultCommand: true,
50
51                // buttonClass: Widget Class
52                //              Class of widget (ex: dijit.form.Button or dijit/form/FilteringSelect)
53                //              that is added to the toolbar to control this plugin.
54                //              This is used to instantiate the button, unless `button` itself is specified directly.
55                buttonClass: Button,
56
57                // disabled: Boolean
58                //              Flag to indicate if this plugin has been disabled and should do nothing
59                //              helps control button state, among other things.  Set via the setter api.
60                disabled: false,
61
62                getLabel: function(/*String*/key){
63                        // summary:
64                        //              Returns the label to use for the button
65                        // tags:
66                        //              private
67                        return this.editor.commands[key];               // String
68                },
69
70                _initButton: function(){
71                        // summary:
72                        //              Initialize the button or other widget that will control this plugin.
73                        //              This code only works for plugins controlling built-in commands in the editor.
74                        // tags:
75                        //              protected extension
76                        if(this.command.length){
77                                var label = this.getLabel(this.command),
78                                        editor = this.editor,
79                                        className = this.iconClassPrefix + " " + this.iconClassPrefix + this.command.charAt(0).toUpperCase() + this.command.substr(1);
80                                if(!this.button){
81                                        var props = lang.mixin({
82                                                label: label,
83                                                ownerDocument: editor.ownerDocument,
84                                                dir: editor.dir,
85                                                lang: editor.lang,
86                                                showLabel: false,
87                                                iconClass: className,
88                                                dropDown: this.dropDown,
89                                                tabIndex: "-1"
90                                        }, this.params || {});
91                                        this.button = new this.buttonClass(props);
92                                }
93                        }
94                        if(this.get("disabled") && this.button){
95                                this.button.set("disabled", this.get("disabled"));
96                        }
97                },
98
99                destroy: function(){
100                        if(this.dropDown){
101                                this.dropDown.destroyRecursive();
102                        }
103
104                        this.inherited(arguments);
105                },
106
107                connect: function(o, f, tf){
108                        // summary:
109                        //              Deprecated.  Use this.own() with dojo/on or dojo/aspect.instead.
110                        //
111                        //              Make a connect.connect() that is automatically disconnected when this plugin is destroyed.
112                        //              Similar to `dijit/_Widget.connect()`.
113                        // tags:
114                        //              protected deprecated
115
116                        this.own(connect.connect(o, f, this, tf));
117                },
118
119                updateState: function(){
120                        // summary:
121                        //              Change state of the plugin to respond to events in the editor.
122                        // description:
123                        //              This is called on meaningful events in the editor, such as change of selection
124                        //              or caret position (but not simple typing of alphanumeric keys).   It gives the
125                        //              plugin a chance to update the CSS of its button.
126                        //
127                        //              For example, the "bold" plugin will highlight/unhighlight the bold button depending on whether the
128                        //              characters next to the caret are bold or not.
129                        //
130                        //              Only makes sense when `useDefaultCommand` is true, as it calls Editor.queryCommandEnabled(`command`).
131                        var e = this.editor,
132                                c = this.command,
133                                checked, enabled;
134                        if(!e || !e.isLoaded || !c.length){
135                                return;
136                        }
137                        var disabled = this.get("disabled");
138                        if(this.button){
139                                try{
140                                        enabled = !disabled && e.queryCommandEnabled(c);
141                                        if(this.enabled !== enabled){
142                                                this.enabled = enabled;
143                                                this.button.set('disabled', !enabled);
144                                        }
145                                        if(enabled){
146                                                if(typeof this.button.checked == 'boolean'){
147                                                        checked = e.queryCommandState(c);
148                                                        if(this.checked !== checked){
149                                                                this.checked = checked;
150                                                                this.button.set('checked', e.queryCommandState(c));
151                                                        }
152                                                }
153                                        }
154                                }catch(e){
155                                        console.log(e); // FIXME: we shouldn't have debug statements in our code.  Log as an error?
156                                }
157                        }
158                },
159
160                setEditor: function(/*dijit/Editor*/ editor){
161                        // summary:
162                        //              Tell the plugin which Editor it is associated with.
163
164                        // TODO: refactor code to just pass editor to constructor.
165
166                        // FIXME: detach from previous editor!!
167                        this.editor = editor;
168
169                        // FIXME: prevent creating this if we don't need to (i.e., editor can't handle our command)
170                        this._initButton();
171
172                        // Processing for buttons that execute by calling editor.execCommand()
173                        if(this.button && this.useDefaultCommand){
174                                if(this.editor.queryCommandAvailable(this.command)){
175                                        this.own(this.button.on("click",
176                                                lang.hitch(this.editor, "execCommand", this.command, this.commandArg)
177                                        ));
178                                }else{
179                                        // hide button because editor doesn't support command (due to browser limitations)
180                                        this.button.domNode.style.display = "none";
181                                }
182                        }
183
184                        this.own(this.editor.on("NormalizedDisplayChanged", lang.hitch(this, "updateState")));
185                },
186
187                setToolbar: function(/*dijit/Toolbar*/ toolbar){
188                        // summary:
189                        //              Tell the plugin to add it's controller widget (often a button)
190                        //              to the toolbar.  Does nothing if there is no controller widget.
191
192                        // TODO: refactor code to just pass toolbar to constructor.
193
194                        if(this.button){
195                                toolbar.addChild(this.button);
196                        }
197                        // console.debug("adding", this.button, "to:", toolbar);
198                },
199
200                set: function(/* attribute */ name, /* anything */ value){
201                        // summary:
202                        //              Set a property on a plugin
203                        // name:
204                        //              The property to set.
205                        // value:
206                        //              The value to set in the property.
207                        // description:
208                        //              Sets named properties on a plugin which may potentially be handled by a
209                        //              setter in the plugin.
210                        //              For example, if the plugin has a properties "foo"
211                        //              and "bar" and a method named "_setFooAttr", calling:
212                        //      |       plugin.set("foo", "Howdy!");
213                        //              would be equivalent to writing:
214                        //      |       plugin._setFooAttr("Howdy!");
215                        //              and:
216                        //      |       plugin.set("bar", 3);
217                        //              would be equivalent to writing:
218                        //      |       plugin.bar = 3;
219                        //
220                        //              set() may also be called with a hash of name/value pairs, ex:
221                        //      |       plugin.set({
222                        //      |               foo: "Howdy",
223                        //      |               bar: 3
224                        //      |       })
225                        //              This is equivalent to calling set(foo, "Howdy") and set(bar, 3)
226                        if(typeof name === "object"){
227                                for(var x in name){
228                                        this.set(x, name[x]);
229                                }
230                                return this;
231                        }
232                        var names = this._getAttrNames(name);
233                        if(this[names.s]){
234                                // use the explicit setter
235                                var result = this[names.s].apply(this, Array.prototype.slice.call(arguments, 1));
236                        }else{
237                                this._set(name, value);
238                        }
239                        return result || this;
240                },
241
242                get: function(name){
243                        // summary:
244                        //              Get a property from a plugin.
245                        // name:
246                        //              The property to get.
247                        // description:
248                        //              Get a named property from a plugin. The property may
249                        //              potentially be retrieved via a getter method. If no getter is defined, this
250                        //              just retrieves the object's property.
251                        //              For example, if the plugin has a properties "foo"
252                        //              and "bar" and a method named "_getFooAttr", calling:
253                        //      |       plugin.get("foo");
254                        //              would be equivalent to writing:
255                        //      |       plugin._getFooAttr();
256                        //              and:
257                        //      |       plugin.get("bar");
258                        //              would be equivalent to writing:
259                        //      |       plugin.bar;
260                        var names = this._getAttrNames(name);
261                        return this[names.g] ? this[names.g]() : this[name];
262                },
263
264                _setDisabledAttr: function(disabled){
265                        // summary:
266                        //              Function to set the plugin state and call updateState to make sure the
267                        //              button is updated appropriately.
268                        this._set("disabled", disabled);
269                        this.updateState();
270                },
271
272                _getAttrNames: function(name){
273                        // summary:
274                        //              Helper function for get() and set().
275                        //              Caches attribute name values so we don't do the string ops every time.
276                        // tags:
277                        //              private
278
279                        var apn = this._attrPairNames;
280                        if(apn[name]){
281                                return apn[name];
282                        }
283                        var uc = name.charAt(0).toUpperCase() + name.substr(1);
284                        return (apn[name] = {
285                                s: "_set" + uc + "Attr",
286                                g: "_get" + uc + "Attr"
287                        });
288                },
289
290                _set: function(/*String*/ name, /*anything*/ value){
291                        // summary:
292                        //              Helper function to set new value for specified attribute
293                        this[name] = value;
294                }
295        });
296
297        // Hash mapping plugin name to factory, used for registering plugins
298        _Plugin.registry = {};
299
300        return _Plugin;
301});
Note: See TracBrowser for help on using the repository browser.