⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 selectbox.js

📁 Javascript code for developing the virtual keyboard
💻 JS
📖 第 1 页 / 共 3 页
字号:
/**
 *  $Id: selectbox.js 247 2007-04-03 16:59:49Z wingedfox $
 *  $HeadURL: https://svn.debugger.ru/repos/jslibs/BrowserExtensions/tags/BrowserExtensions.008/dom/selectbox.js $
 *
 *  Extends the selectbox interface
 *
 *  @author Ilya Lebedev <ilya@lebedev.net>
 *  @modified $Date: 2007-04-03 20:59:49 +0400 (Втр, 03 Апр 2007) $
 *  @version $Rev: 247 $
 *  @title Selectbox
 *  @license LGPL 2.1 or later
 */
// ===================================================================
//
// Author: Matt Kruse <matt@mattkruse.com>
// Author: Ilya Lebedev <ilya@lebedev.net>
// http://debugger.ru
//
// NOTICE: You may use this code for any purpose, commercial or
// private, without any further permission from the author. You may
// remove this notice from your final code if you wish, however it is
// appreciated by the author if at least my web site address is kept.
//
// You may *NOT* re-distribute this code in any way except through its
// use. That means, you can include it in your product, or your web
// site, or any other form where the code is actually being used. You
// may not put the plain javascript up on your site for download or
// include it in your javascript libraries for download. 
// If you wish to share this code with others, please just point them
// to the URL instead.
// Please DO NOT link directly to my .js files from your site. Copy
// the files to your server and use them there. Thank you.
// ===================================================================


// HISTORY
// ------------------------------------------------------------------
// October 2, 2006: Rewritten in the OOP style and added number of useful features
// June 12, 2003: Modified up and down functions to support more than
//                one selected option
/*
COMPATIBILITY: These are fairly basic functions - they should work on
all browsers that support Javascript.
*/

/**
 *  Provides control component for the select box
 *
 *  @class
 *  @param {String} id select box to attach control to
 *  @scope public
 */
Selectbox = function (id /*: String*/) {
  var self = this;
  /**
   *  Selectbox node
   *
   *  @type HTMLSelectElement
   *  @scope private
   */
  var node;
  /**
   *  List of all the options in the list
   *  Format of the array elements
   *  { 'value'    : option value,
   *    'text'     : option text,
   *    'defaultSelected' : default selection flag,
   *    'selected'  : selection flag,
   *    'visible'   : visible flag,
   *    'fixed'     : fixes position in the list
   *  }
   *
   *  @type Array
   *  @scope private
   */
  var options = [];
  /**
   * Trackers does keep a track of the options
   * 
   * @type Object
   * @scope private
   */
  var trackers = {
      'added' : [],
      'deleted' : []
  }
  /**
   *  Visible options list will not exceed this value
   *  
   *  @type Number
   *  @scope private
   */
  var maxlistlen = 1000;
  /**
   *  @constructor
   */
  var __construct = function (id) /* :void */{
    node = document.getElementById(id) || id;
    if (node && node.tagName.toLowerCase() != 'select') 
      throw new Error('Node with supplied id="'+id+'" is not the <select> box.')
    /*
    *  if node is not exists, create it.
    */
    if (!node) {
        node = document.createElement('select');
        node.id = 'selectbox'+(new Date).valueOf();
    } else if (node.options.length>0) {
        self.addOptionsList(node.options, false, false);
    }
    node.onblur = __storeOptionsState;
  }
  //---------------------------------------------------------------------------
  // Private methods
  //---------------------------------------------------------------------------
  /**
   * Special 'toString' method, allowing to have a free array sorting
   * 
   * @return {String}
   * @scope protected
   */
  var __toString = function() {
      return String(this.text);
  }
  /**
   *  Check all visible options and set the state for them
   *
   *  @param {RegExp, String, Array} reg expression to match option text against
   *  @param {String} type state to be changed, currently 'selected' and 'visible' supported
   *  @param {Boolean} state true means 'set selected'
   *  @param {Boolean} pre true means 'preserve already selected options state'
   *  @param {String} match match needle from: 'start', 'end', 'exact', 'any'. Default is 'start'. Has no meaning, when regexp is supplied.
   *  @param {String} attr attribute to do the check against, either 'text' or 'value'
   *  @return {Number} number of changed options
   */
  var __setOptionsState = function ( reg   /* :RegExp, String, Array */
                                    ,type  /* :String */
                                    ,state /* :Boolean */
                                    ,pre   /* :Boolean */
                                    ,match /* :String */
                                    ,attr  /* :String */ ) /* :Number */ {
    var res = 0;
    /*
    *  either 'text' or 'value' is allowed
    */
    if (attr != 'value') attr = 'text';
    /*
    *  don't touch options with empty match 
    */
    if (!isRegExp(reg)) {
        reg = RegExp.escape(reg);
        if (!isString(match)) match = 'start';
        switch (match.toLowerCase()) {
            case "any" :
                reg = new RegExp(reg,"i");   
                break;
            case "end" :
                reg = new RegExp(reg+"$","i");   
                break;
            case "exact" :
                reg = new RegExp("^"+reg+"$","i");   
                break;
            case "start" :
            case "default" :
                reg = new RegExp("^"+reg,"i");   
                break;
        }
    }
    for (var i=0, oL=options.length; i<oL; i++) {
      /*
      *  skip already options with matching state, if allowed
      */
      if (pre && options[i][type] == state) continue;
      /*
      *  flag that some options are processed successfully
      */
      if ( reg.test(options[i][attr]) ) {
        res += (options[i][type] != state);
        options[i][type] = state;
      } else {
        if ( options[i][type] == state && !pre) {
          res += (options[i][type] == state);
          options[i][type] = ! state;
        }
      }
    }
    /*
    *  if something has changed, do the update
    */
    if (res) self.updateOptions();
    return res;
  }
  /**
   *  Stores actual selection state, made by user
   *
   *  @scope protected
   */
  var __storeOptionsState = function () /* :void */{
      for (var i=0, oL=this.options.length; i<oL; i++) {
          if (!isUndefined(this.options[i].__idx) && options[this.options[i].__idx]) { 
              options[this.options[i].__idx].selected = this.options[i].selected;
              options[this.options[i].__idx].defaultSelected = this.options[i].defaultSelected;
          }
      }
  }
  /**
   *  Stores option name in the tracker
   * 
   *  @see #trackers
   *  @param {String} track name of the tracker
   *  @param {String} text option text
   *  @param {String} val option value
   *  @return {Boolean}
   *  @scope private
   */
  var __saveOptionsTrack = function (track /* :String */, text /* :String */, val /* :String */) /* :Boolean */{
      if (!trackers[track]) return false;
      if (trackers[track].fixed) {
          trackers[track] = [];
          trackers[track].fixed = false;
      }  
      trackers[track][trackers[track].length] = {'text' :text, 'value' :val};
      return true;  
  }
  /**
   *  Fixes current tracking state in the past
   *  
   *  @scope private
   */
  var __fixOptionsTrack = function () {
      trackers.added.fixed = true;
      trackers.deleted.fixed = true;
  }
  //---------------------------------------------------------------------------
  // Public methods
  //---------------------------------------------------------------------------
  /**
   *  Return the number of options in the list
   *
   *  @return {Number}
   *  @scope public
   */
  this.hasOptions = function () /* :Number */{
    return options.length;
  }
  /**
   *  Redraw options list
   *
   *  @scope public
   */
  this.updateOptions = function () /* :void */ {
      /*
      *  detach box to speedup conversion
      */
      var nxt = node.nextSibling
         ,prn = node.parentNode;
      if (prn) prn.removeChild(node);
      
      for (var i=ndx=0, oL=options.length; i<oL; i++) {
          /*
          *  don't process options beyond the borders
          */
          if (ndx>=maxlistlen) break;
          if (options[i].visible) {
              if (!node.options[ndx]) {
                  node.options[ndx] = new Option(options[i].text
                                                ,options[i].value
                                                ,options[i].defaultSelected
                                                ,options[i].selected);
              } else {
                  /*
                  *  firefox behavior - it does reset selectbox, 
                  *  when even single label has been touched
                  *  so, try to keep its scroll on the place
                  */
                  if (node.options[ndx].text != options[i].text)
                      node.options[ndx].text        = options[i].text;
    
                  node.options[ndx].value           = options[i].value;
                  node.options[ndx].defaultSelected = options[i].defaultSelected;
                  node.options[ndx].selected        = options[i].selected;
              }
              node.options[ndx].__idx           = i;
              ndx++;
          }
      }

      node.options.length=ndx;

      __fixOptionsTrack();
      /*
      *  set box back on its place
      */
      if (prn) {
          prn.insertBefore(node, nxt);
          prn = nxt = null;
      }
  }
  //-------------------------------------------
  //  SELECTION OPERATION
  //-------------------------------------------
  /**
   *  Selects all available options
   *
   *  It's useful, when do the transfer from one select box to another and before submitting a form
   *
   *  @scope public
   */
  this.selectAllOptions = function () /* :void */ {
    for (var i=0; i<options.length; i++) {
       if (options[i].visible) {
         options[i].selected = true;
       }
    }
    this.updateOptions();
  }
  /**
   *  Selects all matching options
   *
   *  @param {String} needle search phrase
   *  @param {String} match match needle from: 'start', 'end', 'exact', 'any'. Default is 'start'. Has no meaning, when regexp is supplied.
   *  @param {String} attr attribute to do the check against, either 'text' or 'value'
   *  @return {Number} number of selected options 
   *  @scope public
   */
  this.selectMatchingOptions = function (needle /* :String */, match /* :String */, attr /* :String */) /* :Number */ {
    return __setOptionsState (needle, 'selected', true, true, match, attr);
  }
  /**
   *  Selects all matching options and reset selection for others
   *
   *  @param {String} needle search phrase
   *  @param {String} match match needle from: 'start', 'end', 'exact', 'any'. Default is 'start'. Has no meaning, when regexp is supplied.
   *  @param {String} attr attribute to do the check against, either 'text' or 'value'
   *  @return {Number} number of selected options 
   *  @scope public
   */
  this.selectOnlyMatchingOptions = function (needle /* :String */, match /* :String */, attr /* :String */) /* :Number */ {
    return __setOptionsState (needle, 'selected', true, false, match, attr);
  }
  /**

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -