New file |
0,0 → 1,238 |
if(!dojo._hasResource["dijit.form.Textarea"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. |
dojo._hasResource["dijit.form.Textarea"] = true; |
dojo.provide("dijit.form.Textarea"); |
|
dojo.require("dijit.form._FormWidget"); |
dojo.require("dojo.i18n"); |
dojo.requireLocalization("dijit", "Textarea", null, "ROOT"); |
|
dojo.declare( |
"dijit.form.Textarea", |
dijit.form._FormWidget, |
{ |
// summary |
// A textarea that resizes vertically to contain the data. |
// Takes nearly all the parameters (name, value, etc.) that a vanilla textarea takes. |
// Cols is not supported and the width should be specified with style width. |
// Rows is not supported since this widget adjusts the height. |
// usage: |
// <textarea dojoType="dijit.form.TextArea">...</textarea> |
|
attributeMap: dojo.mixin(dojo.clone(dijit.form._FormWidget.prototype.attributeMap), |
{style:"styleNode", 'class':"styleNode"}), |
|
templateString: (dojo.isIE || dojo.isSafari || dojo.isMozilla) ? |
((dojo.isIE || dojo.isSafari) ? '<fieldset id="${id}" class="dijitInline dijitInputField dijitTextArea" dojoAttachPoint="styleNode" waiRole="presentation"><div dojoAttachPoint="editNode,focusNode,eventNode" dojoAttachEvent="onpaste:_changing,oncut:_changing" waiRole="textarea" style="text-decoration:none;_padding-bottom:16px;display:block;overflow:auto;" contentEditable="true"></div>' |
: '<span id="${id}" class="dijitReset">'+ |
'<iframe src="javascript:<html><head><title>${_iframeEditTitle}</title></head><body><script>var _postCreate=window.frameElement?window.frameElement.postCreate:null;if(_postCreate)_postCreate();</script></body></html>"'+ |
' dojoAttachPoint="iframe,styleNode" dojoAttachEvent="onblur:_onIframeBlur" class="dijitInline dijitInputField dijitTextArea"></iframe>') |
+ '<textarea name="${name}" value="${value}" dojoAttachPoint="formValueNode" style="display:none;"></textarea>' |
+ ((dojo.isIE || dojo.isSafari) ? '</fieldset>':'</span>') |
: '<textarea id="${id}" name="${name}" value="${value}" dojoAttachPoint="formValueNode,editNode,focusNode,styleNode" class="dijitInputField dijitTextArea"></textarea>', |
|
focus: function(){ |
// summary: Received focus, needed for the InlineEditBox widget |
if(!this.disabled){ |
this._changing(); // set initial height |
} |
if(dojo.isMozilla){ |
dijit.focus(this.iframe); |
}else{ |
dijit.focus(this.focusNode); |
} |
}, |
|
setValue: function(/*String*/ value, /*Boolean, optional*/ priorityChange){ |
var editNode = this.editNode; |
if(typeof value == "string"){ |
editNode.innerHTML = ""; // wipe out old nodes |
if(value.split){ |
var _this=this; |
var isFirst = true; |
dojo.forEach(value.split("\n"), function(line){ |
if(isFirst){ isFirst = false; } |
else { |
editNode.appendChild(document.createElement("BR")); // preserve line breaks |
} |
editNode.appendChild(document.createTextNode(line)); // use text nodes so that imbedded tags can be edited |
}); |
}else{ |
editNode.appendChild(document.createTextNode(value)); |
} |
}else{ |
// blah<BR>blah --> blah\nblah |
// <P>blah</P><P>blah</P> --> blah\nblah |
// <DIV>blah</DIV><DIV>blah</DIV> --> blah\nblah |
// &<> -->&< > |
value = editNode.innerHTML; |
if(this.iframe){ // strip sizeNode |
value = value.replace(/<div><\/div>\r?\n?$/i,""); |
} |
value = value.replace(/\s*\r?\n|^\s+|\s+$| /g,"").replace(/>\s+</g,"><").replace(/<\/(p|div)>$|^<(p|div)[^>]*>/gi,"").replace(/([^>])<div>/g,"$1\n").replace(/<\/p>\s*<p[^>]*>|<br[^>]*>/gi,"\n").replace(/<[^>]*>/g,"").replace(/&/gi,"\&").replace(/</gi,"<").replace(/>/gi,">"); |
} |
this.value = this.formValueNode.value = value; |
if(this.iframe){ |
var sizeNode = document.createElement('div'); |
editNode.appendChild(sizeNode); |
var newHeight = sizeNode.offsetTop; |
if(editNode.scrollWidth > editNode.clientWidth){ newHeight+=16; } // scrollbar space needed? |
if(this.lastHeight != newHeight){ // cache size so that we don't get a resize event because of a resize event |
if(newHeight == 0){ newHeight = 16; } // height = 0 causes the browser to not set scrollHeight |
dojo.contentBox(this.iframe, {h: newHeight}); |
this.lastHeight = newHeight; |
} |
editNode.removeChild(sizeNode); |
} |
dijit.form.Textarea.superclass.setValue.call(this, this.getValue(), priorityChange); |
}, |
|
getValue: function(){ |
return this.formValueNode.value.replace(/\r/g,""); |
}, |
|
postMixInProperties: function(){ |
dijit.form.Textarea.superclass.postMixInProperties.apply(this,arguments); |
// don't let the source text be converted to a DOM structure since we just want raw text |
if(this.srcNodeRef && this.srcNodeRef.innerHTML != ""){ |
this.value = this.srcNodeRef.innerHTML; |
this.srcNodeRef.innerHTML = ""; |
} |
if((!this.value || this.value == "") && this.srcNodeRef && this.srcNodeRef.value){ |
this.value = this.srcNodeRef.value; |
} |
if(!this.value){ this.value = ""; } |
this.value = this.value.replace(/\r\n/g,"\n").replace(/>/g,">").replace(/</g,"<").replace(/&/g,"&"); |
if(dojo.isMozilla){ |
// In the case of Firefox an iframe is used and when the text gets focus, |
// focus is fired from the document object. There isn't a way to put a |
// waiRole on the document object and as a result screen readers don't |
// announce the role. As a result screen reader users are lost. |
// |
// An additional problem is that the browser gives the document object a |
// very cryptic accessible name, e.g. |
// wysiwyg://13/http://archive.dojotoolkit.org/nightly/dojotoolkit/dijit/tests/form/test_InlineEditBox.html |
// When focus is fired from the document object, the screen reader speaks |
// the accessible name. The cyptic accessile name is confusing. |
// |
// A workaround for both of these problems is to give the iframe's |
// document a title, the name of which is similar to a role name, i.e. |
// "edit area". This will be used as the accessible name which will replace |
// the cryptic name and will also convey the role information to the user. |
// Because it is read directly to the user, the string must be localized. |
// In addition, since a <label> element can not be associated with an iframe, if |
// this control has a label, insert the text into the title as well. |
var _nlsResources = dojo.i18n.getLocalization("dijit", "Textarea"); |
this._iframeEditTitle = _nlsResources.iframeEditTitle; |
this._iframeFocusTitle = _nlsResources.iframeFocusTitle; |
var label=dojo.query('label[for="'+this.id+'"]'); |
if(label.length){ |
this._iframeEditTitle = label[0].innerHTML + " " + this._iframeEditTitle; |
} |
var body = this.focusNode = this.editNode = document.createElement('BODY'); |
body.style.margin="0px"; |
body.style.padding="0px"; |
body.style.border="0px"; |
} |
}, |
|
postCreate: function(){ |
if(dojo.isIE || dojo.isSafari){ |
this.domNode.style.overflowY = 'hidden'; |
}else if(dojo.isMozilla){ |
var w = this.iframe.contentWindow; |
try { // #4715: peeking at the title can throw a security exception during iframe setup |
var title = this.iframe.contentDocument.title; |
} catch(e) { var title = ''; } |
if(!w || !title){ |
this.iframe.postCreate = dojo.hitch(this, this.postCreate); |
return; |
} |
var d = w.document; |
d.getElementsByTagName('HTML')[0].replaceChild(this.editNode, d.getElementsByTagName('BODY')[0]); |
if(!this.isLeftToRight()){ |
d.getElementsByTagName('HTML')[0].dir = "rtl"; |
} |
this.iframe.style.overflowY = 'hidden'; |
this.eventNode = d; |
// this.connect won't destroy this handler cleanly since its on the iframe's window object |
// resize is a method of window, not document |
w.addEventListener("resize", dojo.hitch(this, this._changed), false); // resize is only on the window object |
}else{ |
this.focusNode = this.domNode; |
} |
if(this.eventNode){ |
this.connect(this.eventNode, "keypress", this._onKeyPress); |
this.connect(this.eventNode, "mousemove", this._changed); |
this.connect(this.eventNode, "focus", this._focused); |
this.connect(this.eventNode, "blur", this._blurred); |
} |
if(this.editNode){ |
this.connect(this.editNode, "change", this._changed); // needed for mouse paste events per #3479 |
} |
this.inherited('postCreate', arguments); |
}, |
|
// event handlers, you can over-ride these in your own subclasses |
_focused: function(e){ |
dojo.addClass(this.iframe||this.domNode, "dijitInputFieldFocused"); |
this._changed(e); |
}, |
|
_blurred: function(e){ |
dojo.removeClass(this.iframe||this.domNode, "dijitInputFieldFocused"); |
this._changed(e, true); |
}, |
|
_onIframeBlur: function(){ |
// Reset the title back to "edit area". |
this.iframe.contentDocument.title = this._iframeEditTitle; |
}, |
|
_onKeyPress: function(e){ |
if(e.keyCode == dojo.keys.TAB && !e.shiftKey && !e.ctrlKey && !e.altKey && this.iframe){ |
// Pressing the tab key in the iframe (with designMode on) will cause the |
// entry of a tab character so we have to trap that here. Since we don't |
// know the next focusable object we put focus on the iframe and then the |
// user has to press tab again (which then does the expected thing). |
// A problem with that is that the screen reader user hears "edit area" |
// announced twice which causes confusion. By setting the |
// contentDocument's title to "edit area frame" the confusion should be |
// eliminated. |
this.iframe.contentDocument.title = this._iframeFocusTitle; |
// Place focus on the iframe. A subsequent tab or shift tab will put focus |
// on the correct control. |
// Note: Can't use this.focus() because that results in a call to |
// dijit.focus and if that receives an iframe target it will set focus |
// on the iframe's contentWindow. |
this.iframe.focus(); // this.focus(); won't work |
dojo.stopEvent(e); |
}else if(e.keyCode == dojo.keys.ENTER){ |
e.stopPropagation(); |
}else if(this.inherited("_onKeyPress", arguments) && this.iframe){ |
// #3752: |
// The key press will not make it past the iframe. |
// If a widget is listening outside of the iframe, (like InlineEditBox) |
// it will not hear anything. |
// Create an equivalent event so everyone else knows what is going on. |
var te = document.createEvent("KeyEvents"); |
te.initKeyEvent("keypress", true, true, null, e.ctrlKey, e.altKey, e.shiftKey, e.metaKey, e.keyCode, e.charCode); |
this.iframe.dispatchEvent(te); |
} |
this._changing(); |
}, |
|
_changing: function(e){ |
// summary: event handler for when a change is imminent |
setTimeout(dojo.hitch(this, "_changed", e, false), 1); |
}, |
|
_changed: function(e, priorityChange){ |
// summary: event handler for when a change has already happened |
if(this.iframe && this.iframe.contentDocument.designMode != "on"){ |
this.iframe.contentDocument.designMode="on"; // in case this failed on init due to being hidden |
} |
this.setValue(null, priorityChange); |
} |
}); |
|
} |