2150 |
mathias |
1 |
if(!dojo._hasResource["dijit.form.InlineEditBox"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
|
|
|
2 |
dojo._hasResource["dijit.form.InlineEditBox"] = true;
|
|
|
3 |
dojo.provide("dijit.form.InlineEditBox");
|
|
|
4 |
|
|
|
5 |
dojo.require("dojo.i18n");
|
|
|
6 |
|
|
|
7 |
dojo.require("dijit.form._FormWidget");
|
|
|
8 |
dojo.require("dijit._Container");
|
|
|
9 |
dojo.require("dijit.form.Button");
|
|
|
10 |
|
|
|
11 |
dojo.requireLocalization("dijit", "common", null, "ko,zh,ja,zh-tw,ru,it,hu,fr,pt,ROOT,pl,es,de,cs");
|
|
|
12 |
|
|
|
13 |
dojo.deprecated("dijit.form.InlineEditBox is deprecated, use dijit.InlineEditBox instead", "", "1.1");
|
|
|
14 |
|
|
|
15 |
dojo.declare(
|
|
|
16 |
"dijit.form.InlineEditBox",
|
|
|
17 |
[dijit.form._FormWidget, dijit._Container],
|
|
|
18 |
// summary
|
|
|
19 |
// Wrapper widget to a text edit widget.
|
|
|
20 |
// The text is displayed on the page using normal user-styling.
|
|
|
21 |
// When clicked, the text is hidden, and the edit widget is
|
|
|
22 |
// visible, allowing the text to be updated. Optionally,
|
|
|
23 |
// Save and Cancel button are displayed below the edit widget.
|
|
|
24 |
// When Save is clicked, the text is pulled from the edit
|
|
|
25 |
// widget and redisplayed and the edit widget is again hidden.
|
|
|
26 |
// Currently all textboxes that inherit from dijit.form.TextBox
|
|
|
27 |
// are supported edit widgets.
|
|
|
28 |
// An edit widget must support the following API to be used:
|
|
|
29 |
// String getDisplayedValue() OR String getValue()
|
|
|
30 |
// void setDisplayedValue(String) OR void setValue(String)
|
|
|
31 |
// void focus()
|
|
|
32 |
// It must also be able to initialize with style="display:none;" set.
|
|
|
33 |
{
|
|
|
34 |
templateString:"<span\n\t><fieldset dojoAttachPoint=\"editNode\" style=\"display:none;\" waiRole=\"presentation\"\n\t\t><div dojoAttachPoint=\"containerNode\" dojoAttachEvent=\"onkeypress:_onEditWidgetKeyPress\"></div\n\t\t><div dojoAttachPoint=\"buttonContainer\"\n\t\t\t><button class='saveButton' dojoAttachPoint=\"saveButton\" dojoType=\"dijit.form.Button\" dojoAttachEvent=\"onClick:save\">${buttonSave}</button\n\t\t\t><button class='cancelButton' dojoAttachPoint=\"cancelButton\" dojoType=\"dijit.form.Button\" dojoAttachEvent=\"onClick:cancel\">${buttonCancel}</button\n\t\t></div\n\t></fieldset\n\t><span tabIndex=\"0\" dojoAttachPoint=\"textNode,focusNode\" waiRole=\"button\" style=\"display:none;\"\n\t\tdojoAttachEvent=\"onkeypress:_onKeyPress,onclick:_onClick,onmouseout:_onMouseOut,onmouseover:_onMouseOver,onfocus:_onMouseOver,onblur:_onMouseOut\"\n\t></span\n></span>\n",
|
|
|
35 |
|
|
|
36 |
// editing: Boolean
|
|
|
37 |
// Is the node currently in edit mode?
|
|
|
38 |
editing: false,
|
|
|
39 |
|
|
|
40 |
// autoSave: Boolean
|
|
|
41 |
// Changing the value automatically saves it, don't have to push save button
|
|
|
42 |
autoSave: true,
|
|
|
43 |
|
|
|
44 |
// buttonSave: String
|
|
|
45 |
// Save button label
|
|
|
46 |
buttonSave: "",
|
|
|
47 |
|
|
|
48 |
// buttonCancel: String
|
|
|
49 |
// Cancel button label
|
|
|
50 |
buttonCancel: "",
|
|
|
51 |
|
|
|
52 |
// renderAsHtml: Boolean
|
|
|
53 |
// should text render as HTML(true) or plain text(false)
|
|
|
54 |
renderAsHtml: false,
|
|
|
55 |
|
|
|
56 |
widgetsInTemplate: true,
|
|
|
57 |
|
|
|
58 |
// _display: String
|
|
|
59 |
// srcNodeRef display style
|
|
|
60 |
_display:"",
|
|
|
61 |
|
|
|
62 |
startup: function(){
|
|
|
63 |
// look for the input widget as a child of the containerNode
|
|
|
64 |
if(!this._started){
|
|
|
65 |
|
|
|
66 |
if(this.editWidget){
|
|
|
67 |
this.containerNode.appendChild(this.editWidget.domNode);
|
|
|
68 |
}else{
|
|
|
69 |
this.editWidget = this.getChildren()[0];
|
|
|
70 |
}
|
|
|
71 |
// #3209: copy the style from the source
|
|
|
72 |
// don't copy ALL properties though, just the necessary/applicable ones
|
|
|
73 |
var srcStyle=dojo.getComputedStyle(this.domNode);
|
|
|
74 |
dojo.forEach(["fontWeight","fontFamily","fontSize","fontStyle"], function(prop){
|
|
|
75 |
this.editWidget.focusNode.style[prop]=srcStyle[prop];
|
|
|
76 |
}, this);
|
|
|
77 |
this._setEditValue = dojo.hitch(this.editWidget,this.editWidget.setDisplayedValue||this.editWidget.setValue);
|
|
|
78 |
this._getEditValue = dojo.hitch(this.editWidget,this.editWidget.getDisplayedValue||this.editWidget.getValue);
|
|
|
79 |
this._setEditFocus = dojo.hitch(this.editWidget,this.editWidget.focus);
|
|
|
80 |
this._isEditValid = dojo.hitch(this.editWidget,this.editWidget.isValid || function(){return true;});
|
|
|
81 |
this.editWidget.onChange = dojo.hitch(this, "_onChange");
|
|
|
82 |
|
|
|
83 |
if(!this.autoSave){ // take over the setValue method so we can know when the value changes
|
|
|
84 |
this._oldSetValue = this.editWidget.setValue;
|
|
|
85 |
var _this = this;
|
|
|
86 |
this.editWidget.setValue = dojo.hitch(this, function(value){
|
|
|
87 |
_this._oldSetValue.apply(_this.editWidget, arguments);
|
|
|
88 |
_this._onEditWidgetKeyPress(null); // check the Save button
|
|
|
89 |
});
|
|
|
90 |
}
|
|
|
91 |
this._showText();
|
|
|
92 |
|
|
|
93 |
this._started = true;
|
|
|
94 |
}
|
|
|
95 |
},
|
|
|
96 |
|
|
|
97 |
postMixInProperties: function(){
|
|
|
98 |
this._srcTag = this.srcNodeRef.tagName;
|
|
|
99 |
this._srcStyle=dojo.getComputedStyle(this.srcNodeRef);
|
|
|
100 |
// getComputedStyle is not good until after onLoad is called
|
|
|
101 |
var srcNodeStyle = this.srcNodeRef.style;
|
|
|
102 |
this._display="";
|
|
|
103 |
if(srcNodeStyle && srcNodeStyle.display){ this._display=srcNodeStyle.display; }
|
|
|
104 |
else{
|
|
|
105 |
switch(this.srcNodeRef.tagName.toLowerCase()){
|
|
|
106 |
case 'span':
|
|
|
107 |
case 'input':
|
|
|
108 |
case 'img':
|
|
|
109 |
case 'button':
|
|
|
110 |
this._display='inline';
|
|
|
111 |
break;
|
|
|
112 |
default:
|
|
|
113 |
this._display='block';
|
|
|
114 |
break;
|
|
|
115 |
}
|
|
|
116 |
}
|
|
|
117 |
this.inherited('postMixInProperties', arguments);
|
|
|
118 |
this.messages = dojo.i18n.getLocalization("dijit", "common", this.lang);
|
|
|
119 |
dojo.forEach(["buttonSave", "buttonCancel"], function(prop){
|
|
|
120 |
if(!this[prop]){ this[prop] = this.messages[prop]; }
|
|
|
121 |
}, this);
|
|
|
122 |
},
|
|
|
123 |
|
|
|
124 |
postCreate: function(){
|
|
|
125 |
// don't call setValue yet since the editing widget is not setup
|
|
|
126 |
if(this.autoSave){
|
|
|
127 |
dojo.style(this.buttonContainer, "display", "none");
|
|
|
128 |
}
|
|
|
129 |
},
|
|
|
130 |
|
|
|
131 |
_onKeyPress: function(e){
|
|
|
132 |
// summary: handle keypress when edit box is not open
|
|
|
133 |
if(this.disabled || e.altKey || e.ctrlKey){ return; }
|
|
|
134 |
if(e.charCode == dojo.keys.SPACE || e.keyCode == dojo.keys.ENTER){
|
|
|
135 |
dojo.stopEvent(e);
|
|
|
136 |
this._onClick(e);
|
|
|
137 |
}
|
|
|
138 |
},
|
|
|
139 |
|
|
|
140 |
_onMouseOver: function(){
|
|
|
141 |
if(!this.editing){
|
|
|
142 |
var classname = this.disabled ? "dijitDisabledClickableRegion" : "dijitClickableRegion";
|
|
|
143 |
dojo.addClass(this.textNode, classname);
|
|
|
144 |
}
|
|
|
145 |
},
|
|
|
146 |
|
|
|
147 |
_onMouseOut: function(){
|
|
|
148 |
if(!this.editing){
|
|
|
149 |
var classStr = this.disabled ? "dijitDisabledClickableRegion" : "dijitClickableRegion";
|
|
|
150 |
dojo.removeClass(this.textNode, classStr);
|
|
|
151 |
}
|
|
|
152 |
},
|
|
|
153 |
|
|
|
154 |
_onClick: function(e){
|
|
|
155 |
// summary
|
|
|
156 |
// When user clicks the text, then start editing.
|
|
|
157 |
// Hide the text and display the form instead.
|
|
|
158 |
|
|
|
159 |
if(this.editing || this.disabled){ return; }
|
|
|
160 |
this._onMouseOut();
|
|
|
161 |
this.editing = true;
|
|
|
162 |
|
|
|
163 |
// show the edit form and hide the read only version of the text
|
|
|
164 |
this._setEditValue(this._isEmpty ? '' : (this.renderAsHtml ? this.textNode.innerHTML : this.textNode.innerHTML.replace(/\s*\r?\n\s*/g,"").replace(/<br\/?>/gi, "\n").replace(/>/g,">").replace(/</g,"<").replace(/&/g,"&")));
|
|
|
165 |
this._initialText = this._getEditValue();
|
|
|
166 |
this._visualize();
|
|
|
167 |
// Before changing the focus, give the browser time to render.
|
|
|
168 |
setTimeout(dojo.hitch(this, function(){
|
|
|
169 |
this._setEditFocus();
|
|
|
170 |
this.saveButton.setDisabled(true);
|
|
|
171 |
}), 1);
|
|
|
172 |
},
|
|
|
173 |
|
|
|
174 |
_visualize: function(){
|
|
|
175 |
dojo.style(this.editNode, "display", this.editing ? this._display : "none");
|
|
|
176 |
// #3749: try to set focus now to fix missing caret
|
|
|
177 |
// #3997: call right after this.containerNode appears
|
|
|
178 |
if(this.editing){this._setEditFocus();}
|
|
|
179 |
dojo.style(this.textNode, "display", this.editing ? "none" : this._display);
|
|
|
180 |
},
|
|
|
181 |
|
|
|
182 |
_showText: function(){
|
|
|
183 |
var value = "" + this._getEditValue(); // "" is to make sure its a string
|
|
|
184 |
dijit.form.InlineEditBox.superclass.setValue.call(this, value);
|
|
|
185 |
// whitespace is really hard to click so show a ?
|
|
|
186 |
// TODO: show user defined message in gray
|
|
|
187 |
if(/^\s*$/.test(value)){ value = "?"; this._isEmpty = true; }
|
|
|
188 |
else { this._isEmpty = false; }
|
|
|
189 |
if(this.renderAsHtml){
|
|
|
190 |
this.textNode.innerHTML = value;
|
|
|
191 |
}else{
|
|
|
192 |
this.textNode.innerHTML = "";
|
|
|
193 |
if(value.split){
|
|
|
194 |
var _this=this;
|
|
|
195 |
var isFirst = true;
|
|
|
196 |
dojo.forEach(value.split("\n"), function(line){
|
|
|
197 |
if(isFirst){
|
|
|
198 |
isFirst = false;
|
|
|
199 |
}else{
|
|
|
200 |
_this.textNode.appendChild(document.createElement("BR")); // preserve line breaks
|
|
|
201 |
}
|
|
|
202 |
_this.textNode.appendChild(document.createTextNode(line)); // use text nodes so that imbedded tags can be edited
|
|
|
203 |
});
|
|
|
204 |
}else{
|
|
|
205 |
this.textNode.appendChild(document.createTextNode(value));
|
|
|
206 |
}
|
|
|
207 |
}
|
|
|
208 |
this._visualize();
|
|
|
209 |
},
|
|
|
210 |
|
|
|
211 |
save: function(e){
|
|
|
212 |
// summary: Callback when user presses "Save" button or it's simulated.
|
|
|
213 |
// e is passed in if click on save button or user presses Enter. It's not
|
|
|
214 |
// passed in when called by _onBlur.
|
|
|
215 |
if(typeof e == "object"){ dojo.stopEvent(e); }
|
|
|
216 |
if(!this.enableSave()){ return; }
|
|
|
217 |
this.editing = false;
|
|
|
218 |
this._showText();
|
|
|
219 |
// If save button pressed on non-autoSave widget or Enter pressed on autoSave
|
|
|
220 |
// widget, restore focus to the inline text.
|
|
|
221 |
if(e){ dijit.focus(this.focusNode); }
|
|
|
222 |
|
|
|
223 |
if(this._lastValue != this._lastValueReported){
|
|
|
224 |
this.onChange(this._lastValue); // tell the world that we have changed
|
|
|
225 |
}
|
|
|
226 |
},
|
|
|
227 |
|
|
|
228 |
cancel: function(e){
|
|
|
229 |
// summary: Callback when user presses "Cancel" button or it's simulated.
|
|
|
230 |
// e is passed in if click on cancel button or user presses Esc. It's not
|
|
|
231 |
// passed in when called by _onBlur.
|
|
|
232 |
if(e){ dojo.stopEvent(e); }
|
|
|
233 |
this.editing = false;
|
|
|
234 |
this._visualize();
|
|
|
235 |
// If cancel button pressed on non-autoSave widget or Esc pressed on autoSave
|
|
|
236 |
// widget, restore focus to the inline text.
|
|
|
237 |
if(e){ dijit.focus(this.focusNode); }
|
|
|
238 |
},
|
|
|
239 |
|
|
|
240 |
setValue: function(/*String*/ value){
|
|
|
241 |
// sets the text without informing the server
|
|
|
242 |
this._setEditValue(value);
|
|
|
243 |
this.editing = false;
|
|
|
244 |
this._showText();
|
|
|
245 |
},
|
|
|
246 |
|
|
|
247 |
_onEditWidgetKeyPress: function(e){
|
|
|
248 |
// summary:
|
|
|
249 |
// Callback when keypress in the edit box (see template).
|
|
|
250 |
// For autoSave widgets, if Esc/Enter, call cancel/save.
|
|
|
251 |
// For non-autoSave widgets, enable save button if the text value is
|
|
|
252 |
// different than the original value.
|
|
|
253 |
if(!this.editing){ return; }
|
|
|
254 |
if(this.autoSave){
|
|
|
255 |
// If Enter/Esc pressed, treat as save/cancel.
|
|
|
256 |
if(e.keyCode == dojo.keys.ESCAPE){
|
|
|
257 |
this.cancel(e);
|
|
|
258 |
}else if(e.keyCode == dojo.keys.ENTER){
|
|
|
259 |
this.save(e);
|
|
|
260 |
}
|
|
|
261 |
}else{
|
|
|
262 |
var _this = this;
|
|
|
263 |
// Delay before calling _getEditValue.
|
|
|
264 |
// The delay gives the browser a chance to update the textarea.
|
|
|
265 |
setTimeout(
|
|
|
266 |
function(){
|
|
|
267 |
_this.saveButton.setDisabled(_this._getEditValue() == _this._initialText);
|
|
|
268 |
}, 100);
|
|
|
269 |
}
|
|
|
270 |
},
|
|
|
271 |
|
|
|
272 |
_onBlur: function(){
|
|
|
273 |
// summary:
|
|
|
274 |
// Called by the focus manager in focus.js when focus moves outside of the
|
|
|
275 |
// InlineEditBox widget (or it's descendants).
|
|
|
276 |
if(this.autoSave && this.editing){
|
|
|
277 |
if(this._getEditValue() == this._initialText){
|
|
|
278 |
this.cancel();
|
|
|
279 |
}else{
|
|
|
280 |
this.save();
|
|
|
281 |
}
|
|
|
282 |
}
|
|
|
283 |
},
|
|
|
284 |
|
|
|
285 |
|
|
|
286 |
enableSave: function(){
|
|
|
287 |
// summary: User replacable function returning a Boolean to indicate
|
|
|
288 |
// if the Save button should be enabled or not - usually due to invalid conditions
|
|
|
289 |
return this._isEditValid();
|
|
|
290 |
},
|
|
|
291 |
|
|
|
292 |
_onChange: function(){
|
|
|
293 |
// summary:
|
|
|
294 |
// This is called when the underlying widget fires an onChange event,
|
|
|
295 |
// which means that the user has finished entering the value
|
|
|
296 |
if(!this.editing){
|
|
|
297 |
this._showText(); // asynchronous update made famous by ComboBox/FilteringSelect
|
|
|
298 |
}else if(this.autoSave){
|
|
|
299 |
this.save(1);
|
|
|
300 |
}else{
|
|
|
301 |
// #3752
|
|
|
302 |
// if the keypress does not bubble up to the div, (iframe in TextArea blocks it for example)
|
|
|
303 |
// make sure the save button gets enabled
|
|
|
304 |
this.saveButton.setDisabled((this._getEditValue() == this._initialText) || !this.enableSave());
|
|
|
305 |
}
|
|
|
306 |
},
|
|
|
307 |
|
|
|
308 |
setDisabled: function(/*Boolean*/ disabled){
|
|
|
309 |
this.saveButton.setDisabled(disabled);
|
|
|
310 |
this.cancelButton.setDisabled(disabled);
|
|
|
311 |
this.textNode.disabled = disabled;
|
|
|
312 |
this.editWidget.setDisabled(disabled);
|
|
|
313 |
this.inherited('setDisabled', arguments);
|
|
|
314 |
}
|
|
|
315 |
});
|
|
|
316 |
|
|
|
317 |
}
|