source: Dev/trunk/src/client/dojox/editor/plugins/Breadcrumb.js

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

Added Dojo 1.9.3 release.

  • Property svn:executable set to *
File size: 10.7 KB
Line 
1define([
2        "dojo",
3        "dijit",
4        "dojox",
5        "dijit/_Widget",
6        "dijit/_TemplatedMixin",
7        "dijit/_Contained",
8        "dijit/Toolbar",
9        "dijit/Menu",
10        "dijit/MenuItem",
11        "dijit/MenuSeparator",
12        "dijit/_editor/_Plugin",
13        "dijit/form/Button",
14        "dijit/form/ComboButton",
15        "dojo/_base/connect",
16        "dojo/_base/declare",
17        "dojo/i18n",
18        "dojo/string",
19        "dojo/i18n!dojox/editor/plugins/nls/Breadcrumb"
20], function(dojo, dijit, dojox, _Widget, _TemplatedMixin, _Contained, Toolbar, Menu, MenuItem,
21        MenuSeparator, _Plugin) {
22
23dojo.experimental("dojox.editor.plugins.Breadcrumb");
24
25var BreadcrumbMenuTitle = dojo.declare("dojox.editor.plugins._BreadcrumbMenuTitle",[_Widget, _TemplatedMixin, _Contained],{
26        // summary:
27        //              Simple internal, non-clickable, menu entry to act as a menu title bar.
28        templateString: "<tr><td dojoAttachPoint=\"title\" colspan=\"4\" class=\"dijitToolbar\" style=\"font-weight: bold; padding: 3px;\"></td></tr>",
29
30        menuTitle: "",
31
32        postCreate: function(){
33                dojo.setSelectable(this.domNode, false);
34                var label = this.id+"_text";
35                this.domNode.setAttribute("aria-labelledby", label);
36        },
37
38        _setMenuTitleAttr: function(str){
39                this.title.innerHTML = str;
40        },
41        _getMenuTitleAttr: function(str){
42                return this.title.innerHTML;
43        }
44});
45
46
47var Breadcrumb = dojo.declare("dojox.editor.plugins.Breadcrumb", _Plugin,{
48        // summary:
49        //              This plugin provides Breadcrumb capability to the editor. As you move
50        //              around the editor, it updates with your current indention depth.
51
52        // _menu: [private] Object
53        //              The popup menu that is displayed.
54        _menu: null,
55
56        // breadcrumbBar: [protected] dijit/Toolbar
57        //              The toolbar containing the breadcrumb.
58        breadcrumbBar: null,
59
60        setEditor: function(editor){
61                // summary:
62                //              Over-ride for the setting of the editor.
63                // editor: Object
64                //              The editor to configure for this plugin to use.
65                this.editor = editor;
66                this._buttons = [];
67                this.breadcrumbBar = new dijit.Toolbar();
68       
69                var strings = dojo.i18n.getLocalization("dojox.editor.plugins", "Breadcrumb");
70                this._titleTemplate = strings.nodeActions;
71
72                dojo.place(this.breadcrumbBar.domNode, editor.footer);
73                this.editor.onLoadDeferred.addCallback(dojo.hitch(this, function(){
74                        this._menu = new dijit.Menu({});
75                        dojo.addClass(this.breadcrumbBar.domNode, "dojoxEditorBreadcrumbArrow");
76                        var self = this;
77                        var body = new dijit.form.ComboButton({
78                                showLabel: true,
79                                label: "body",
80                                _selNode: editor.editNode,
81                                dropDown: this._menu,
82                                onClick: dojo.hitch(this, function(){
83                                        this._menuTarget = editor.editNode;
84                                        this._selectContents();
85                                })
86                        });
87                       
88                        // Build the menu
89                        this._menuTitle = new BreadcrumbMenuTitle({menuTitle: strings.nodeActions});
90                        this._selCMenu = new dijit.MenuItem({label: strings.selectContents, onClick: dojo.hitch(this, this._selectContents)});
91                        this._delCMenu = new dijit.MenuItem({label: strings.deleteContents, onClick: dojo.hitch(this, this._deleteContents)});
92                        this._selEMenu = new dijit.MenuItem({label: strings.selectElement, onClick: dojo.hitch(this, this._selectElement)});
93                        this._delEMenu = new dijit.MenuItem({label: strings.deleteElement, onClick: dojo.hitch(this, this._deleteElement)});
94                        this._moveSMenu = new dijit.MenuItem({label: strings.moveStart, onClick: dojo.hitch(this, this._moveCToStart)});
95                        this._moveEMenu = new dijit.MenuItem({label: strings.moveEnd, onClick: dojo.hitch(this, this._moveCToEnd)});
96
97                        this._menu.addChild(this._menuTitle);
98                        this._menu.addChild(this._selCMenu);
99                        this._menu.addChild(this._delCMenu);
100                        this._menu.addChild(new dijit.MenuSeparator({}));
101                        this._menu.addChild(this._selEMenu);
102                        this._menu.addChild(this._delEMenu);
103                        this._menu.addChild(new dijit.MenuSeparator({}));
104                        this._menu.addChild(this._moveSMenu);
105                        this._menu.addChild(this._moveEMenu);
106
107                        body._ddConnect = dojo.connect(body, "openDropDown", dojo.hitch(this, function(){
108                                this._menuTarget = body._selNode;
109                                this._menuTitle.set("menuTitle", dojo.string.substitute(this._titleTemplate,{
110                                                "nodeName": "&lt;body&gt;"
111                                }));
112                                this._selEMenu.set("disabled", true);
113                                this._delEMenu.set("disabled", true);
114                                this._selCMenu.set("disabled", false);
115                                this._delCMenu.set("disabled", false);
116                                this._moveSMenu.set("disabled", false);
117                                this._moveEMenu.set("disabled", false);
118                        }));
119                        this.breadcrumbBar.addChild(body);
120                        this.connect(this.editor, "onNormalizedDisplayChanged", "updateState");
121                }));
122                this.breadcrumbBar.startup();
123                if(dojo.isIE){
124                        // Sometimes IE will mess up layout and needs to be poked.
125            setTimeout(dojo.hitch(this, function(){this.breadcrumbBar.domNode.className = this.breadcrumbBar.domNode.className;}), 100);
126                }
127        },
128
129        _selectContents: function(){
130                // summary:
131                //              Internal function for selecting the contents of a node.
132                this.editor.focus();
133                if(this._menuTarget){
134                        var nodeName = this._menuTarget.tagName.toLowerCase();
135                        switch(nodeName){
136                                case 'br':
137                                case 'hr':
138                                case 'img':
139                                case 'input':
140                                case 'base':
141                                case 'meta':
142                                case 'area':
143                                case 'basefont':
144                                                break;
145                                default:
146                                        try{
147                                                this.editor._sCall("collapse", [null]);
148                                                this.editor._sCall("selectElementChildren", [this._menuTarget]);
149                                                this.editor.onDisplayChanged();
150                                        }catch(e){/*squelch*/}
151                        }
152                }
153        },
154
155        _deleteContents: function(){
156                // summary:
157                //              Internal function for selecting the contents of a node.
158                if(this._menuTarget){
159                        this.editor.beginEditing();
160                        this._selectContents();
161                        this.editor._sCall("remove", [this._menuTarget]);
162                        this.editor.endEditing();
163                        this._updateBreadcrumb();
164                        this.editor.onDisplayChanged();
165                }
166        },
167
168        _selectElement: function(){
169                // summary:
170                //              Internal function for selecting the contents of a node.
171                this.editor.focus();
172                if(this._menuTarget){
173                        this.editor._sCall("collapse", [null]);
174                        this.editor._sCall("selectElement", [this._menuTarget]);
175                        this.editor.onDisplayChanged();
176                       
177                }
178        },
179
180        _deleteElement: function(){
181                // summary:
182                //              Internal function for selecting the contents of a node.
183                if(this._menuTarget){
184                        this.editor.beginEditing();
185                        this._selectElement();
186                        this.editor._sCall("remove", [this._menuTarget]);
187                        this.editor.endEditing();
188                        this._updateBreadcrumb();
189                        this.editor.onDisplayChanged();
190                }
191        },
192
193        _moveCToStart: function(){
194                // summary:
195                //              Internal function for selecting the contents of a node.
196                this.editor.focus();
197                if(this._menuTarget){
198                        this._selectContents();
199                        this.editor._sCall("collapse", [true]);
200                }
201        },
202
203        _moveCToEnd: function(){
204                // summary:
205                //              Internal function for selecting the contents of a node.
206                this.editor.focus();
207                if(this._menuTarget){
208                        this._selectContents();
209                        this.editor._sCall("collapse", [false]);
210                }
211        },
212
213        _updateBreadcrumb: function(){
214                // summary:
215                //              Function to trigger updating of the breadcrumb
216                // tags:
217                //              private
218                var ed = this.editor;
219                if(ed.window){
220                        var sel = dijit.range.getSelection(ed.window);
221                        if(sel && sel.rangeCount > 0){
222                                var range = sel.getRangeAt(0);
223               
224                                // Check the getSelectedElement call.  Needed when dealing with img tags.
225                                var node = ed._sCall("getSelectedElement", []) || range.startContainer;
226                                //var node = range.startContainer;
227                                var bcList = [];
228
229                                // Make sure we get a selection within the editor document,
230                                // have seen cases on IE where this wasn't true.
231                                if(node && node.ownerDocument === ed.document){
232                                        while(node && node !== ed.editNode && node != ed.document.body && node != ed.document){
233                                                if(node.nodeType === 1){
234                                                        bcList.push({type: node.tagName.toLowerCase(), node: node});
235                                                }
236                                                node = node.parentNode;
237                                        }
238                                        bcList = bcList.reverse();
239
240                                        while(this._buttons.length){
241                                                var db = this._buttons.pop();
242                                                dojo.disconnect(db._ddConnect);
243                                                this.breadcrumbBar.removeChild(db);
244                                        }
245                                        this._buttons = [];
246
247                                        var i;
248                                        var self = this;
249                                        for(i = 0; i < bcList.length; i++){
250                                                var bc = bcList[i];
251                                                var b = new dijit.form.ComboButton({
252                                                        showLabel: true,
253                                                        label: bc.type,
254                                                        _selNode: bc.node,
255                                                        dropDown: this._menu,
256                                                        onClick: function(){
257                                                                self._menuTarget = this._selNode;
258                                                                self._selectContents();
259                                                        }
260                                                });
261                                                b._ddConnect = dojo.connect(b, "openDropDown", dojo.hitch(b, function(){
262                                                        self._menuTarget = this._selNode;
263                                                        var nodeName = self._menuTarget.tagName.toLowerCase();
264                                                        var title = dojo.string.substitute(self._titleTemplate,{
265                                                                "nodeName": "&lt;" + nodeName + "&gt;"
266                                                        });
267                                                        self._menuTitle.set("menuTitle", title);
268                                                        switch(nodeName){
269                                                                case 'br':
270                                                                case 'hr':
271                                                                case 'img':
272                                                                case 'input':
273                                                                case 'base':
274                                                                case 'meta':
275                                                                case 'area':
276                                                                case 'basefont':
277                                                                        self._selCMenu.set("disabled", true);
278                                                                        self._delCMenu.set("disabled", true);
279                                                                        self._moveSMenu.set("disabled", true);
280                                                                        self._moveEMenu.set("disabled", true);
281                                                                        self._selEMenu.set("disabled", false);
282                                                                        self._delEMenu.set("disabled", false);
283                                                                        break;
284                                                                default:
285                                                                        self._selCMenu.set("disabled", false);
286                                                                        self._delCMenu.set("disabled", false);
287                                                                        self._selEMenu.set("disabled", false);
288                                                                        self._delEMenu.set("disabled", false);
289                                                                        self._moveSMenu.set("disabled", false);
290                                                                        self._moveEMenu.set("disabled", false);
291                                                        }
292                                                }));
293                                                this._buttons.push(b);
294                                                this.breadcrumbBar.addChild(b);
295                                        }
296                                        if(dojo.isIE){
297                                                // Prod it to fix layout.
298                                                this.breadcrumbBar.domNode.className = this.breadcrumbBar.domNode.className;
299                                        }
300                                       
301                                }
302                        }
303                }
304        },
305
306        updateState: function(){
307                // summary:
308                //              Over-ride of updateState to hide the toolbar when the iframe is not visible.
309                //              Also triggers the breadcrumb update.
310                if(dojo.style(this.editor.iframe, "display") === "none" || this.get("disabled")){
311                        dojo.style(this.breadcrumbBar.domNode, "display", "none");
312                }else{
313                        if(dojo.style(this.breadcrumbBar.domNode, "display") === "none"){
314                                dojo.style(this.breadcrumbBar.domNode, "display", "block");
315                        }
316                        this._updateBreadcrumb();
317
318                        // Some themes do padding, so we have to resize again after display.
319                        var size = dojo.marginBox(this.editor.domNode);
320                        this.editor.resize({h: size.h});
321                }
322        },
323
324        destroy: function(){
325                // summary:
326                //              Over-ride to clean up the breadcrumb toolbar.
327                if(this.breadcrumbBar){
328                        this.breadcrumbBar.destroyRecursive();
329                        this.breadcrumbBar = null;
330                }
331                if(this._menu){
332                        this._menu.destroyRecursive();
333                        delete this._menu;
334                }
335                this._buttons = null;
336                delete this.editor.breadcrumbBar;
337                this.inherited(arguments);
338        }
339});
340
341// For monkey patching
342Breadcrumb._BreadcrumbMenuTitle = BreadcrumbMenuTitle;
343
344// Register this plugin.
345dojo.subscribe(dijit._scopeName + ".Editor.getPlugin",null,function(o){
346        if(o.plugin){ return; }
347        var name = o.args.name.toLowerCase();
348        if(name === "breadcrumb"){
349                o.plugin = new Breadcrumb({});
350        }
351});
352
353return Breadcrumb;
354
355});
Note: See TracBrowser for help on using the repository browser.