]>
git.wh0rd.org - tt-rss.git/blob - lib/dijit/_editor/_Plugin.js
2 Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved.
3 Available via Academic Free License >= 2.1 OR the modified BSD license.
4 see: http://dojotoolkit.org/license for details
8 if(!dojo
._hasResource
["dijit._editor._Plugin"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
9 dojo
._hasResource
["dijit._editor._Plugin"] = true;
10 dojo
.provide("dijit._editor._Plugin");
11 dojo
.require("dijit._Widget");
12 dojo
.require("dijit.form.Button");
15 dojo
.declare("dijit._editor._Plugin", null, {
17 // Base class for a "plugin" to the editor, which is usually
18 // a single button on the Toolbar and some associated code
20 constructor: function(/*Object?*/args
, /*DomNode?*/node
){
21 this.params
= args
|| {};
22 dojo
.mixin(this, this.params
);
24 this._attrPairNames
= {};
27 // editor: [const] dijit.Editor
28 // Points to the parent editor
31 // iconClassPrefix: [const] String
32 // The CSS class name for the button node is formed from `iconClassPrefix` and `command`
33 iconClassPrefix
: "dijitEditorIcon",
35 // button: dijit._Widget?
36 // Pointer to `dijit.form.Button` or other widget (ex: `dijit.form.FilteringSelect`)
37 // that is added to the toolbar to control this plugin.
38 // If not specified, will be created on initialization according to `buttonClass`
42 // String like "insertUnorderedList", "outdent", "justifyCenter", etc. that represents an editor command.
43 // Passed to editor.execCommand() if `useDefaultCommand` is true.
46 // useDefaultCommand: Boolean
47 // If true, this plugin executes by calling Editor.execCommand() with the argument specified in `command`.
48 useDefaultCommand
: true,
50 // buttonClass: Widget Class
51 // Class of widget (ex: dijit.form.Button or dijit.form.FilteringSelect)
52 // that is added to the toolbar to control this plugin.
53 // This is used to instantiate the button, unless `button` itself is specified directly.
54 buttonClass
: dijit
.form
.Button
,
57 // Flag to indicate if this plugin has been disabled and should do nothing
58 // helps control button state, among other things. Set via the setter api.
61 getLabel: function(/*String*/key
){
63 // Returns the label to use for the button
66 return this.editor
.commands
[key
]; // String
69 _initButton: function(){
71 // Initialize the button or other widget that will control this plugin.
72 // This code only works for plugins controlling built-in commands in the editor.
74 // protected extension
75 if(this.command
.length
){
76 var label
= this.getLabel(this.command
),
78 className
= this.iconClassPrefix
+" "+this.iconClassPrefix
+ this.command
.charAt(0).toUpperCase() + this.command
.substr(1);
80 var props
= dojo
.mixin({
86 dropDown
: this.dropDown
,
88 }, this.params
|| {});
89 this.button
= new this.buttonClass(props
);
92 if(this.get("disabled") && this.button
){
93 this.button
.set("disabled", this.get("disabled"));
99 // Destroy this plugin
101 dojo
.forEach(this._connects
, dojo
.disconnect
);
103 this.dropDown
.destroyRecursive();
107 connect: function(o
, f
, tf
){
109 // Make a dojo.connect() that is automatically disconnected when this plugin is destroyed.
110 // Similar to `dijit._Widget.connect`.
113 this._connects
.push(dojo
.connect(o
, f
, this, tf
));
116 updateState: function(){
118 // Change state of the plugin to respond to events in the editor.
120 // This is called on meaningful events in the editor, such as change of selection
121 // or caret position (but not simple typing of alphanumeric keys). It gives the
122 // plugin a chance to update the CSS of its button.
124 // For example, the "bold" plugin will highlight/unhighlight the bold button depending on whether the
125 // characters next to the caret are bold or not.
127 // Only makes sense when `useDefaultCommand` is true, as it calls Editor.queryCommandEnabled(`command`).
131 if(!e
|| !e
.isLoaded
|| !c
.length
){ return; }
132 var disabled
= this.get("disabled");
135 enabled
= !disabled
&& e
.queryCommandEnabled(c
);
136 if(this.enabled
!== enabled
){
137 this.enabled
= enabled
;
138 this.button
.set('disabled', !enabled
);
140 if(typeof this.button
.checked
== 'boolean'){
141 checked
= e
.queryCommandState(c
);
142 if(this.checked
!== checked
){
143 this.checked
= checked
;
144 this.button
.set('checked', e
.queryCommandState(c
));
148 console
.log(e
); // FIXME: we shouldn't have debug statements in our code. Log as an error?
153 setEditor: function(/*dijit.Editor*/ editor
){
155 // Tell the plugin which Editor it is associated with.
157 // TODO: refactor code to just pass editor to constructor.
159 // FIXME: detach from previous editor!!
160 this.editor
= editor
;
162 // FIXME: prevent creating this if we don't need to (i.e., editor can't handle our command)
165 // Processing for buttons that execute by calling editor.execCommand()
166 if(this.button
&& this.useDefaultCommand
){
167 if(this.editor
.queryCommandAvailable(this.command
)){
168 this.connect(this.button
, "onClick",
169 dojo
.hitch(this.editor
, "execCommand", this.command
, this.commandArg
)
172 // hide button because editor doesn't support command (due to browser limitations)
173 this.button
.domNode
.style
.display
= "none";
177 this.connect(this.editor
, "onNormalizedDisplayChanged", "updateState");
180 setToolbar: function(/*dijit.Toolbar*/ toolbar
){
182 // Tell the plugin to add it's controller widget (often a button)
183 // to the toolbar. Does nothing if there is no controller widget.
185 // TODO: refactor code to just pass toolbar to constructor.
188 toolbar
.addChild(this.button
);
190 // console.debug("adding", this.button, "to:", toolbar);
193 set: function(/* attribute */ name
, /* anything */ value
){
195 // Set a property on a plugin
197 // The property to set.
199 // The value to set in the property.
201 // Sets named properties on a plugin which may potentially be handled by a
202 // setter in the plugin.
203 // For example, if the plugin has a properties "foo"
204 // and "bar" and a method named "_setFooAttr", calling:
205 // | plugin.set("foo", "Howdy!");
206 // would be equivalent to writing:
207 // | plugin._setFooAttr("Howdy!");
209 // | plugin.set("bar", 3);
210 // would be equivalent to writing:
213 // set() may also be called with a hash of name/value pairs, ex:
218 // This is equivalent to calling set(foo, "Howdy") and set(bar, 3)
219 if(typeof name
=== "object"){
221 this.set(x
, name
[x
]);
225 var names
= this._getAttrNames(name
);
227 // use the explicit setter
228 var result
= this[names
.s
].apply(this, Array
.prototype.slice
.call(arguments
, 1));
230 this._set(name
, value
);
232 return result
|| this;
237 // Get a property from a plugin.
239 // The property to get.
241 // Get a named property from a plugin. The property may
242 // potentially be retrieved via a getter method. If no getter is defined, this
243 // just retrieves the object's property.
244 // For example, if the plugin has a properties "foo"
245 // and "bar" and a method named "_getFooAttr", calling:
246 // | plugin.get("foo");
247 // would be equivalent to writing:
248 // | plugin._getFooAttr();
250 // | plugin.get("bar");
251 // would be equivalent to writing:
253 var names
= this._getAttrNames(name
);
254 return this[names
.g
] ? this[names
.g
]() : this[name
];
257 _setDisabledAttr: function(disabled
){
259 // Function to set the plugin state and call updateState to make sure the
260 // button is updated appropriately.
261 this.disabled
= disabled
;
265 _getAttrNames: function(name
){
267 // Helper function for get() and set().
268 // Caches attribute name values so we don't do the string ops every time.
272 var apn
= this._attrPairNames
;
273 if(apn
[name
]){ return apn
[name
]; }
274 var uc
= name
.charAt(0).toUpperCase() + name
.substr(1);
275 return (apn
[name
] = {
281 _set: function(/*String*/ name
, /*anything*/ value
){
283 // Helper function to set new value for specified attribute
284 var oldValue
= this[name
];