WaBis

walter.bislins.ch

Datei: xTextControl: xtc.js

Inhalt der Datei: javascript/xtc/src/xtc.js
//------------------------------------------------------------
// 13.04.2008 (C) Walter Bislin; http://walter.bislins.ch/doku/xtc
// 02.10.2009 added SetScrollTop, GetScrollTop
// 07.05.2014 fixed: GetCursorScrollTop() works now in all browsers correct
// 07.05.2014 added: GetLineHeight()
//
// xTextControl class that encapsulates text controls for browser independence:
// To ensure browser independence do not use properties of text controls directly!
// NL sould be a single '\n' character, not '\r\n', so positions of carets
// correspond to character positions in strings on all browsers.
//
// usage:
//
// var textControl = new xTextControl(document.myForm.myTextInput);
// alert( textControl.Text );
// alert( textControl.SelText ); etc.
//
// Note: all members are ment to be read only!
// Use functions to change the control!
// You must not directly change the control properties!
//
// Note:
// range.moveToElementText(ele) on IE throws an exception if ele is a text input field!?
// That means, that xTextControl only works with textarea on all modern browsers :-(

function xNormString( aStr ) {
  return aStr.replace(/\r\n/g,'\n');
}

function xTextControl( aTextControl ) {
  // aTextControl must be a textarea element
  this.TextControl = aTextControl;
  this.SelStart = 0;
  this.SelEnd = 0;
  this.SelText = '';
  this.Text = '';
  this.Enabled = this.GetDataFromControl();
  this.LineHeight = 0;
  var ft = '';
  for (var i = 0; i < 32; i++) { ft += 'x\nx\nx\nx\nx\nx\nx\nx\n'; }
  this.FillText = ft;
}

xTextControl.prototype.GetDataFromControl = function() {
  if (typeof(this.TextControl) == 'undefined') {return false;}
  this.Text = xNormString(this.TextControl.value);
  if (document.selection) { // IE
    this.TextControl.focus();
    // find start of originalRange with a binary search
    var originalRange = document.selection.createRange();
    var testRange = originalRange.duplicate();
    testRange.moveToElementText( this.TextControl );
    var len = this.Text.length;
    var pos = 0;
    var step = Math.floor( len / 2 ) + 1;
    while (step > 0) {
      while ((pos+step <= len) && testRange.inRange(originalRange)) {
        testRange.moveStart( 'character', step );
        pos += step;
      }
      if (!testRange.inRange(originalRange)) {
        testRange.moveStart( 'character', -step );
        pos -= step;
      }
      step = Math.floor( step / 2 );
    }
    this.SelStart = pos;
    // find end of originalRange with a binary search
    testRange.moveToElementText( this.TextControl );
    var pos = len;
    var step = Math.floor( len / 2 ) + 1;
    while (step > 0) {
      while ((pos-step >= 0) && testRange.inRange(originalRange)) {
        testRange.moveEnd( 'character', -step );
        pos -= step;
      }
      if (!testRange.inRange(originalRange)) {
        testRange.moveEnd( 'character', step );
        pos += step;
      }
      step = Math.floor( step / 2 );
    }
    this.SelEnd = pos;
    this.SelText = this.Text.substring( this.SelStart, this.SelEnd );
    return true;
  }
  else if (this.TextControl.setSelectionRange) { // Mozilla
    this.SelStart = this.TextControl.selectionStart;
    this.SelEnd = this.TextControl.selectionEnd;
    this.SelText = this.Text.substring( this.SelStart, this.SelEnd );
    return true;
  }
  return false;
};

xTextControl.prototype.GetScrollTop = function() {
  if (typeof(this.TextControl.scrollTop) == 'number') {
    return this.TextControl.scrollTop;
  }
  return 0;
}

xTextControl.prototype.SetScrollTop = function( aTop ) {
  if (typeof(this.TextControl.scrollTop) == 'number') {
    this.TextControl.scrollTop = aTop;
  }
}

xTextControl.prototype.GetLineHeight = function() {
  if (this.LineHeight == 0) {
    var dummy = this.GetCursorScrollTop();
  }
  return this.LineHeight;
}

xTextControl.prototype.GetCursorScrollTop = function() {
  // Implementation: Cut the text after cursor pos and read scrollHight.
  // This is the scrollTop of the cursor position. After that restore the TextControl0
  if (typeof(this.TextControl.scrollHeight) != 'number') { return 0; }
  // save current text and selection
  var startPos = this.SelStart;
  var endPos = this.SelEnd;
  var fullText = this.Text;
  // Implementation: Some browsers return window height instead of document height in scrollHeight.
  // To get the effective scroll height, I fill the docu with FillText, get the scrollHeight as an offset,
  // add the topText, get and the scroll height again. The difference of the scroll heights is the real scroll height.
  this.SetText( this.FillText );
  var topOffset = this.TextControl.scrollHeight;
  // cut text after cursor position
  var topText = this.FillText + fullText.substring( 0, startPos );
  this.SetText( topText );
  // read scrollHeight = scrollTop of cursor
  var top = this.TextControl.scrollHeight - topOffset;
  // get height of a single line
  this.SetText( topText + '\nx' );
  var lineHeight = this.TextControl.scrollHeight - top - topOffset;
  this.LineHeight = lineHeight;
  // restore TextControl
  this.SetText( fullText );
  this.SetSelectionRange( startPos, endPos, true );
  return top;
}

xTextControl.prototype.SetText = function( aText ) {
  // Requires normalized aText
  // Note: this invalidates the selection members.
  // Use GetDataFromControl to get updated or
  // use SetSelectionRange to set a new selection
  if (this.TextControl.setSelectionRange) { // Mozilla
    var scrollTop = this.TextControl.scrollTop;
    this.TextControl.value = aText;
    this.TextControl.scrollTop = scrollTop;
  } else {
    this.TextControl.value = aText;
  }
  this.Text = aText;
};

xTextControl.prototype.ChangeSelection = function( aSelStart, aSelEnd, aReplaceText, aUpdateControlSelection ) {
  // Note: the controls selection is only updated if
  // aUpdateControlSelection is true. You may update the controls selection via UpdateControlSelection() manually.
  var preText = this.Text.substring( 0, aSelStart );
  var pstText = this.Text.substring( aSelEnd );
  var newText = preText + aReplaceText + pstText;
  this.SetText( newText );
  this.SelStart = aSelStart;
  this.SelEnd = aSelStart + aReplaceText.length;
  this.SelText = aReplaceText;
  if (aUpdateControlSelection) {this.UpdateControlSelection();}
};

xTextControl.prototype.SetSelectionRange = function( aSelStart, aSelEnd, aUpdateControlSelection ) {
  // Note: the controls selection is only updated if
  // aUpdateControlSelection is true. You may update the controls selection via UpdateControlSelection() manually.
  this.SelStart = aSelStart;
  this.SelEnd = aSelEnd;
  this.SelText = this.Text.substring( aSelStart, aSelEnd );
  if (aUpdateControlSelection) {this.UpdateControlSelection();}
};

xTextControl.prototype.ChangeSelectionText = function( aReplaceText, aUpdateControlSelection ) {
  // Note: the controls selection is only updated if
  // aUpdateControlSelection is true. You may update the controls selection via UpdateControlSelection() manually.
  this.ChangeSelection( this.SelStart, this.SelEnd, aReplaceText, aUpdateControlSelection );
};

xTextControl.prototype.SetCaretPos = function( aPos ) {
  this.SetSelectionRange( aPos, aPos, true );
};

xTextControl.prototype.UpdateControlSelection = function() {
  // updates the text control selection to the current values.
  this.TextControl.focus();
  if (this.TextControl.setSelectionRange) { // MOZILLA
    this.TextControl.setSelectionRange( this.SelStart, this.SelEnd );
  }
  else if (this.TextControl.createTextRange) { // IE
    var range = this.TextControl.createTextRange();
    range.collapse( true );
    range.moveEnd( 'character', this.SelEnd );
    range.moveStart( 'character', this.SelStart );
    range.select();
  }
};

More Page Infos / Sitemap
Created Dienstag, 17. Juni 2014
Scroll to Top of Page
Changed Montag, 2. Februar 2015