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