1 | define([ |
---|
2 | "dojo/_base/array", // array.forEach |
---|
3 | "dojo/_base/declare", // declare |
---|
4 | "dojo/dom-attr", // domAttr.set domAttr.get |
---|
5 | "dojo/dom-class", // domClass.add domClass.remove domClass.toggle |
---|
6 | "dojo/dom-construct", // domConstruct.create domConstruct.destroy |
---|
7 | "dojo/dom-style", // domStyle.getComputedStyle domStyle.set domStyle.get |
---|
8 | "dojo/_base/event", // event.stop |
---|
9 | "dojo/i18n", // i18n.getLocalization |
---|
10 | "dojo/_base/kernel", // kernel.deprecated |
---|
11 | "dojo/keys", // keys.ENTER keys.ESCAPE |
---|
12 | "dojo/_base/lang", // lang.getObject |
---|
13 | "dojo/_base/sniff", // has("ie") |
---|
14 | "./focus", |
---|
15 | "./_Widget", |
---|
16 | "./_TemplatedMixin", |
---|
17 | "./_WidgetsInTemplateMixin", |
---|
18 | "./_Container", |
---|
19 | "./form/Button", |
---|
20 | "./form/_TextBoxMixin", |
---|
21 | "./form/TextBox", |
---|
22 | "dojo/text!./templates/InlineEditBox.html", |
---|
23 | "dojo/i18n!./nls/common" |
---|
24 | ], function(array, declare, domAttr, domClass, domConstruct, domStyle, event, i18n, kernel, keys, lang, has, |
---|
25 | fm, _Widget, _TemplatedMixin, _WidgetsInTemplateMixin, _Container, Button, _TextBoxMixin, TextBox, template){ |
---|
26 | |
---|
27 | /*===== |
---|
28 | var _Widget = dijit._Widget; |
---|
29 | var _TemplatedMixin = dijit._TemplatedMixin; |
---|
30 | var _WidgetsInTemplateMixin = dijit._WidgetsInTemplateMixin; |
---|
31 | var _Container = dijit._Container; |
---|
32 | var Button = dijit.form.Button; |
---|
33 | var TextBox = dijit.form.TextBox; |
---|
34 | =====*/ |
---|
35 | |
---|
36 | // module: |
---|
37 | // dijit/InlineEditBox |
---|
38 | // summary: |
---|
39 | // An element with in-line edit capabilities |
---|
40 | |
---|
41 | var InlineEditor = declare("dijit._InlineEditor", [_Widget, _TemplatedMixin, _WidgetsInTemplateMixin], { |
---|
42 | // summary: |
---|
43 | // Internal widget used by InlineEditBox, displayed when in editing mode |
---|
44 | // to display the editor and maybe save/cancel buttons. Calling code should |
---|
45 | // connect to save/cancel methods to detect when editing is finished |
---|
46 | // |
---|
47 | // Has mainly the same parameters as InlineEditBox, plus these values: |
---|
48 | // |
---|
49 | // style: Object |
---|
50 | // Set of CSS attributes of display node, to replicate in editor |
---|
51 | // |
---|
52 | // value: String |
---|
53 | // Value as an HTML string or plain text string, depending on renderAsHTML flag |
---|
54 | |
---|
55 | templateString: template, |
---|
56 | |
---|
57 | postMixInProperties: function(){ |
---|
58 | this.inherited(arguments); |
---|
59 | this.messages = i18n.getLocalization("dijit", "common", this.lang); |
---|
60 | array.forEach(["buttonSave", "buttonCancel"], function(prop){ |
---|
61 | if(!this[prop]){ this[prop] = this.messages[prop]; } |
---|
62 | }, this); |
---|
63 | }, |
---|
64 | |
---|
65 | buildRendering: function(){ |
---|
66 | this.inherited(arguments); |
---|
67 | |
---|
68 | // Create edit widget in place in the template |
---|
69 | var cls = typeof this.editor == "string" ? lang.getObject(this.editor) : this.editor; |
---|
70 | |
---|
71 | // Copy the style from the source |
---|
72 | // Don't copy ALL properties though, just the necessary/applicable ones. |
---|
73 | // wrapperStyle/destStyle code is to workaround IE bug where getComputedStyle().fontSize |
---|
74 | // is a relative value like 200%, rather than an absolute value like 24px, and |
---|
75 | // the 200% can refer *either* to a setting on the node or it's ancestor (see #11175) |
---|
76 | var srcStyle = this.sourceStyle, |
---|
77 | editStyle = "line-height:" + srcStyle.lineHeight + ";", |
---|
78 | destStyle = domStyle.getComputedStyle(this.domNode); |
---|
79 | array.forEach(["Weight","Family","Size","Style"], function(prop){ |
---|
80 | var textStyle = srcStyle["font"+prop], |
---|
81 | wrapperStyle = destStyle["font"+prop]; |
---|
82 | if(wrapperStyle != textStyle){ |
---|
83 | editStyle += "font-"+prop+":"+srcStyle["font"+prop]+";"; |
---|
84 | } |
---|
85 | }, this); |
---|
86 | array.forEach(["marginTop","marginBottom","marginLeft", "marginRight"], function(prop){ |
---|
87 | this.domNode.style[prop] = srcStyle[prop]; |
---|
88 | }, this); |
---|
89 | var width = this.inlineEditBox.width; |
---|
90 | if(width == "100%"){ |
---|
91 | // block mode |
---|
92 | editStyle += "width:100%;"; |
---|
93 | this.domNode.style.display = "block"; |
---|
94 | }else{ |
---|
95 | // inline-block mode |
---|
96 | editStyle += "width:" + (width + (Number(width) == width ? "px" : "")) + ";"; |
---|
97 | } |
---|
98 | var editorParams = lang.delegate(this.inlineEditBox.editorParams, { |
---|
99 | style: editStyle, |
---|
100 | dir: this.dir, |
---|
101 | lang: this.lang, |
---|
102 | textDir: this.textDir |
---|
103 | }); |
---|
104 | editorParams[ "displayedValue" in cls.prototype ? "displayedValue" : "value"] = this.value; |
---|
105 | this.editWidget = new cls(editorParams, this.editorPlaceholder); |
---|
106 | |
---|
107 | if(this.inlineEditBox.autoSave){ |
---|
108 | // Remove the save/cancel buttons since saving is done by simply tabbing away or |
---|
109 | // selecting a value from the drop down list |
---|
110 | domConstruct.destroy(this.buttonContainer); |
---|
111 | } |
---|
112 | }, |
---|
113 | |
---|
114 | postCreate: function(){ |
---|
115 | this.inherited(arguments); |
---|
116 | |
---|
117 | var ew = this.editWidget; |
---|
118 | |
---|
119 | if(this.inlineEditBox.autoSave){ |
---|
120 | // Selecting a value from a drop down list causes an onChange event and then we save |
---|
121 | this.connect(ew, "onChange", "_onChange"); |
---|
122 | |
---|
123 | // ESC and TAB should cancel and save. Note that edit widgets do a stopEvent() on ESC key (to |
---|
124 | // prevent Dialog from closing when the user just wants to revert the value in the edit widget), |
---|
125 | // so this is the only way we can see the key press event. |
---|
126 | this.connect(ew, "onKeyPress", "_onKeyPress"); |
---|
127 | }else{ |
---|
128 | // If possible, enable/disable save button based on whether the user has changed the value |
---|
129 | if("intermediateChanges" in ew){ |
---|
130 | ew.set("intermediateChanges", true); |
---|
131 | this.connect(ew, "onChange", "_onIntermediateChange"); |
---|
132 | this.saveButton.set("disabled", true); |
---|
133 | } |
---|
134 | } |
---|
135 | }, |
---|
136 | |
---|
137 | _onIntermediateChange: function(/*===== val =====*/){ |
---|
138 | // summary: |
---|
139 | // Called for editor widgets that support the intermediateChanges=true flag as a way |
---|
140 | // to detect when to enable/disabled the save button |
---|
141 | this.saveButton.set("disabled", (this.getValue() == this._resetValue) || !this.enableSave()); |
---|
142 | }, |
---|
143 | |
---|
144 | destroy: function(){ |
---|
145 | this.editWidget.destroy(true); // let the parent wrapper widget clean up the DOM |
---|
146 | this.inherited(arguments); |
---|
147 | }, |
---|
148 | |
---|
149 | getValue: function(){ |
---|
150 | // summary: |
---|
151 | // Return the [display] value of the edit widget |
---|
152 | var ew = this.editWidget; |
---|
153 | return String(ew.get("displayedValue" in ew ? "displayedValue" : "value")); |
---|
154 | }, |
---|
155 | |
---|
156 | _onKeyPress: function(e){ |
---|
157 | // summary: |
---|
158 | // Handler for keypress in the edit box in autoSave mode. |
---|
159 | // description: |
---|
160 | // For autoSave widgets, if Esc/Enter, call cancel/save. |
---|
161 | // tags: |
---|
162 | // private |
---|
163 | |
---|
164 | if(this.inlineEditBox.autoSave && this.inlineEditBox.editing){ |
---|
165 | if(e.altKey || e.ctrlKey){ return; } |
---|
166 | // If Enter/Esc pressed, treat as save/cancel. |
---|
167 | if(e.charOrCode == keys.ESCAPE){ |
---|
168 | event.stop(e); |
---|
169 | this.cancel(true); // sets editing=false which short-circuits _onBlur processing |
---|
170 | }else if(e.charOrCode == keys.ENTER && e.target.tagName == "INPUT"){ |
---|
171 | event.stop(e); |
---|
172 | this._onChange(); // fire _onBlur and then save |
---|
173 | } |
---|
174 | |
---|
175 | // _onBlur will handle TAB automatically by allowing |
---|
176 | // the TAB to change focus before we mess with the DOM: #6227 |
---|
177 | // Expounding by request: |
---|
178 | // The current focus is on the edit widget input field. |
---|
179 | // save() will hide and destroy this widget. |
---|
180 | // We want the focus to jump from the currently hidden |
---|
181 | // displayNode, but since it's hidden, it's impossible to |
---|
182 | // unhide it, focus it, and then have the browser focus |
---|
183 | // away from it to the next focusable element since each |
---|
184 | // of these events is asynchronous and the focus-to-next-element |
---|
185 | // is already queued. |
---|
186 | // So we allow the browser time to unqueue the move-focus event |
---|
187 | // before we do all the hide/show stuff. |
---|
188 | } |
---|
189 | }, |
---|
190 | |
---|
191 | _onBlur: function(){ |
---|
192 | // summary: |
---|
193 | // Called when focus moves outside the editor |
---|
194 | // tags: |
---|
195 | // private |
---|
196 | |
---|
197 | this.inherited(arguments); |
---|
198 | if(this.inlineEditBox.autoSave && this.inlineEditBox.editing){ |
---|
199 | if(this.getValue() == this._resetValue){ |
---|
200 | this.cancel(false); |
---|
201 | }else if(this.enableSave()){ |
---|
202 | this.save(false); |
---|
203 | } |
---|
204 | } |
---|
205 | }, |
---|
206 | |
---|
207 | _onChange: function(){ |
---|
208 | // summary: |
---|
209 | // Called when the underlying widget fires an onChange event, |
---|
210 | // such as when the user selects a value from the drop down list of a ComboBox, |
---|
211 | // which means that the user has finished entering the value and we should save. |
---|
212 | // tags: |
---|
213 | // private |
---|
214 | |
---|
215 | if(this.inlineEditBox.autoSave && this.inlineEditBox.editing && this.enableSave()){ |
---|
216 | fm.focus(this.inlineEditBox.displayNode); // fires _onBlur which will save the formatted value |
---|
217 | } |
---|
218 | }, |
---|
219 | |
---|
220 | enableSave: function(){ |
---|
221 | // summary: |
---|
222 | // User overridable function returning a Boolean to indicate |
---|
223 | // if the Save button should be enabled or not - usually due to invalid conditions |
---|
224 | // tags: |
---|
225 | // extension |
---|
226 | return ( |
---|
227 | this.editWidget.isValid |
---|
228 | ? this.editWidget.isValid() |
---|
229 | : true |
---|
230 | ); |
---|
231 | }, |
---|
232 | |
---|
233 | focus: function(){ |
---|
234 | // summary: |
---|
235 | // Focus the edit widget. |
---|
236 | // tags: |
---|
237 | // protected |
---|
238 | |
---|
239 | this.editWidget.focus(); |
---|
240 | setTimeout(lang.hitch(this, function(){ |
---|
241 | if(this.editWidget.focusNode && this.editWidget.focusNode.tagName == "INPUT"){ |
---|
242 | _TextBoxMixin.selectInputText(this.editWidget.focusNode); |
---|
243 | } |
---|
244 | }), 0); |
---|
245 | } |
---|
246 | }); |
---|
247 | |
---|
248 | |
---|
249 | var InlineEditBox = declare("dijit.InlineEditBox", _Widget, { |
---|
250 | // summary: |
---|
251 | // An element with in-line edit capabilities |
---|
252 | // |
---|
253 | // description: |
---|
254 | // Behavior for an existing node (`<p>`, `<div>`, `<span>`, etc.) so that |
---|
255 | // when you click it, an editor shows up in place of the original |
---|
256 | // text. Optionally, Save and Cancel button are displayed below the edit widget. |
---|
257 | // When Save is clicked, the text is pulled from the edit |
---|
258 | // widget and redisplayed and the edit widget is again hidden. |
---|
259 | // By default a plain Textarea widget is used as the editor (or for |
---|
260 | // inline values a TextBox), but you can specify an editor such as |
---|
261 | // dijit.Editor (for editing HTML) or a Slider (for adjusting a number). |
---|
262 | // An edit widget must support the following API to be used: |
---|
263 | // - displayedValue or value as initialization parameter, |
---|
264 | // and available through set('displayedValue') / set('value') |
---|
265 | // - void focus() |
---|
266 | // - DOM-node focusNode = node containing editable text |
---|
267 | |
---|
268 | // editing: [readonly] Boolean |
---|
269 | // Is the node currently in edit mode? |
---|
270 | editing: false, |
---|
271 | |
---|
272 | // autoSave: Boolean |
---|
273 | // Changing the value automatically saves it; don't have to push save button |
---|
274 | // (and save button isn't even displayed) |
---|
275 | autoSave: true, |
---|
276 | |
---|
277 | // buttonSave: String |
---|
278 | // Save button label |
---|
279 | buttonSave: "", |
---|
280 | |
---|
281 | // buttonCancel: String |
---|
282 | // Cancel button label |
---|
283 | buttonCancel: "", |
---|
284 | |
---|
285 | // renderAsHtml: Boolean |
---|
286 | // Set this to true if the specified Editor's value should be interpreted as HTML |
---|
287 | // rather than plain text (ex: `dijit.Editor`) |
---|
288 | renderAsHtml: false, |
---|
289 | |
---|
290 | // editor: String|Function |
---|
291 | // Class name (or reference to the Class) for Editor widget |
---|
292 | editor: TextBox, |
---|
293 | |
---|
294 | // editorWrapper: String|Function |
---|
295 | // Class name (or reference to the Class) for widget that wraps the editor widget, displaying save/cancel |
---|
296 | // buttons. |
---|
297 | editorWrapper: InlineEditor, |
---|
298 | |
---|
299 | // editorParams: Object |
---|
300 | // Set of parameters for editor, like {required: true} |
---|
301 | editorParams: {}, |
---|
302 | |
---|
303 | // disabled: Boolean |
---|
304 | // If true, clicking the InlineEditBox to edit it will have no effect. |
---|
305 | disabled: false, |
---|
306 | |
---|
307 | onChange: function(/*===== value =====*/){ |
---|
308 | // summary: |
---|
309 | // Set this handler to be notified of changes to value. |
---|
310 | // tags: |
---|
311 | // callback |
---|
312 | }, |
---|
313 | |
---|
314 | onCancel: function(){ |
---|
315 | // summary: |
---|
316 | // Set this handler to be notified when editing is cancelled. |
---|
317 | // tags: |
---|
318 | // callback |
---|
319 | }, |
---|
320 | |
---|
321 | // width: String |
---|
322 | // Width of editor. By default it's width=100% (ie, block mode). |
---|
323 | width: "100%", |
---|
324 | |
---|
325 | // value: String |
---|
326 | // The display value of the widget in read-only mode |
---|
327 | value: "", |
---|
328 | |
---|
329 | // noValueIndicator: [const] String |
---|
330 | // The text that gets displayed when there is no value (so that the user has a place to click to edit) |
---|
331 | noValueIndicator: has("ie") <= 6 ? // font-family needed on IE6 but it messes up IE8 |
---|
332 | "<span style='font-family: wingdings; text-decoration: underline;'>    ✍    </span>" : |
---|
333 | "<span style='text-decoration: underline;'>    ✍    </span>", // //   == |
---|
334 | |
---|
335 | constructor: function(){ |
---|
336 | // summary: |
---|
337 | // Sets up private arrays etc. |
---|
338 | // tags: |
---|
339 | // private |
---|
340 | this.editorParams = {}; |
---|
341 | }, |
---|
342 | |
---|
343 | postMixInProperties: function(){ |
---|
344 | this.inherited(arguments); |
---|
345 | |
---|
346 | // save pointer to original source node, since Widget nulls-out srcNodeRef |
---|
347 | this.displayNode = this.srcNodeRef; |
---|
348 | |
---|
349 | // connect handlers to the display node |
---|
350 | var events = { |
---|
351 | ondijitclick: "_onClick", |
---|
352 | onmouseover: "_onMouseOver", |
---|
353 | onmouseout: "_onMouseOut", |
---|
354 | onfocus: "_onMouseOver", |
---|
355 | onblur: "_onMouseOut" |
---|
356 | }; |
---|
357 | for(var name in events){ |
---|
358 | this.connect(this.displayNode, name, events[name]); |
---|
359 | } |
---|
360 | this.displayNode.setAttribute("role", "button"); |
---|
361 | if(!this.displayNode.getAttribute("tabIndex")){ |
---|
362 | this.displayNode.setAttribute("tabIndex", 0); |
---|
363 | } |
---|
364 | |
---|
365 | if(!this.value && !("value" in this.params)){ // "" is a good value if specified directly so check params){ |
---|
366 | this.value = lang.trim(this.renderAsHtml ? this.displayNode.innerHTML : |
---|
367 | (this.displayNode.innerText||this.displayNode.textContent||"")); |
---|
368 | } |
---|
369 | if(!this.value){ |
---|
370 | this.displayNode.innerHTML = this.noValueIndicator; |
---|
371 | } |
---|
372 | |
---|
373 | domClass.add(this.displayNode, 'dijitInlineEditBoxDisplayMode'); |
---|
374 | }, |
---|
375 | |
---|
376 | setDisabled: function(/*Boolean*/ disabled){ |
---|
377 | // summary: |
---|
378 | // Deprecated. Use set('disabled', ...) instead. |
---|
379 | // tags: |
---|
380 | // deprecated |
---|
381 | kernel.deprecated("dijit.InlineEditBox.setDisabled() is deprecated. Use set('disabled', bool) instead.", "", "2.0"); |
---|
382 | this.set('disabled', disabled); |
---|
383 | }, |
---|
384 | |
---|
385 | _setDisabledAttr: function(/*Boolean*/ disabled){ |
---|
386 | // summary: |
---|
387 | // Hook to make set("disabled", ...) work. |
---|
388 | // Set disabled state of widget. |
---|
389 | this.domNode.setAttribute("aria-disabled", disabled); |
---|
390 | if(disabled){ |
---|
391 | this.displayNode.removeAttribute("tabIndex"); |
---|
392 | }else{ |
---|
393 | this.displayNode.setAttribute("tabIndex", 0); |
---|
394 | } |
---|
395 | domClass.toggle(this.displayNode, "dijitInlineEditBoxDisplayModeDisabled", disabled); |
---|
396 | this._set("disabled", disabled); |
---|
397 | }, |
---|
398 | |
---|
399 | _onMouseOver: function(){ |
---|
400 | // summary: |
---|
401 | // Handler for onmouseover and onfocus event. |
---|
402 | // tags: |
---|
403 | // private |
---|
404 | if(!this.disabled){ |
---|
405 | domClass.add(this.displayNode, "dijitInlineEditBoxDisplayModeHover"); |
---|
406 | } |
---|
407 | }, |
---|
408 | |
---|
409 | _onMouseOut: function(){ |
---|
410 | // summary: |
---|
411 | // Handler for onmouseout and onblur event. |
---|
412 | // tags: |
---|
413 | // private |
---|
414 | domClass.remove(this.displayNode, "dijitInlineEditBoxDisplayModeHover"); |
---|
415 | }, |
---|
416 | |
---|
417 | _onClick: function(/*Event*/ e){ |
---|
418 | // summary: |
---|
419 | // Handler for onclick event. |
---|
420 | // tags: |
---|
421 | // private |
---|
422 | if(this.disabled){ return; } |
---|
423 | if(e){ event.stop(e); } |
---|
424 | this._onMouseOut(); |
---|
425 | |
---|
426 | // Since FF gets upset if you move a node while in an event handler for that node... |
---|
427 | setTimeout(lang.hitch(this, "edit"), 0); |
---|
428 | }, |
---|
429 | |
---|
430 | edit: function(){ |
---|
431 | // summary: |
---|
432 | // Display the editor widget in place of the original (read only) markup. |
---|
433 | // tags: |
---|
434 | // private |
---|
435 | |
---|
436 | if(this.disabled || this.editing){ return; } |
---|
437 | this._set('editing', true); |
---|
438 | |
---|
439 | // save some display node values that can be restored later |
---|
440 | this._savedPosition = domStyle.get(this.displayNode, "position") || "static"; |
---|
441 | this._savedOpacity = domStyle.get(this.displayNode, "opacity") || "1"; |
---|
442 | this._savedTabIndex = domAttr.get(this.displayNode, "tabIndex") || "0"; |
---|
443 | |
---|
444 | if(this.wrapperWidget){ |
---|
445 | var ew = this.wrapperWidget.editWidget; |
---|
446 | ew.set("displayedValue" in ew ? "displayedValue" : "value", this.value); |
---|
447 | }else{ |
---|
448 | // Placeholder for edit widget |
---|
449 | // Put place holder (and eventually editWidget) before the display node so that it's positioned correctly |
---|
450 | // when Calendar dropdown appears, which happens automatically on focus. |
---|
451 | var placeholder = domConstruct.create("span", null, this.domNode, "before"); |
---|
452 | |
---|
453 | // Create the editor wrapper (the thing that holds the editor widget and the save/cancel buttons) |
---|
454 | var ewc = typeof this.editorWrapper == "string" ? lang.getObject(this.editorWrapper) : this.editorWrapper; |
---|
455 | this.wrapperWidget = new ewc({ |
---|
456 | value: this.value, |
---|
457 | buttonSave: this.buttonSave, |
---|
458 | buttonCancel: this.buttonCancel, |
---|
459 | dir: this.dir, |
---|
460 | lang: this.lang, |
---|
461 | tabIndex: this._savedTabIndex, |
---|
462 | editor: this.editor, |
---|
463 | inlineEditBox: this, |
---|
464 | sourceStyle: domStyle.getComputedStyle(this.displayNode), |
---|
465 | save: lang.hitch(this, "save"), |
---|
466 | cancel: lang.hitch(this, "cancel"), |
---|
467 | textDir: this.textDir |
---|
468 | }, placeholder); |
---|
469 | if(!this._started){ |
---|
470 | this.startup(); |
---|
471 | } |
---|
472 | } |
---|
473 | var ww = this.wrapperWidget; |
---|
474 | |
---|
475 | // to avoid screen jitter, we first create the editor with position:absolute, visibility:hidden, |
---|
476 | // and then when it's finished rendering, we switch from display mode to editor |
---|
477 | // position:absolute releases screen space allocated to the display node |
---|
478 | // opacity:0 is the same as visibility:hidden but is still focusable |
---|
479 | // visiblity:hidden removes focus outline |
---|
480 | |
---|
481 | domStyle.set(this.displayNode, { position: "absolute", opacity: "0" }); // makes display node invisible, display style used for focus-ability |
---|
482 | domStyle.set(ww.domNode, { position: this._savedPosition, visibility: "visible", opacity: "1" }); |
---|
483 | domAttr.set(this.displayNode, "tabIndex", "-1"); // needed by WebKit for TAB from editor to skip displayNode |
---|
484 | |
---|
485 | // Replace the display widget with edit widget, leaving them both displayed for a brief time so that |
---|
486 | // focus can be shifted without incident. (browser may needs some time to render the editor.) |
---|
487 | setTimeout(lang.hitch(ww, function(){ |
---|
488 | this.focus(); // both nodes are showing, so we can switch focus safely |
---|
489 | this._resetValue = this.getValue(); |
---|
490 | }), 0); |
---|
491 | }, |
---|
492 | |
---|
493 | _onBlur: function(){ |
---|
494 | // summary: |
---|
495 | // Called when focus moves outside the InlineEditBox. |
---|
496 | // Performs garbage collection. |
---|
497 | // tags: |
---|
498 | // private |
---|
499 | |
---|
500 | this.inherited(arguments); |
---|
501 | if(!this.editing){ |
---|
502 | /* causes IE focus problems, see TooltipDialog_a11y.html... |
---|
503 | setTimeout(lang.hitch(this, function(){ |
---|
504 | if(this.wrapperWidget){ |
---|
505 | this.wrapperWidget.destroy(); |
---|
506 | delete this.wrapperWidget; |
---|
507 | } |
---|
508 | }), 0); |
---|
509 | */ |
---|
510 | } |
---|
511 | }, |
---|
512 | |
---|
513 | destroy: function(){ |
---|
514 | if(this.wrapperWidget && !this.wrapperWidget._destroyed){ |
---|
515 | this.wrapperWidget.destroy(); |
---|
516 | delete this.wrapperWidget; |
---|
517 | } |
---|
518 | this.inherited(arguments); |
---|
519 | }, |
---|
520 | |
---|
521 | _showText: function(/*Boolean*/ focus){ |
---|
522 | // summary: |
---|
523 | // Revert to display mode, and optionally focus on display node |
---|
524 | // tags: |
---|
525 | // private |
---|
526 | |
---|
527 | var ww = this.wrapperWidget; |
---|
528 | domStyle.set(ww.domNode, { position: "absolute", visibility: "hidden", opacity: "0" }); // hide the editor from mouse/keyboard events |
---|
529 | domStyle.set(this.displayNode, { position: this._savedPosition, opacity: this._savedOpacity }); // make the original text visible |
---|
530 | domAttr.set(this.displayNode, "tabIndex", this._savedTabIndex); |
---|
531 | if(focus){ |
---|
532 | fm.focus(this.displayNode); |
---|
533 | } |
---|
534 | }, |
---|
535 | |
---|
536 | save: function(/*Boolean*/ focus){ |
---|
537 | // summary: |
---|
538 | // Save the contents of the editor and revert to display mode. |
---|
539 | // focus: Boolean |
---|
540 | // Focus on the display mode text |
---|
541 | // tags: |
---|
542 | // private |
---|
543 | |
---|
544 | if(this.disabled || !this.editing){ return; } |
---|
545 | this._set('editing', false); |
---|
546 | |
---|
547 | var ww = this.wrapperWidget; |
---|
548 | var value = ww.getValue(); |
---|
549 | this.set('value', value); // display changed, formatted value |
---|
550 | |
---|
551 | this._showText(focus); // set focus as needed |
---|
552 | }, |
---|
553 | |
---|
554 | setValue: function(/*String*/ val){ |
---|
555 | // summary: |
---|
556 | // Deprecated. Use set('value', ...) instead. |
---|
557 | // tags: |
---|
558 | // deprecated |
---|
559 | kernel.deprecated("dijit.InlineEditBox.setValue() is deprecated. Use set('value', ...) instead.", "", "2.0"); |
---|
560 | return this.set("value", val); |
---|
561 | }, |
---|
562 | |
---|
563 | _setValueAttr: function(/*String*/ val){ |
---|
564 | // summary: |
---|
565 | // Hook to make set("value", ...) work. |
---|
566 | // Inserts specified HTML value into this node, or an "input needed" character if node is blank. |
---|
567 | |
---|
568 | val = lang.trim(val); |
---|
569 | var renderVal = this.renderAsHtml ? val : val.replace(/&/gm, "&").replace(/</gm, "<").replace(/>/gm, ">").replace(/"/gm, """).replace(/\n/g, "<br>"); |
---|
570 | this.displayNode.innerHTML = renderVal || this.noValueIndicator; |
---|
571 | this._set("value", val); |
---|
572 | |
---|
573 | if(this._started){ |
---|
574 | // tell the world that we have changed |
---|
575 | setTimeout(lang.hitch(this, "onChange", val), 0); // setTimeout prevents browser freeze for long-running event handlers |
---|
576 | } |
---|
577 | // contextual (auto) text direction depends on the text value |
---|
578 | if(this.textDir == "auto"){ |
---|
579 | this.applyTextDir(this.displayNode, this.displayNode.innerText); |
---|
580 | } |
---|
581 | }, |
---|
582 | |
---|
583 | getValue: function(){ |
---|
584 | // summary: |
---|
585 | // Deprecated. Use get('value') instead. |
---|
586 | // tags: |
---|
587 | // deprecated |
---|
588 | kernel.deprecated("dijit.InlineEditBox.getValue() is deprecated. Use get('value') instead.", "", "2.0"); |
---|
589 | return this.get("value"); |
---|
590 | }, |
---|
591 | |
---|
592 | cancel: function(/*Boolean*/ focus){ |
---|
593 | // summary: |
---|
594 | // Revert to display mode, discarding any changes made in the editor |
---|
595 | // tags: |
---|
596 | // private |
---|
597 | |
---|
598 | if(this.disabled || !this.editing){ return; } |
---|
599 | this._set('editing', false); |
---|
600 | |
---|
601 | // tell the world that we have no changes |
---|
602 | setTimeout(lang.hitch(this, "onCancel"), 0); // setTimeout prevents browser freeze for long-running event handlers |
---|
603 | |
---|
604 | this._showText(focus); |
---|
605 | }, |
---|
606 | _setTextDirAttr: function(/*String*/ textDir){ |
---|
607 | // summary: |
---|
608 | // Setter for textDir. |
---|
609 | // description: |
---|
610 | // Users shouldn't call this function; they should be calling |
---|
611 | // set('textDir', value) |
---|
612 | // tags: |
---|
613 | // private |
---|
614 | if(!this._created || this.textDir != textDir){ |
---|
615 | this._set("textDir", textDir); |
---|
616 | this.applyTextDir(this.displayNode, this.displayNode.innerText); |
---|
617 | this.displayNode.align = this.dir == "rtl" ? "right" : "left"; //fix the text alignment |
---|
618 | } |
---|
619 | } |
---|
620 | }); |
---|
621 | |
---|
622 | InlineEditBox._InlineEditor = InlineEditor; // for monkey patching |
---|
623 | |
---|
624 | return InlineEditBox; |
---|
625 | }); |
---|