Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
rwt.widgets.base.BasicText.js Maven / Gradle / Ivy
Go to download
The Rich Ajax Platform lets you build rich, Ajax-enabled Web applications.
/*******************************************************************************
* Copyright: 2004, 2012 1&1 Internet AG, Germany, http://www.1und1.de,
* and EclipseSource
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0 which accompanies this
* distribution, and is available at http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* 1&1 Internet AG and others - original API and implementation
* EclipseSource - adaptation for the Eclipse Rich Ajax Platform
******************************************************************************/
rwt.qx.Class.define( "rwt.widgets.base.BasicText", {
extend : rwt.widgets.base.Terminator,
construct : function( value ) {
this.base( arguments );
if( value != null ) {
this.setValue( value );
}
this.initHideFocus();
this.initWidth();
this.initHeight();
this.initTabIndex();
this._selectionStart = 0;
this._selectionLength = 0;
this.__oninput = rwt.util.Functions.bindEvent( this._oninputDom, this );
this.addEventListener( "blur", this._onblur );
this.addEventListener( "keydown", this._onkeydown );
this.addEventListener( "keypress", this._onkeypress );
this.addEventListener( "keyup", this._onkeyup, this );
this.addEventListener( "mousedown", this._onMouseDownUp, this );
this.addEventListener( "mouseup", this._onMouseDownUp, this );
this._updateLineHeight();
this._typed = null;
this._selectionNeedsUpdate = false;
this._applyBrowserFixes();
this._inputOverflow = "hidden";
},
destruct : function() {
if( this._inputElement != null ) {
if( rwt.client.Client.isMshtml() ) {
this._inputElement.onpropertychange = null;
} else {
this._inputElement.removeEventListener( "input", this.__oninput, false );
}
}
this._inputElement = null;
this.__font = null;
if( this._checkTimer ) {
this._checkTimer.dispose();
this._checkTimer = null;
}
},
events: {
"input" : "rwt.event.DataEvent"
},
properties : {
allowStretchX : { refine : true, init : true },
allowStretchY : { refine : true, init : false },
appearance : { refine : true, init : "text-field" },
tabIndex : { refine : true, init : 1 },
hideFocus : { refine : true, init : true },
width : { refine : true, init : "auto" },
height : { refine : true, init : "auto" },
selectable : { refine : true, init : true },
value : {
init : "",
nullable : true,
event : "changeValue",
apply : "_applyValue",
dispose : true // in the case we use i18n text here
},
textAlign : {
check : [ "left", "center", "right", "justify" ],
nullable : true,
themeable : true,
apply : "_applyTextAlign"
},
maxLength : {
check : "Integer",
apply : "_applyMaxLength",
nullable : true
},
readOnly : {
check : "Boolean",
apply : "_applyReadOnly",
init : false,
event : "changeReadOnly"
}
},
members : {
_LINE_HEIGT_FACTOR : 1.2,
_inputTag : "input",
_inputType : "text",
_inputElement : null,
/////////
// API
setSelection : function( selection ) {
this._selectionStart = selection[ 0 ];
this._selectionLength = selection[ 1 ] - selection[ 0 ];
this._renderSelection();
},
getSelection : function() {
return [ this._selectionStart, this._selectionStart + this._selectionLength ];
},
getComputedSelection : function() {
var start = this._getSelectionStart();
var length = this._getSelectionLength();
return [ start, start + length ];
},
getComputedValue : function() {
var result;
if( this._inputElement != null ) {
result = this._inputElement.value;
} else {
result = this.getValue();
}
return result;
},
getInputElement : function() {
return this._inputElement || null;
},
/////////////////////
// selection handling
_renderSelection : function() {
// setting selection here might de-select all other selections, so only render if focused
if( this.isCreated() && this.getFocused() ) {
this._setSelectionStart( this._selectionStart );
this._setSelectionLength( this._selectionLength );
this._selectionNeedsUpdate = false;
}
},
_detectSelectionChange : function() {
if( this._isCreated ) {
var start = this._getSelectionStart();
var length = this._getSelectionLength();
if( typeof start === "undefined" ) {
start = 0;
}
if( typeof length === "undefined" ) {
length = 0;
}
if( this._selectionStart !== start || this._selectionLength !== length ) {
this._handleSelectionChange( start, length );
}
}
},
_handleSelectionChange : function( start, length ) {
this._selectionStart = start;
this._selectionLength = length;
},
_setSelectionStart : rwt.util.Variant.select( "qx.client", {
"mshtml" : function( vStart ) {
this._visualPropertyCheck();
var vText = this._inputElement.value;
// special handling for line-breaks
var i = 0;
while( i < vStart ) {
i = vText.indexOf( "\r\n", i );
if( i === -1 ) {
break;
}
vStart--;
i++;
}
var vRange = this._inputElement.createTextRange();
vRange.collapse();
vRange.move( "character", vStart );
vRange.select();
},
"gecko" : function( vStart ) {
this._visualPropertyCheck();
// the try catch block is neccesary because FireFox raises an exception
// if the property "selectionStart" is read while the element or one of
// its parent elements is invisible
// https://bugzilla.mozilla.org/show_bug.cgi?id=329354
try {
this._inputElement.selectionStart = vStart;
} catch(ex ) {
// do nothing
}
},
"default" : function( vStart) {
this._visualPropertyCheck();
if( this._inputElement.selectionStart !== vStart ) {
this._inputElement.selectionStart = vStart;
}
}
} ),
_getSelectionStart : rwt.util.Variant.select( "qx.client", {
"mshtml" : function() {
this._visualPropertyCheck();
var vSelectionRange = window.document.selection.createRange();
// Check if the document.selection is the text range inside the input element
if( !this._inputElement.contains( vSelectionRange.parentElement() ) ) {
return -1;
}
var vRange = this._inputElement.createTextRange();
var vRange2 = vRange.duplicate();
// Weird Internet Explorer statement
vRange2.moveToBookmark( vSelectionRange.getBookmark() );
vRange.setEndPoint( 'EndToStart', vRange2 );
// for some reason IE doesn’t always count the \n and \r in the length
var textPart = vSelectionRange.text.replace( /[\r\n]/g, '.' );
var textWhole = this._inputElement.value.replace( /[\r\n]/g, '.' );
return textWhole.indexOf( textPart, vRange.text.length );
},
"gecko" : function() {
this._visualPropertyCheck();
var el = this._inputElement;
var result;
// the try catch block is neccesary because FireFox raises an exception
// if the property "selectionStart" is read while the element or one of
// its parent elements is invisible
// https://bugzilla.mozilla.org/show_bug.cgi?id=329354
try {
if( this.isValidString( el.value ) ) {
result = el.selectionStart;
} else {
result = 0;
}
} catch( ex ) {
result = 0;
}
return result;
},
"default" : function() {
this._visualPropertyCheck();
return this._inputElement.selectionStart;
}
} ),
_setSelectionLength : rwt.util.Variant.select( "qx.client", {
"mshtml" : function( vLength ) {
this._visualPropertyCheck();
var vSelectionRange = window.document.selection.createRange();
if( !this._inputElement.contains(vSelectionRange.parentElement() ) ) {
return;
}
vSelectionRange.collapse();
vSelectionRange.moveEnd( "character", vLength );
vSelectionRange.select();
},
"gecko" : function( vLength ) {
this._visualPropertyCheck();
var el = this._inputElement;
// the try catch block is neccesary because FireFox raises an exception
// if the property "selectionStart" is read while the element or one of
// its parent elements is invisible
// https://bugzilla.mozilla.org/show_bug.cgi?id=329354
try {
if( this.isValidString( el.value ) ) {
el.selectionEnd = el.selectionStart + vLength;
}
} catch (ex) {}
},
"default" : function(vLength) {
this._visualPropertyCheck();
var el = this._inputElement;
if( this.isValidString( el.value ) ) {
var end = el.selectionStart + vLength;
if( el.selectionEnd != end ) {
el.selectionEnd = el.selectionStart + vLength;
}
}
}
} ),
_getSelectionLength : rwt.util.Variant.select( "qx.client", {
"mshtml" : function() {
this._visualPropertyCheck();
var vSelectionRange = window.document.selection.createRange();
if( !this._inputElement.contains( vSelectionRange.parentElement() ) ) {
return 0;
}
return vSelectionRange.text.length;
},
"gecko" : function() {
this._visualPropertyCheck();
var el = this._inputElement;
// the try catch block is neccesary because FireFox raises an exception
// if the property "selectionStart" is read while the element or one of
// its parent elements is invisible
// https://bugzilla.mozilla.org/show_bug.cgi?id=329354
try {
return el.selectionEnd - el.selectionStart;
} catch( ex ) {
// do nothing
}
},
"default" : function() {
this._visualPropertyCheck();
var el = this._inputElement;
return el.selectionEnd - el.selectionStart;
}
} ),
selectAll : function() {
this._visualPropertyCheck();
if( this.getValue() != null ) {
this._setSelectionStart( 0 );
this._setSelectionLength( this._inputElement.value.length );
}
// to be sure we get the element selected
this._inputElement.select();
// RAP [if] focus() leads to error in IE if the _inputElement is disabled or not visible.
// 277444: JavaScript error in IE when using setSelection on a ComboViewer with setEnabled
// is false
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=277444
// 280420: [Combo] JavaScript error in IE when using setSelection on an invisible Combo
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=280420
if( this.isEnabled() && this.isSeeable() ) {
this._inputElement.focus();
}
this._detectSelectionChange();
},
////////////
// rendering
_applyElement : function( value, old ) {
this.base( arguments, value, old );
if( value ) {
this._inputElement = document.createElement( this._inputTag );
if( this._inputType ) {
this._inputElement.type = this._inputType;
}
this._inputElement.autoComplete = "off";
this._inputElement.setAttribute( "autoComplete", "off" );
this._inputElement.disabled = this.getEnabled() === false;
this._inputElement.readOnly = this.getReadOnly();
if( rwt.client.Client.isMshtml() ) {
if( this.getValue() != null && this.getValue() !== "" ) {
this._inputElement.value = this.getValue();
} else {
// See Bug 243557 - [Text] Pasting text from clipboard does not trigger ModifyListener
this._inputElement.value = " ";
}
} else {
this._inputElement.value = this.getValue() != null ? this.getValue().toString() : "";
}
if( this.getMaxLength() != null ) {
this._inputElement.maxLength = this.getMaxLength();
}
var istyle = this._inputElement.style;
istyle.padding = 0;
istyle.margin = 0;
istyle.border = "0 none";
istyle.background = "transparent";
istyle.overflow = this._inputOverflow;
istyle.outline = "none";
istyle.resize = "none";
istyle.WebkitAppearance = "none";
istyle.MozAppearance = "none";
this._renderFont();
this._renderTextColor();
this._renderTextAlign();
this._renderCursor();
this._renderTextShadow();
this._textInit();
this._getTargetNode().appendChild( this._inputElement );
this._updateLineHeight();
}
},
_textInit : rwt.util.Variant.select( "qx.client", {
"default" : function() {
// Emulate IE hard-coded margin
// Mozilla by default emulates this IE handling, but in a wrong
// way. IE adds the additional margin to the CSS margin where
// Mozilla replaces it. But this make it possible for the user
// to overwrite the margin, which is not possible in IE.
// See also: https://bugzilla.mozilla.org/show_bug.cgi?id=73817
// NOTE [tb] : Non-IE browser also shift text 1px to the right, correcting with margin:
this._inputElement.style.margin = "1px 0 1px -1px";
this._inputElement.addEventListener( "input", this.__oninput, false );
this._applyBrowserFixesOnCreate();
},
"mshtml" : function() {
this._inputElement.onpropertychange = this.__oninput;
}
} ),
_postApply : function() {
this._syncFieldWidth();
this._syncFieldHeight();
},
_changeInnerWidth : function( value, old ) {
this._syncFieldWidth();
},
_changeInnerHeight : function(value, old) {
this._syncFieldHeight();
this._centerFieldVertically();
},
_syncFieldWidth : function() {
this._inputElement.style.width = Math.max( 2, this.getInnerWidth() ) + "px";
},
_syncFieldHeight : function() {
if( this._inputTag !== "input" ) {
// Reduce height by 2 pixels (the manual or mshtml margin)
this._inputElement.style.height = Math.max( 0, this.getInnerHeight() - 2 ) + "px";
}
},
_applyCursor : function( value, old ) {
if( this._inputElement != null ) {
this._renderCursor();
}
},
_renderCursor : function() {
var style = this._inputElement.style;
var value = this.getCursor();
if( value ) {
if( value === "pointer" && rwt.client.Client.isMshtml() ) {
style.cursor = "hand";
} else {
style.cursor = value;
}
} else {
style.cursor = "";
}
},
_applyTextAlign : function( value, old ) {
if( this._inputElement ) {
this._renderTextAlign();
}
},
_renderTextAlign : function() {
this._inputElement.style.textAlign = this.getTextAlign() || "";
},
_applyEnabled : function( value, old ) {
if( this._inputElement != null ) {
this._inputElement.disabled = value === false;
}
return this.base( arguments, value, old );
},
_applyValue : function( value, old ) {
this._renderValue();
this._detectSelectionChange();
},
_renderValue : function() {
this._inValueProperty = true;
var value = this.getValue();
if( this._inputElement != null ) {
if (value === null) {
value = "";
}
if( this._inputElement.value !== value ) {
this._inputElement.value = value;
}
}
delete this._inValueProperty;
},
_applyMaxLength : function( value, old ) {
if( this._inputElement ) {
this._inputElement.maxLength = value == null ? "" : value;
}
},
_applyReadOnly : function( value, old ) {
if( this._inputElement ) {
this._inputElement.readOnly = value;
}
if( value ) {
this.addState( "readonly" );
} else {
this.removeState( "readonly" );
}
},
_applyTextColor : function( value, old ) {
this._styleTextColor( value );
},
_styleTextColor : function( value ) {
this.__textColor = value;
this._renderTextColor();
},
_renderTextColor : function() {
if( this._inputElement != null ) {
this._inputElement.style.color = this.__textColor || "";
}
},
_applyFont : function( value, old ) {
this._styleFont( value );
this._updateLineHeight();
},
_styleFont : function( value ) {
this.__font = value;
this._renderFont();
},
_renderFont : function() {
if( this._inputElement != null ) {
if( this.__font != null ) {
this.__font.renderElement( this._inputElement );
} else {
rwt.html.Font.resetElement( this._inputElement );
}
}
},
_updateLineHeight : function() {
if( this._inputElement != null ) {
var font = this.getFont();
var height = Math.floor( font.getSize() * this._LINE_HEIGT_FACTOR );
this._inputElement.style.lineHeight = height + "px";
}
},
_applyTextShadow : function( value, oldValue ) {
this.__textShadow = value;
if( this._inputElement ) {
this._renderTextShadow();
}
},
_renderTextShadow : function() {
rwt.html.Style.setTextShadow( this._inputElement, this.__textShadow );
},
_visualizeFocus : function() {
this.base( arguments );
if( !rwt.widgets.util.FocusHandler.blockFocus ) {
try {
this._inputElement.focus();
} catch( ex ) {
// ignore
}
}
},
_visualizeBlur : function() {
this.base( arguments );
try {
this._inputElement.blur();
} catch( ex ) {
// ignore
}
},
_afterAppear : function() {
this.base( arguments );
this._applyBrowserFixesOnAppear();
this._centerFieldVertically();
this._renderSelection();
},
_centerFieldVertically : function() {
if( this._inputTag === "input" && this._inputElement ) {
var innerHeight = this.getInnerHeight();
var inputElementHeight = this._getInputElementHeight();
if( inputElementHeight !== 0 ) {
var top = ( innerHeight - inputElementHeight ) / 2 - 1;
if( top < 0 ) {
top = 0;
}
top = Math.floor( top );
// [if] Set padding instead of style.position of the _inputElement.
// style.position leads to problems with DOM events in FF 3.0.x
// see bug 292487 and bug 284356
this.setStyleProperty( "paddingTop", top + "px" );
}
}
},
_getInputElementHeight : rwt.util.Variant.select( "qx.client", {
"mshtml" : function() {
var result = this._inputElement.offsetHeight;
if( result !== 0 ) {
result -= 2;
}
return result;
},
"default" :function() {
return this._inputElement.offsetHeight;
}
} ),
////////////////
// event handler
_oninputDom : rwt.util.Variant.select( "qx.client", {
"mshtml" : function( event ) {
if( !this._inValueProperty && event.propertyName === "value" ) {
this._oninput();
}
},
"default" : function( event ) {
this._oninput();
}
} ),
_oninput : function() {
try {
var newValue = this.getComputedValue().toString();
var doit = true;
if( this.hasEventListeners( "input" ) ) {
doit = this.dispatchEvent( new rwt.event.DataEvent( "input", this._typed ), true );
}
if( doit ) {
this.setValue( newValue ); // if doit is false, the listener has to do this
} else if( rwt.client.Client.isWebkit() || rwt.client.Client.isMshtml() ){
// some browser set new selection after input event, ignoring all changes before that
rwt.client.Timer.once( this._renderSelection, this, 0 );
this._selectionNeedsUpdate = true;
}
} catch( ex ) {
rwt.runtime.ErrorHandler.processJavaScriptError( ex );
}
},
_ontabfocus : function() {
this.selectAll();
},
_applyFocused : function( newValue, oldValue ) {
this.base( arguments, newValue, oldValue );
if( !rwt.widgets.util.FocusHandler.mouseFocus ) {
this._renderSelection();
}
},
_onblur : function() {
// RAP workaround for https://bugs.eclipse.org/bugs/show_bug.cgi?id=201080
if( this.getParent() != null ) {
this._setSelectionLength( 0 );
}
},
// [rst] Catch backspace in readonly text fields to prevent browser default
// action (which commonly triggers a history step back)
// See https://bugs.eclipse.org/bugs/show_bug.cgi?id=178320
_onkeydown : function( e ) {
if( e.getKeyIdentifier() == "Backspace" && this.getReadOnly() ) {
e.preventDefault();
}
this._detectSelectionChange();
this._typed = null;
},
// [if] Stops keypress propagation
// see https://bugs.eclipse.org/bugs/show_bug.cgi?id=335779
_onkeypress : function( e ) {
if( e.getKeyIdentifier() !== "Tab" ) {
e.stopPropagation();
}
if( this._selectionNeedsUpdate ) {
this._renderSelection();
}
this._detectSelectionChange();
this._typed = String.fromCharCode( e.getCharCode() );
},
_onkeyup : function( event ) {
if( this._selectionNeedsUpdate ) {
this._renderSelection();
}
this._detectSelectionChange();
this._typed = null;
},
_onMouseDownUp : function( event ) {
this._detectSelectionChange();
this._typed = null;
},
/////////////////
// browser quirks
_applyBrowserFixes : rwt.util.Variant.select( "qx.client", {
"default" : function() {},
"newmshtml" : function() {
// See Bug 372193 - Text widget: Modify Event not fired for Backspace key in IE
this._checkTimer = new rwt.client.Timer( 0 );
this._checkTimer.addEventListener( "interval", this._checkValueChanged, this );
// For delete, backspace, CTRL+X, etc:
this.addEventListener( "keypress", this._checkTimer.start, this._checkTimer );
this.addEventListener( "keyup", this._checkTimer.start, this._checkTimer );
// For context menu: (might not catch the change instantly
this.addEventListener( "mousemove", this._checkValueChanged, this );
this.addEventListener( "mouseout", this._checkValueChanged, this );
// Backup for all other cases (e.g. menubar):
this.addEventListener( "blur", this._checkValueChanged, this );
}
} ),
_checkValueChanged : function() {
this._checkTimer.stop();
var newValue = this.getComputedValue();
var oldValue = this.getValue();
if( newValue !== oldValue ) {
this._oninput();
}
},
_applyBrowserFixesOnAppear : rwt.util.Variant.select( "qx.client", {
"default" : function() {},
"mshtml" : function() {
if( this._firstInputFixApplied !== true && this._inputElement ) {
rwt.client.Timer.once( this._ieFirstInputFix, this, 1 );
}
}
} ),
_ieFirstInputFix : function() {
if( !this.isDisposed() ) {
this._inValueProperty = true;
this._inputElement.value = this.getValue() === null ? "" : this.getValue().toString();
this._renderSelection();
this._firstInputFixApplied = true;
delete this._inValueProperty;
}
},
_applyBrowserFixesOnCreate : rwt.util.Variant.select( "qx.client", {
"default" : function() {},
"webkit" : function() {
this.addEventListener( "keydown", this._preventEnter, this );
this.addEventListener( "keypress", this._preventEnter, this );
this.addEventListener( "keyup", this._preventEnter, this );
}
} ),
_preventEnter : function( event ) {
if( event.getKeyIdentifier() === "Enter" ) {
event.preventDefault();
}
},
/////////
// helper
isValidString : function( v ) {
return typeof v === "string" && v !== "";
}
}
} );