1 | define([ |
---|
2 | "require", |
---|
3 | "dojo/_base/array", // array.indexOf array.map |
---|
4 | "dojo/_base/declare", // declare |
---|
5 | "dojo/dom-construct", // domConstruct.place |
---|
6 | "dojo/i18n", // i18n.getLocalization |
---|
7 | "dojo/_base/lang", // lang.delegate lang.hitch lang.isString |
---|
8 | "dojo/store/Memory", // MemoryStore |
---|
9 | "../../registry", // registry.getUniqueId |
---|
10 | "../../_Widget", |
---|
11 | "../../_TemplatedMixin", |
---|
12 | "../../_WidgetsInTemplateMixin", |
---|
13 | "../../form/FilteringSelect", |
---|
14 | "../_Plugin", |
---|
15 | "../range", |
---|
16 | "dojo/i18n!../nls/FontChoice" |
---|
17 | ], function(require, array, declare, domConstruct, i18n, lang, MemoryStore, |
---|
18 | registry, _Widget, _TemplatedMixin, _WidgetsInTemplateMixin, FilteringSelect, _Plugin, rangeapi){ |
---|
19 | |
---|
20 | // module: |
---|
21 | // dijit/_editor/plugins/FontChoice |
---|
22 | |
---|
23 | var _FontDropDown = declare("dijit._editor.plugins._FontDropDown", |
---|
24 | [_Widget, _TemplatedMixin, _WidgetsInTemplateMixin], { |
---|
25 | // summary: |
---|
26 | // Base class for widgets that contains a label (like "Font:") |
---|
27 | // and a FilteringSelect drop down to pick a value. |
---|
28 | // Used as Toolbar entry. |
---|
29 | |
---|
30 | // label: [public] String |
---|
31 | // The label to apply to this particular FontDropDown. |
---|
32 | label: "", |
---|
33 | |
---|
34 | // plainText: [public] boolean |
---|
35 | // Flag to indicate that the returned label should be plain text |
---|
36 | // instead of an example. |
---|
37 | plainText: false, |
---|
38 | |
---|
39 | // templateString: [public] String |
---|
40 | // The template used to construct the labeled dropdown. |
---|
41 | templateString: "<span style='white-space: nowrap' class='dijit dijitReset dijitInline'>" + |
---|
42 | "<label class='dijitLeft dijitInline' for='${selectId}'>${label}</label>" + |
---|
43 | "<input data-dojo-type='../../form/FilteringSelect' required='false' " + |
---|
44 | "data-dojo-props='labelType:\"html\", labelAttr:\"label\", searchAttr:\"name\"' " + |
---|
45 | "class='${comboClass}' " + |
---|
46 | "tabIndex='-1' id='${selectId}' data-dojo-attach-point='select' value=''/>" + |
---|
47 | "</span>", |
---|
48 | |
---|
49 | // contextRequire: [public] Function |
---|
50 | // The context require that is used to resolve modules in template. |
---|
51 | contextRequire: require, |
---|
52 | |
---|
53 | postMixInProperties: function(){ |
---|
54 | // summary: |
---|
55 | // Over-ride to set specific properties. |
---|
56 | this.inherited(arguments); |
---|
57 | |
---|
58 | this.strings = i18n.getLocalization("dijit._editor", "FontChoice"); |
---|
59 | |
---|
60 | // Set some substitution variables used in the template |
---|
61 | this.label = this.strings[this.command]; |
---|
62 | |
---|
63 | // _WidgetBase sets the id after postMixInProperties(), but we need it now. |
---|
64 | // Alternative is to have a buildRendering() method and move this.selectId setting there, |
---|
65 | // or alternately get rid of selectId variable and just access ${id} in template? |
---|
66 | this.id = registry.getUniqueId(this.declaredClass.replace(/\./g, "_")); |
---|
67 | |
---|
68 | this.selectId = this.id + "_select"; // used in template |
---|
69 | |
---|
70 | this.inherited(arguments); |
---|
71 | }, |
---|
72 | |
---|
73 | postCreate: function(){ |
---|
74 | // summary: |
---|
75 | // Over-ride for the default postCreate action |
---|
76 | // This establishes the filtering selects and the like. |
---|
77 | |
---|
78 | // Initialize the list of items in the drop down by creating data store with items like: |
---|
79 | // {value: 1, name: "xx-small", label: "<font size=1>xx-small</font-size>" } |
---|
80 | this.select.set("store", new MemoryStore({ |
---|
81 | idProperty: "value", |
---|
82 | data: array.map(this.values, function(value){ |
---|
83 | var name = this.strings[value] || value; |
---|
84 | return { |
---|
85 | label: this.getLabel(value, name), |
---|
86 | name: name, |
---|
87 | value: value |
---|
88 | }; |
---|
89 | }, this) |
---|
90 | })); |
---|
91 | |
---|
92 | this.select.set("value", "", false); |
---|
93 | this.disabled = this.select.get("disabled"); |
---|
94 | }, |
---|
95 | |
---|
96 | _setValueAttr: function(value, priorityChange){ |
---|
97 | // summary: |
---|
98 | // Over-ride for the default action of setting the |
---|
99 | // widget value, maps the input to known values |
---|
100 | // value: Object|String |
---|
101 | // The value to set in the select. |
---|
102 | // priorityChange: |
---|
103 | // Optional parameter used to tell the select whether or not to fire |
---|
104 | // onChange event. |
---|
105 | |
---|
106 | // if the value is not a permitted value, just set empty string to prevent showing the warning icon |
---|
107 | priorityChange = priorityChange !== false; |
---|
108 | this.select.set('value', array.indexOf(this.values, value) < 0 ? "" : value, priorityChange); |
---|
109 | if(!priorityChange){ |
---|
110 | // Clear the last state in case of updateState calls. Ref: #10466 |
---|
111 | this.select._lastValueReported = null; |
---|
112 | } |
---|
113 | }, |
---|
114 | |
---|
115 | _getValueAttr: function(){ |
---|
116 | // summary: |
---|
117 | // Allow retrieving the value from the composite select on |
---|
118 | // call to button.get("value"); |
---|
119 | return this.select.get('value'); |
---|
120 | }, |
---|
121 | |
---|
122 | focus: function(){ |
---|
123 | // summary: |
---|
124 | // Over-ride for focus control of this widget. Delegates focus down to the |
---|
125 | // filtering select. |
---|
126 | this.select.focus(); |
---|
127 | }, |
---|
128 | |
---|
129 | _setDisabledAttr: function(value){ |
---|
130 | // summary: |
---|
131 | // Over-ride for the button's 'disabled' attribute so that it can be |
---|
132 | // disabled programmatically. |
---|
133 | |
---|
134 | // Save off ths disabled state so the get retrieves it correctly |
---|
135 | //without needing to have a function proxy it. |
---|
136 | this._set("disabled", value); |
---|
137 | this.select.set("disabled", value); |
---|
138 | } |
---|
139 | }); |
---|
140 | |
---|
141 | |
---|
142 | var _FontNameDropDown = declare("dijit._editor.plugins._FontNameDropDown", _FontDropDown, { |
---|
143 | // summary: |
---|
144 | // Dropdown to select a font; goes in editor toolbar. |
---|
145 | |
---|
146 | // generic: [const] Boolean |
---|
147 | // Use generic (web standard) font names |
---|
148 | generic: false, |
---|
149 | |
---|
150 | // command: [public] String |
---|
151 | // The editor 'command' implemented by this plugin. |
---|
152 | command: "fontName", |
---|
153 | |
---|
154 | comboClass: "dijitFontNameCombo", |
---|
155 | |
---|
156 | postMixInProperties: function(){ |
---|
157 | // summary: |
---|
158 | // Over-ride for the default posr mixin control |
---|
159 | if(!this.values){ |
---|
160 | this.values = this.generic ? |
---|
161 | ["serif", "sans-serif", "monospace", "cursive", "fantasy"] : // CSS font-family generics |
---|
162 | ["Arial", "Times New Roman", "Comic Sans MS", "Courier New"]; |
---|
163 | } |
---|
164 | this.inherited(arguments); |
---|
165 | }, |
---|
166 | |
---|
167 | getLabel: function(value, name){ |
---|
168 | // summary: |
---|
169 | // Function used to generate the labels of the format dropdown |
---|
170 | // will return a formatted, or plain label based on the value |
---|
171 | // of the plainText option. |
---|
172 | // value: String |
---|
173 | // The 'insert value' associated with a name |
---|
174 | // name: String |
---|
175 | // The text name of the value |
---|
176 | if(this.plainText){ |
---|
177 | return name; |
---|
178 | }else{ |
---|
179 | return "<div style='font-family: " + value + "'>" + name + "</div>"; |
---|
180 | } |
---|
181 | }, |
---|
182 | |
---|
183 | _setValueAttr: function(value, priorityChange){ |
---|
184 | // summary: |
---|
185 | // Over-ride for the default action of setting the |
---|
186 | // widget value, maps the input to known values |
---|
187 | |
---|
188 | priorityChange = priorityChange !== false; |
---|
189 | if(this.generic){ |
---|
190 | var map = { |
---|
191 | "Arial": "sans-serif", |
---|
192 | "Helvetica": "sans-serif", |
---|
193 | "Myriad": "sans-serif", |
---|
194 | "Times": "serif", |
---|
195 | "Times New Roman": "serif", |
---|
196 | "Comic Sans MS": "cursive", |
---|
197 | "Apple Chancery": "cursive", |
---|
198 | "Courier": "monospace", |
---|
199 | "Courier New": "monospace", |
---|
200 | "Papyrus": "fantasy", |
---|
201 | "Estrangelo Edessa": "cursive", // Windows 7 |
---|
202 | "Gabriola": "fantasy" // Windows 7 |
---|
203 | }; |
---|
204 | value = map[value] || value; |
---|
205 | } |
---|
206 | this.inherited(arguments, [value, priorityChange]); |
---|
207 | } |
---|
208 | }); |
---|
209 | |
---|
210 | var _FontSizeDropDown = declare("dijit._editor.plugins._FontSizeDropDown", _FontDropDown, { |
---|
211 | // summary: |
---|
212 | // Dropdown to select a font size; goes in editor toolbar. |
---|
213 | |
---|
214 | // command: [public] String |
---|
215 | // The editor 'command' implemented by this plugin. |
---|
216 | command: "fontSize", |
---|
217 | |
---|
218 | comboClass: "dijitFontSizeCombo", |
---|
219 | |
---|
220 | // values: [public] Number[] |
---|
221 | // The HTML font size values supported by this plugin |
---|
222 | values: [1, 2, 3, 4, 5, 6, 7], // sizes according to the old HTML FONT SIZE |
---|
223 | |
---|
224 | getLabel: function(value, name){ |
---|
225 | // summary: |
---|
226 | // Function used to generate the labels of the format dropdown |
---|
227 | // will return a formatted, or plain label based on the value |
---|
228 | // of the plainText option. |
---|
229 | // We're stuck using the deprecated FONT tag to correspond |
---|
230 | // with the size measurements used by the editor |
---|
231 | // value: String |
---|
232 | // The 'insert value' associated with a name |
---|
233 | // name: String |
---|
234 | // The text name of the value |
---|
235 | if(this.plainText){ |
---|
236 | return name; |
---|
237 | }else{ |
---|
238 | return "<font size=" + value + "'>" + name + "</font>"; |
---|
239 | } |
---|
240 | }, |
---|
241 | |
---|
242 | _setValueAttr: function(value, priorityChange){ |
---|
243 | // summary: |
---|
244 | // Over-ride for the default action of setting the |
---|
245 | // widget value, maps the input to known values |
---|
246 | priorityChange = priorityChange !== false; |
---|
247 | if(value.indexOf && value.indexOf("px") != -1){ |
---|
248 | var pixels = parseInt(value, 10); |
---|
249 | value = {10: 1, 13: 2, 16: 3, 18: 4, 24: 5, 32: 6, 48: 7}[pixels] || value; |
---|
250 | } |
---|
251 | |
---|
252 | this.inherited(arguments, [value, priorityChange]); |
---|
253 | } |
---|
254 | }); |
---|
255 | |
---|
256 | |
---|
257 | var _FormatBlockDropDown = declare("dijit._editor.plugins._FormatBlockDropDown", _FontDropDown, { |
---|
258 | // summary: |
---|
259 | // Dropdown to select a format (like paragraph or heading); goes in editor toolbar. |
---|
260 | |
---|
261 | // command: [public] String |
---|
262 | // The editor 'command' implemented by this plugin. |
---|
263 | command: "formatBlock", |
---|
264 | |
---|
265 | comboClass: "dijitFormatBlockCombo", |
---|
266 | |
---|
267 | // values: [public] Array |
---|
268 | // The HTML format tags supported by this plugin |
---|
269 | values: ["noFormat", "p", "h1", "h2", "h3", "pre"], |
---|
270 | |
---|
271 | postCreate: function(){ |
---|
272 | // Init and set the default value to no formatting. Update state will adjust it |
---|
273 | // as needed. |
---|
274 | this.inherited(arguments); |
---|
275 | this.set("value", "noFormat", false); |
---|
276 | }, |
---|
277 | |
---|
278 | getLabel: function(value, name){ |
---|
279 | // summary: |
---|
280 | // Function used to generate the labels of the format dropdown |
---|
281 | // will return a formatted, or plain label based on the value |
---|
282 | // of the plainText option. |
---|
283 | // value: String |
---|
284 | // The 'insert value' associated with a name |
---|
285 | // name: String |
---|
286 | // The text name of the value |
---|
287 | if(this.plainText || value == "noFormat"){ |
---|
288 | return name; |
---|
289 | }else{ |
---|
290 | return "<" + value + ">" + name + "</" + value + ">"; |
---|
291 | } |
---|
292 | }, |
---|
293 | |
---|
294 | _execCommand: function(editor, command, choice){ |
---|
295 | // summary: |
---|
296 | // Over-ride for default exec-command label. |
---|
297 | // Allows us to treat 'none' as special. |
---|
298 | if(choice === "noFormat"){ |
---|
299 | var start; |
---|
300 | var end; |
---|
301 | var sel = rangeapi.getSelection(editor.window); |
---|
302 | if(sel && sel.rangeCount > 0){ |
---|
303 | var range = sel.getRangeAt(0); |
---|
304 | var node, tag; |
---|
305 | if(range){ |
---|
306 | start = range.startContainer; |
---|
307 | end = range.endContainer; |
---|
308 | |
---|
309 | // find containing nodes of start/end. |
---|
310 | while(start && start !== editor.editNode && |
---|
311 | start !== editor.document.body && |
---|
312 | start.nodeType !== 1){ |
---|
313 | start = start.parentNode; |
---|
314 | } |
---|
315 | |
---|
316 | while(end && end !== editor.editNode && |
---|
317 | end !== editor.document.body && |
---|
318 | end.nodeType !== 1){ |
---|
319 | end = end.parentNode; |
---|
320 | } |
---|
321 | |
---|
322 | var processChildren = lang.hitch(this, function(node, ary){ |
---|
323 | if(node.childNodes && node.childNodes.length){ |
---|
324 | var i; |
---|
325 | for(i = 0; i < node.childNodes.length; i++){ |
---|
326 | var c = node.childNodes[i]; |
---|
327 | if(c.nodeType == 1){ |
---|
328 | if(editor.selection.inSelection(c)){ |
---|
329 | var tag = c.tagName ? c.tagName.toLowerCase() : ""; |
---|
330 | if(array.indexOf(this.values, tag) !== -1){ |
---|
331 | ary.push(c); |
---|
332 | } |
---|
333 | processChildren(c, ary); |
---|
334 | } |
---|
335 | } |
---|
336 | } |
---|
337 | } |
---|
338 | }); |
---|
339 | |
---|
340 | var unformatNodes = lang.hitch(this, function(nodes){ |
---|
341 | // summary: |
---|
342 | // Internal function to clear format nodes. |
---|
343 | // nodes: |
---|
344 | // The array of nodes to strip formatting from. |
---|
345 | if(nodes && nodes.length){ |
---|
346 | editor.beginEditing(); |
---|
347 | while(nodes.length){ |
---|
348 | this._removeFormat(editor, nodes.pop()); |
---|
349 | } |
---|
350 | editor.endEditing(); |
---|
351 | } |
---|
352 | }); |
---|
353 | |
---|
354 | var clearNodes = []; |
---|
355 | if(start == end){ |
---|
356 | //Contained within the same block, may be collapsed, but who cares, see if we |
---|
357 | // have a block element to remove. |
---|
358 | var block; |
---|
359 | node = start; |
---|
360 | while(node && node !== editor.editNode && node !== editor.document.body){ |
---|
361 | if(node.nodeType == 1){ |
---|
362 | tag = node.tagName ? node.tagName.toLowerCase() : ""; |
---|
363 | if(array.indexOf(this.values, tag) !== -1){ |
---|
364 | block = node; |
---|
365 | break; |
---|
366 | } |
---|
367 | } |
---|
368 | node = node.parentNode; |
---|
369 | } |
---|
370 | |
---|
371 | //Also look for all child nodes in the selection that may need to be |
---|
372 | //cleared of formatting |
---|
373 | processChildren(start, clearNodes); |
---|
374 | if(block){ |
---|
375 | clearNodes = [block].concat(clearNodes); |
---|
376 | } |
---|
377 | unformatNodes(clearNodes); |
---|
378 | }else{ |
---|
379 | // Probably a multi select, so we have to process it. Whee. |
---|
380 | node = start; |
---|
381 | while(editor.selection.inSelection(node)){ |
---|
382 | if(node.nodeType == 1){ |
---|
383 | tag = node.tagName ? node.tagName.toLowerCase() : ""; |
---|
384 | if(array.indexOf(this.values, tag) !== -1){ |
---|
385 | clearNodes.push(node); |
---|
386 | } |
---|
387 | processChildren(node, clearNodes); |
---|
388 | } |
---|
389 | node = node.nextSibling; |
---|
390 | } |
---|
391 | unformatNodes(clearNodes); |
---|
392 | } |
---|
393 | editor.onDisplayChanged(); |
---|
394 | } |
---|
395 | } |
---|
396 | }else{ |
---|
397 | editor.execCommand(command, choice); |
---|
398 | } |
---|
399 | }, |
---|
400 | |
---|
401 | _removeFormat: function(editor, node){ |
---|
402 | // summary: |
---|
403 | // function to remove the block format node. |
---|
404 | // node: |
---|
405 | // The block format node to remove (and leave the contents behind) |
---|
406 | if(editor.customUndo){ |
---|
407 | // So of course IE doesn't work right with paste-overs. |
---|
408 | // We have to do this manually, which is okay since IE already uses |
---|
409 | // customUndo and we turned it on for WebKit. WebKit pasted funny, |
---|
410 | // so couldn't use the execCommand approach |
---|
411 | while(node.firstChild){ |
---|
412 | domConstruct.place(node.firstChild, node, "before"); |
---|
413 | } |
---|
414 | node.parentNode.removeChild(node); |
---|
415 | }else{ |
---|
416 | // Everyone else works fine this way, a paste-over and is native |
---|
417 | // undo friendly. |
---|
418 | editor.selection.selectElementChildren(node); |
---|
419 | var html = editor.selection.getSelectedHtml(); |
---|
420 | editor.selection.selectElement(node); |
---|
421 | editor.execCommand("inserthtml", html || ""); |
---|
422 | } |
---|
423 | } |
---|
424 | }); |
---|
425 | |
---|
426 | // TODO: for 2.0, split into FontChoice plugin into three separate classes, |
---|
427 | // one for each command (and change registry below) |
---|
428 | var FontChoice = declare("dijit._editor.plugins.FontChoice", _Plugin, { |
---|
429 | // summary: |
---|
430 | // This plugin provides three drop downs for setting style in the editor |
---|
431 | // (font, font size, and format block), as controlled by command. |
---|
432 | // |
---|
433 | // description: |
---|
434 | // The commands provided by this plugin are: |
---|
435 | // |
---|
436 | // - fontName: Provides a drop down to select from a list of font names |
---|
437 | // - fontSize: Provides a drop down to select from a list of font sizes |
---|
438 | // - formatBlock: Provides a drop down to select from a list of block styles |
---|
439 | // which can easily be added to an editor by including one or more of the above commands |
---|
440 | // in the `plugins` attribute as follows: |
---|
441 | // |
---|
442 | // | plugins="['fontName','fontSize',...]" |
---|
443 | // |
---|
444 | // It is possible to override the default dropdown list by providing an Array for the `custom` property when |
---|
445 | // instantiating this plugin, e.g. |
---|
446 | // |
---|
447 | // | plugins="[{name:'dijit._editor.plugins.FontChoice', command:'fontName', values:['Verdana','Myriad','Garamond']},...]" |
---|
448 | // |
---|
449 | // Alternatively, for `fontName` only, `generic:true` may be specified to provide a dropdown with |
---|
450 | // [CSS generic font families](http://www.w3.org/TR/REC-CSS2/fonts.html#generic-font-families). |
---|
451 | // |
---|
452 | // Note that the editor is often unable to properly handle font styling information defined outside |
---|
453 | // the context of the current editor instance, such as pre-populated HTML. |
---|
454 | |
---|
455 | // useDefaultCommand: [protected] Boolean |
---|
456 | // Override _Plugin.useDefaultCommand... |
---|
457 | // processing is handled by this plugin, not by dijit/Editor. |
---|
458 | useDefaultCommand: false, |
---|
459 | |
---|
460 | _initButton: function(){ |
---|
461 | // summary: |
---|
462 | // Overrides _Plugin._initButton(), to initialize the FilteringSelect+label in toolbar, |
---|
463 | // rather than a simple button. |
---|
464 | // tags: |
---|
465 | // protected |
---|
466 | |
---|
467 | // Create the widget to go into the toolbar (the so-called "button") |
---|
468 | var clazz = { |
---|
469 | fontName: _FontNameDropDown, |
---|
470 | fontSize: _FontSizeDropDown, |
---|
471 | formatBlock: _FormatBlockDropDown |
---|
472 | }[this.command], |
---|
473 | params = this.params; |
---|
474 | |
---|
475 | // For back-compat reasons support setting custom values via "custom" parameter |
---|
476 | // rather than "values" parameter. Remove in 2.0. |
---|
477 | if(this.params.custom){ |
---|
478 | params.values = this.params.custom; |
---|
479 | } |
---|
480 | |
---|
481 | var editor = this.editor; |
---|
482 | this.button = new clazz(lang.delegate({dir: editor.dir, lang: editor.lang}, params)); |
---|
483 | |
---|
484 | // Reflect changes to the drop down in the editor |
---|
485 | this.own(this.button.select.on("change", lang.hitch(this, function(choice){ |
---|
486 | // User invoked change, since all internal updates set priorityChange to false and will |
---|
487 | // not trigger an onChange event. |
---|
488 | |
---|
489 | if(this.editor.focused){ |
---|
490 | // put focus back in the iframe, unless focus has somehow been shifted out of the editor completely |
---|
491 | this.editor.focus(); |
---|
492 | } |
---|
493 | |
---|
494 | if(this.command == "fontName" && choice.indexOf(" ") != -1){ |
---|
495 | choice = "'" + choice + "'"; |
---|
496 | } |
---|
497 | |
---|
498 | // Invoke, the editor already normalizes commands called through its |
---|
499 | // execCommand. |
---|
500 | if(this.button._execCommand){ |
---|
501 | this.button._execCommand(this.editor, this.command, choice); |
---|
502 | }else{ |
---|
503 | this.editor.execCommand(this.command, choice); |
---|
504 | } |
---|
505 | }))); |
---|
506 | }, |
---|
507 | |
---|
508 | updateState: function(){ |
---|
509 | // summary: |
---|
510 | // Overrides _Plugin.updateState(). This controls updating the menu |
---|
511 | // options to the right values on state changes in the document (that trigger a |
---|
512 | // test of the actions.) |
---|
513 | // It set value of drop down in toolbar to reflect font/font size/format block |
---|
514 | // of text at current caret position. |
---|
515 | // tags: |
---|
516 | // protected |
---|
517 | var _e = this.editor; |
---|
518 | var _c = this.command; |
---|
519 | if(!_e || !_e.isLoaded || !_c.length){ |
---|
520 | return; |
---|
521 | } |
---|
522 | |
---|
523 | if(this.button){ |
---|
524 | var disabled = this.get("disabled"); |
---|
525 | this.button.set("disabled", disabled); |
---|
526 | if(disabled){ |
---|
527 | return; |
---|
528 | } |
---|
529 | var value; |
---|
530 | try{ |
---|
531 | value = _e.queryCommandValue(_c) || ""; |
---|
532 | }catch(e){ |
---|
533 | //Firefox may throw error above if the editor is just loaded, ignore it |
---|
534 | value = ""; |
---|
535 | } |
---|
536 | |
---|
537 | // strip off single quotes, if any |
---|
538 | var quoted = lang.isString(value) && value.match(/'([^']*)'/); |
---|
539 | if(quoted){ |
---|
540 | value = quoted[1]; |
---|
541 | } |
---|
542 | |
---|
543 | if(_c === "formatBlock"){ |
---|
544 | if(!value || value == "p"){ |
---|
545 | // Some browsers (WebKit) doesn't actually get the tag info right. |
---|
546 | // and IE returns paragraph when in a DIV!, so incorrect a lot, |
---|
547 | // so we have double-check it. |
---|
548 | value = null; |
---|
549 | var elem; |
---|
550 | // Try to find the current element where the caret is. |
---|
551 | var sel = rangeapi.getSelection(this.editor.window); |
---|
552 | if(sel && sel.rangeCount > 0){ |
---|
553 | var range = sel.getRangeAt(0); |
---|
554 | if(range){ |
---|
555 | elem = range.endContainer; |
---|
556 | } |
---|
557 | } |
---|
558 | |
---|
559 | // Okay, now see if we can find one of the formatting types we're in. |
---|
560 | while(elem && elem !== _e.editNode && elem !== _e.document){ |
---|
561 | var tg = elem.tagName ? elem.tagName.toLowerCase() : ""; |
---|
562 | if(tg && array.indexOf(this.button.values, tg) > -1){ |
---|
563 | value = tg; |
---|
564 | break; |
---|
565 | } |
---|
566 | elem = elem.parentNode; |
---|
567 | } |
---|
568 | if(!value){ |
---|
569 | // Still no value, so lets select 'none'. |
---|
570 | value = "noFormat"; |
---|
571 | } |
---|
572 | }else{ |
---|
573 | // Check that the block format is one allowed, if not, |
---|
574 | // null it so that it gets set to empty. |
---|
575 | if(array.indexOf(this.button.values, value) < 0){ |
---|
576 | value = "noFormat"; |
---|
577 | } |
---|
578 | } |
---|
579 | } |
---|
580 | if(value !== this.button.get("value")){ |
---|
581 | // Set the value, but denote it is not a priority change, so no |
---|
582 | // onchange fires. |
---|
583 | this.button.set('value', value, false); |
---|
584 | } |
---|
585 | } |
---|
586 | } |
---|
587 | }); |
---|
588 | |
---|
589 | // Register these plugins |
---|
590 | array.forEach(["fontName", "fontSize", "formatBlock"], function(name){ |
---|
591 | _Plugin.registry[name] = function(args){ |
---|
592 | return new FontChoice({ |
---|
593 | command: name, |
---|
594 | plainText: args.plainText |
---|
595 | }); |
---|
596 | }; |
---|
597 | }); |
---|
598 | |
---|
599 | // Make all classes available through AMD, and return main class |
---|
600 | FontChoice._FontDropDown = _FontDropDown; |
---|
601 | FontChoice._FontNameDropDown = _FontNameDropDown; |
---|
602 | FontChoice._FontSizeDropDown = _FontSizeDropDown; |
---|
603 | FontChoice._FormatBlockDropDown = _FormatBlockDropDown; |
---|
604 | return FontChoice; |
---|
605 | |
---|
606 | }); |
---|