text: /**
   * @file jQuery Plugin: SelectPage
   * @version 0.1
   * @author TerryZeng
   * @license MIT License
   * 
   * 插件的部分功能使用、借鉴了
   * jQuery Plugin: jquery.ajax-combobox
   * 作者：Yuusaku Miyazaki <toumin.m7@gmail.com>(宮崎 雄策)
   * 
   */
  ;
  (function (factory) {
      if (typeof define === "function" && define.amd) {
          // AMD模式
          define(["jquery"], factory);
      } else {
          // 全局模式
          factory(jQuery);
      }
  }(function ($) {
      "use strict";
      /**
       * 内部使用常量
       */
      var constants = {
          dataKey: 'selectPageObject', //插件缓存内部对象的KEY
          objStatusKey: 'selectPage-self-mark', //全局范围设置当前点击是否为插件自身的标识
          objStatusIndex: 'selectPage-self-index'          //全局范围设置当前点击的selectpage的索引下标
      };
      /**
       * @desc 下拉分页查询控件初始化入口
       * @global
       * @memberof jQuery
       * @param {string|Object} source - 数据源（String：Ajax查询的URL|Object：JSON格式的数据源）
       * @param {Object} option - 初始化参数集
       * 
       * 
       * option参数集内容
       * @param {boolean} [option.instance] - 是否返回插件内部对象（true：返回内部对象，false：返回输入框自身）
       * @param {string} [option.lang='cn'] - 插件显示语言 ('en','cn'等)
       * @param {boolean} [option.multiple] - 是否为多选模式（多选模式下，选中的项目将会以Tag标签的形式展现）
       * @param {string} [option.field='name'] - 结果集中用于显示的属性名
       * @param {string} [option.search_field=option.field] - 使用ajax作为数据源情况下的查询字段指定。 (e.g.: 'id, name, job')
       * @param {string|Array} [option.order_by=option.search_field] - 排序字段指定，若不指定则自动使用查询字段 (e.g.: 'name DESC' or ['name ASC', 'age DESC'])
       * @param {number} [option.per_page=10] - 每页显示的记录数
       * @param {string} [option.init_record=false] - 插件初始值指定，该值会与option.primary_key字段进行匹配，若匹配到，则自动设置选中并高亮
       * @param {string} [option.bind_to] - 指定事件名称，用于在选择项目后进行触发（必须已自行绑定好事件）
       * @param {string} [option.and_or='AND'] - 查询方式 ('AND' or 'OR')
       * @param {boolean} [option.select_only=false] - 仅选择，不能输入查询关键字
       * @param {string} [option.primary_key='id'] - 值字段，通常该字段的内容会自动保存在隐藏域中
       */
      $.fn.selectPage = function (option) {
          var arr = [];
          this.each(function () {
              arr.push(new SelectPage(this, option));
          });
          return (option !== undefined && option.instance !== undefined && option.instance) ? $(arr) : this;
      };
  
      /**
       * @global
       * @constructor
       * @classdesc 插件初始化
       * @param {Object} combo_input - 插件的初始化输入框元素。
       * @param {string|Object} source - 数据来源
       *         string：服务端请求的URL地址
       *         Object：JSON格式数组，推荐格式：[{a:1,b:2,c:3},{...}]
       * @param {Object} option - 初始化参数
       */
      function SelectPage(combo_input, option) {
          var option = $.extend({}, option, $(combo_input).data());
          option = this._setCamelcaseToUnderscore(option);
          this._setOption(option);
          this._setLanguage();
          this._setCssClass();
          this._setProp();
          this._setElem(combo_input, option);
  
          this._setButtonAttrDefault();
          this._setInitRecord();
  
          this._ehButton();
          this._ehComboInput();
          this._ehWhole();
  
          //缓存内部对象
          $(this.elem.container).data(constants.dataKey, this);
      }
  
      /**
       * 内部函数定义
       */
      $.extend(SelectPage.prototype, {
          /**
           * @private
           * @desc 参数初始化
           * @param {string|Object} source - 数据源
           * @param {Object} option - 参数集
           */
          _setOption: function (option) {
              option = this._setOption1st(option);
              option = this._setOption2nd(option);
              this.option = option;
          },
  
          /**
           * @private
           * @desc 参数使用默认值进行初始化与合并
           * @param {Object} option - 初始化参数
           * @return {Object} - 合并后的参数
           */
          _setOption1st: function (option) {
              option = $.extend({
                  lang: 'cn',
                  multiple: false,
                  init_record: false,
                  field: 'name',
                  and_or: 'AND',
                  per_page: 10,
                  primary_key: 'id',
                  bind_to: false,
                  /**
                   * 是否在输入框获得焦点时，展开下拉窗口
                   * 默认:true
                   */
                  focus_drop_list: true,
                  /**
                   * 是否自动选择列表中的第一项内容(输入关键字查询模式，直接使用鼠标下拉并不触发)
                   * 默认：false
                   */
                  auto_select_first: false,
                  /**
                   * 是否自动填充内容
                   * 若有列表项目被高亮显示，在焦点离开控件后，自动设置该项为选中内容
                   * 默认：false
                   */
                  auto_fill_result: false,
                  /**
                   * 是否清空输入关键字
                   * 在输入框中输入内容进行查询，但没有匹配的内容返回，在焦点离开控件后，自动清空输入框输入的内容
                   * 默认：false
                   */
                  no_result_clean: false,
                  /**
                   * 列表项目显示内容格式化
                   * 参数类型：function
                   * 参数1：data，行数据object格式
                   * 返回：string
                   */
                  format_item: false,
                  /**
                   * 是否使用Formatter的text文本来填充文本框
                   */
                  format_fill: false,
                  /**
                   * 只选择模式
                   */
                  select_only: true,
              }, option);
              //特殊字段处理
              $.each({data: 'source', key_field: 'primary_key', show_field: 'field', init_code: 'init_record', page_size: 'per_page'}, function (i, j) {
                  if (typeof option[i] !== 'undefined') {
                      option[j] = option[i];
                      delete option[i];
                  }
              });
              return option;
          },
  
          /**
           * @private
           * @desc 参数初始化后的调整
           * @param {Object} option - 参数集
           * @return {Object} - 处理后的参数集
           */
          _setOption2nd: function (option) {
              //若没有设置搜索字段，则使用显示字段作为搜索字段
              option.search_field = (option.search_field === undefined) ? option.field : option.search_field;
  
              //统一大写
              option.and_or = option.and_or.toUpperCase();
  
              var arr = ['hide_field', 'show_field', 'search_field'];
              for (var i = 0; i < arr.length; i++) {
                  option[arr[i]] = this._strToArray(option[arr[i]]);
              }
  
              //设置排序字段
              option.order_by = (option.order_by === undefined) ? option.search_field : option.order_by;
  
              //设置多字段排序
              //例:  [ ['id', 'ASC'], ['name', 'DESC'] ]
              option.order_by = this._setOrderbyOption(option.order_by, option.field);
  
              return option;
          },
  
          /**
           * 设置峰驼至下划线
           * @param {object} option
           * @returns {object}
           */
          _setCamelcaseToUnderscore: function (option) {
              $.each(option, function (i, j) {
                  var field = i.replace(/([a-z])([A-Z])/g, '$1_$2').toLowerCase();
                  if (field !== i) {
                      option[field] = j;
                      delete option[i];
                  }
              });
              return option;
          },
  
          /**
           * @private
           * @desc 字符串转换为数组
           * @param {string} str - 字符串
           * @return {Array} - 数组
           */
          _strToArray: function (str) {
              if (!str)
                  return '';
              return str.replace(/[\s　]+/g, '').split(',');
          },
  
          /**
           * @private
           * @desc 设置多字段排序
           * @param {Array} arg_order - 排序顺序
           * @param {string} arg_field - 字段
           * @return {Array} - 处理后的排序字段内容
           */
          _setOrderbyOption: function (arg_order, arg_field) {
              var arr = [], orders = [];
              if (typeof arg_order == 'object') {
                  for (var i = 0; i < arg_order.length; i++) {
                      orders = $.trim(arg_order[i]).split(' ');
                      arr[i] = (orders.length == 2) ? orders : [orders[0], 'ASC'];
                  }
              } else {
                  orders = $.trim(arg_order).split(' ');
                  arr[0] = (orders.length == 2) ? orders : (orders[0].match(/^(ASC|DESC)$/i)) ? [arg_field, orders[0]] : [orders[0], 'ASC'];
              }
              return arr;
          },
  
          /**
           * @private
           * @desc 界面文字国际化
           */
          _setLanguage: function () {
              var message;
              switch (this.option.lang) {
                      // English
                  case 'en':
                      message = {
                          add_btn: 'Add button',
                          add_title: 'add a box',
                          del_btn: 'Del button',
                          del_title: 'delete a box',
                          next: 'Next',
                          next_title: 'Next' + this.option.per_page + ' (Right key)',
                          prev: 'Prev',
                          prev_title: 'Prev' + this.option.per_page + ' (Left key)',
                          first_title: 'First (Shift + Left key)',
                          last_title: 'Last (Shift + Right key)',
                          get_all_btn: 'Get All (Down key)',
                          get_all_alt: '(button)',
                          close_btn: 'Close (Tab key)',
                          close_alt: '(button)',
                          loading: 'loading...',
                          loading_alt: '(loading)',
                          page_info: 'num_page_top - num_page_end of cnt_whole',
                          select_ng: 'Attention : Please choose from among the list.',
                          select_ok: 'OK : Correctly selected.',
                          not_found: 'not found',
                          ajax_error: 'An error occurred while connecting to server. (ajax-combobox)'
                      };
                      break;
  
                      // 中文
                  case 'cn':
                      message = {
                          add_btn: '添加按钮',
                          add_title: '添加区域',
                          del_btn: '删除按钮',
                          del_title: '删除区域',
                          next: '下一页',
                          next_title: '下' + this.option.per_page + ' (→)',
                          prev: '上一页',
                          prev_title: '上' + this.option.per_page + ' (←)',
                          first_title: '首页 (Shift + ←)',
                          last_title: '尾页 (Shift + →)',
                          get_all_btn: '获得全部 (↓)',
                          get_all_alt: '(按钮)',
                          close_btn: '关闭 (Tab键)',
                          close_alt: '(按钮)',
                          loading: '读取中...',
                          loading_alt: '(读取中)',
                          page_info: 'num_page_top - num_page_end (共 cnt_whole)',
                          select_ng: '请注意：请从列表中选择.',
                          select_ok: 'OK : 已经选择.',
                          not_found: '无查询结果',
                          ajax_error: '连接到服务器时发生错误！'
                      };
                      break;
              }
              this.message = message;
          },
  
          /**
           * @private
           * @desc CSS样式表名称字义
           */
          _setCssClass: function () {
              var css_class = {
                  container: 'sp_container',
                  // SelectPage最外层DIV的打开状态
                  container_open: 'sp_container_open',
                  selected: 'sp_selected',
                  re_area: 'sp_result_area',
                  //标签及输入框的
                  element_box: 'sp_element_box',
                  // 分页导航
                  navi: 'pagination',
                  // 下拉结果列表
                  results: 'sp_results',
                  re_off: 'sp_results_off',
                  select: 'sp_over',
                  select_ok: 'sp_select_ok',
                  select_ng: 'sp_select_ng',
                  input_off: 'sp_input_off',
  
                  button: 'sp_button',
                  btn_on: 'sp_btn_on',
                  btn_out: 'sp_btn_out',
                  input: 'sp_input'
              };
              this.css_class = css_class;
          },
  
          /**
           * @private
           * @desc 设置属性默认值
           */
          _setProp: function () {
              this.prop = {
                  is_suggest: false,
                  //当前页
                  page_all: 1,
                  page_suggest: 1,
                  //总页数
                  max_all: 1,
                  max_suggest: 1,
                  //正在分页状态
                  is_paging: false,
                  //是否正在Ajax请求
                  is_loading: false,
                  xhr: false,
                  //使用键盘进行分页
                  key_paging: false,
                  //使用键盘进行选择
                  key_select: false,
                  //上一个选择的项目值
                  prev_value: ''
              };
              this.template = {
                  tag: {
                      content: '<li class="selected_tag" itemvalue="#item_value#">#item_text#<span class="tag_close">&times;</span></li>',
                      textKey: '#item_text#',
                      valueKey: '#item_value#'
                  }
              };
          },
  
          /**
           * @private
           * @desc 插件HTML结构生成
           * @param {Object} combo_input - 输入框源对象
           */
          _setElem: function (combo_input, option) {
              //如果当前元素有默认值,且init_record为false时自动从元素取
              var value = $(combo_input).val();
              if (value && !option.init_record) {
                  this.option.init_record = $.isArray(value) ? value.join(',') : value;
              }
              // 1. 生成、替换DOM对象
              var elem = {};//本体
              //将原始输入框中，用户设置的样式提取，并放到最外层的容器中,'class':''
              var outerWidth = $(combo_input).outerWidth();
              elem.combo_input = $(combo_input).attr({'autocomplete': 'off'}).addClass(this.css_class.input).wrap('<div>'); // This "div" is "container".
              elem.container = $(elem.combo_input).parent().addClass(this.css_class.container);
  
              elem.button = $('<div>').addClass(this.css_class.button);
              //更换为bootstrap风格的向下三角箭头
              elem.img = $('<span class="bs-caret"><span class="caret"></span></span>');
  
              //多选模式下带标签显示及文本输入的组合框
              elem.element_box = $('<ul>').addClass(this.css_class.element_box);
  
              //结果集列表
              elem.result_area = $('<div>').addClass(this.css_class.re_area);
              //分页栏
              elem.navi = $('<ul>').addClass(this.css_class.navi).addClass("hide");
              //elem.navi_info   = $('<div>').addClass('info');
              //elem.navi_p      = $('<p>');
              elem.results = $('<ul>').addClass(this.css_class.results);
  
              /**
               * 将原输入框的Name交换到Hidden中，因为具体需要保存传递到后端的是ID，而非Title
               */
              var namePrefix = '_text';
              //将primary_key的值放入"input:hidden"
              var input_id = ($(elem.combo_input).attr('id') !== undefined) ? $(elem.combo_input).attr('id') : $(elem.combo_input).attr('name');
              var input_name = ($(elem.combo_input).attr('name') !== undefined) ? $(elem.combo_input).attr('name') : 'selectPage';
              var hidden_name = input_name,
                      hidden_id = input_id;
  
              if (input_name.match(/\]$/))
                  input_name = input_name.replace(/\]?$/, namePrefix);
              else
                  input_name += namePrefix;
              if (input_id.match(/\]$/))
                  input_id = input_id.replace(/\]?$/, namePrefix);
              else
                  input_id += namePrefix;
  
              if ($(elem.combo_input).is("select")) {
                  //将输入框的Name与Hidden的Name进行交换，使得可以将项目的具体ID被保存到后端进行处理
                  elem.hidden = $('<select class="hide" />').attr({
                      name: hidden_name,
                      id: hidden_id
                  }).prop("multiple", $(elem.combo_input).prop("multiple")).empty();
                  var newinput = $('<input type="text" class="form-control" />').attr({
                      name: input_name,
                      id: input_id
                  }).addClass(this.css_class.input);
                  if (!option.source) {
                      var source = [];
                      $("option", elem.combo_input).each(function (i, j) {
                          source.push({id: i, name: $(this).text()});
                      });
                      this.option.source = source;
                  }
                  $(elem.combo_input).replaceWith(newinput);
                  elem.combo_input = newinput;
              } else {
                  //将输入框的Name与Hidden的Name进行交换，使得可以将项目的具体ID被保存到后端进行处理
                  elem.hidden = $('<input type="hidden" class="hide" />').attr({
                      name: hidden_name,
                      id: hidden_id
                  }).val('');
                  $(elem.combo_input).attr({
                      name: input_name,
                      id: input_id
                  });
              }
              $(elem.hidden).addClass("selectpage-input-hidden");
              // 2. DOM内容放置
              $(elem.container).append(elem.button).append(elem.result_area).append(elem.hidden);
              $(elem.button).append(elem.img);
              $(elem.result_area).append(elem.results).append(elem.navi);
  
              //多选模式下的特殊处理
              if (option.multiple) {
                  $(elem.container).addClass('sp_container_combo');
                  $(elem.combo_input).addClass('sp_combo_input').before($(elem.element_box));
                  var li = $('<li>').addClass('input_box');
                  $(li).append($(elem.combo_input));
                  $(elem.element_box).append($(li));
                  if ($(elem.combo_input).attr('placeholder'))
                      $(elem.combo_input).attr('placeholder_bak', $(elem.combo_input).attr('placeholder'));
              }
              if ($(elem.container).parent().hasClass("input-group")) {
                  $(elem.container).height($(elem.container).parent().height());
              }
  
              this.elem = elem;
          },
  
          /**
           * @private
           * @desc 将控件的部分内容设置为默认状态
           */
          _setButtonAttrDefault: function () {
              if (this.option.select_only) {
                  if ($(this.elem.combo_input).val() !== '') {
                      if ($(this.elem.hidden).val()) {
                          //选择条件
                          $(this.elem.combo_input).prop('title', this.message.select_ok).removeClass(this.css_class.select_ng).addClass(this.css_class.select_ok);
                      } else {
                          //输入方式
                          $(this.elem.combo_input).prop('title', this.message.select_ng).removeClass(this.css_class.select_ok).addClass(this.css_class.select_ng);
                      }
                  } else {
                      $(this.elem.combo_input).prop('title', '').removeClass(this.css_class.select_ng);
                  }
              }
              $(this.elem.button).prop('title', this.message.get_all_btn);
          },
  
          /**
           * @private
           * @desc 为插件设置初始化的选中值（若有指定的话）
           */
          _setInitRecord: function () {
              var self = this;
              //初始化外框宽度
              //$(self.elem.container).width($(self.elem.combo_input).outerWidth());
              if (this.option.init_record === false)
                  return;
              // 初始的KEY值放入隐藏域
              self._setHiddenValue(self.option.init_record);
  
              //将初始值放入控件
              if (typeof self.option.source == 'object') {
                  var data = new Array();
                  var keyarr = self.option.init_record.split(',');
                  $.each(keyarr, function (index, row) {
                      for (var i = 0; i < self.option.source.length; i++) {
                          if (self.option.source[i][self.option.primary_key] == row) {
                              data.push(self.option.source[i]);
                              break;
                          }
                      }
                  });
                  //在单选模式下，若使用了多选模式的初始化值（“key1,key2,...”多选方式），则不进行初始化选中操作
                  if (!self.option.multiple && data.length > 1)
                      data = null;
                  self._afterInit(self, data);
              } else {
                  var _paramsFunc = self.option.params;
                  var _params = {};
                  //原始参数
                  var _orgParams = {
                      field: self.option.field,
                      order_by: self.option.order_by,
                      pkey_name: self.option.primary_key,
                      pkey_value: self.option.init_record
                  };
                  if (_paramsFunc) {
                      var result = $.isFunction(_paramsFunc) ? _paramsFunc() : _paramsFunc;
                      if (result && $.isPlainObject(result)) {
                          _params = $.extend({}, _orgParams, result);
                      } else {
                          _params = _orgParams;
                      }
                  } else {
                      _params = _orgParams;
                  }
                  $.ajax({
                      dataType: 'json',
                      url: self.option.source,
                      data: _params,
                      success: function (returnData) {
                          if (typeof returnData.rows === 'undefined' || !$.isArray(returnData.rows)) {
                              self.prop.xhr = null;
                              self._notFoundSearch(self);
                              return;
                          } else {
                              returnData.list = returnData.rows;
                          }
                          self._afterInit(self, returnData.list);
                      },
                      error: function (jqXHR, textStatus, errorThrown) {
                          self._ajaxErrorNotify(self, errorThrown);
                      }
                  });
              }
          },
  
          /**
           * @private
           * @desc 初始化后的处理
           * @param {Object} self - 插件的内部对象
           * @param {Object} data - 列表数据
           */
          _afterInit: function (self, data) {
              if (!data)
                  return;
              if (!$.isArray(data))
                  data = [data];
  
              if (self.option.multiple) {//多选模式初始化
                  $(self.elem.combo_input).val('');
                  $.each(data, function (i, row) {
                      var item = {text: row[self.option.field], value: row[self.option.primary_key]};
                      if (!self._isAlreadySelected(self, item))
                          self._addNewTag(self, item);
                  });
                  self._tagValuesSet(self);
                  self._inputResize(self);
              } else {//单选模式初始化
                  var row = data[0];
                  $(self.elem.combo_input).val(row[self.option.field]);
                  self._setHiddenValue(row[self.option.primary_key]);
                  self.prop.prev_value = row[self.option.field];
                  if (self.option.select_only) {
                      $(self.elem.combo_input).attr('title', self.message.select_ok).removeClass(self.css_class.select_ng).addClass(self.css_class.select_ok);
                  }
              }
          },
  
          /**
           * @private
           * @desc 下拉按钮的事件处理
           */
          _ehButton: function () {
              var self = this;
  
              $(self.elem.button).mouseup(function (ev) {
                  if ($(self.elem.result_area).is(':hidden') && !$(self.elem.combo_input).prop('disabled')) {
                      //self.prop.is_suggest = false;
                      //self._checkValue(self);
                      //self._suggest(self);
                      $(self.elem.combo_input).focus();
                  } else {
                      self._hideResults(self);
                  }
                  ev.stopPropagation();
              }).mouseover(function () {
                  $(self.elem.button).addClass(self.css_class.btn_on).removeClass(self.css_class.btn_out);
              }).mouseout(function () {
                  $(self.elem.button).addClass(self.css_class.btn_out).removeClass(self.css_class.btn_on);
              }).mouseout(); // default: mouseout
          },
  
          /**
           * @private
           * @desc 输入框的事件绑定
           */
          _ehComboInput: function () {
              var self = this;
              $(self.elem.combo_input).keyup(function (ev) {
                  self._processKey(self, ev);
              }).keydown(function (e) {
                  if (e.keyCode === 8 && self.option.multiple && $(self.elem.combo_input).val() == '') {
                      $(self.elem.combo_input).parent().prev().find(".tag_close").trigger("click");
                  }
              }).focus(function (e) {
                  //增加输入框获得焦点后，显示数据列表
                  if ($(self.elem.result_area).is(':hidden')) {
                      e.stopPropagation();
                      self.elem.navi.addClass("hide");
                      self.prop.first_show = true;
                      self.prop.page_move = false;
                      //self._checkValue(self);
                      self.prop.is_suggest = false;
                      self._suggest(self);
                      //self.prop.first_show = false;
                  }
              }).click(function () {
                  self._setCssFocusedInput(self);
                  //该句会去除当前高亮项目的显示，暂时屏蔽
                  //$(self.elem.results).children('li').removeClass(self.css_class.select);
              }).blur(function () {
                  $(self.elem.hidden).trigger("blur");
              });
              if (self.option.multiple) {
                  $(self.elem.element_box).click(function (e) {
                      var srcEl = e.target || e.srcElement;
                      if ($(srcEl).is('ul'))
                          $(self.elem.combo_input).focus();
                  });
                  //标签关闭操作
                  //关闭同时需要将该标签的key从已保存的隐藏域中删除
                  $(self.elem.element_box).on('click', 'span.tag_close', function () {
                      var li = $(this).closest('li');
                      var key = $(li).attr('itemvalue');
                      var keys = $(self.elem.hidden).val();
                      //从已保存的key列表中删除该标签对应的项目
                      if ($.type(key) != 'undefined' && keys) {
                          var keyarr = $.isArray(keys) ? keys : (keys ? keys.split(',') : new Array());
                          var index = $.inArray(key.toString(), keyarr);
                          if (index != -1) {
                              keyarr.splice(index, 1);
                              self._setHiddenValue(keyarr.toString());
                          }
                      }
                      $(li).remove();
                      self._inputResize(self);
                      $("li[pkey='" + key + "']", self.elem.results).removeClass(self.css_class.selected);
                  });
                  self._inputResize(self);
              }
          },
  
          /**
           * 设置隐藏元素的值
           * @param {type} value
           * @returns {undefined}
           */
          _setHiddenValue: function (value) {
              var self = this;
              if ($(self.elem.hidden).is("select")) {
                  $(self.elem.hidden).empty();
                  value = $.isArray(value) ? value : ($(self.elem.hidden).prop("multiple") ? (value + "").split(",") : value);
                  $.each(value, function (i, j) {
                      $(self.elem.hidden).append($("<option />").prop("selected", true).val(j).text(j));
                  });
              } else {
                  value = $.isArray(value) ? value.join(",") : value;
                  $(self.elem.hidden).val(value);
              }
          },
  
          /**
           * @private
           * @desc 插件整体的事件处理
           */
          _ehWhole: function () {
              var self = this;
              //如果是点击了控件本身则不响应外部鼠标点击事件
              $(self.elem.container).mousedown(function () {
                  var thisindex = $('div.sp_container').index(this);
                  var lastindex = $(document.body).data(constants.objStatusIndex);
                  if (lastindex != undefined && thisindex != lastindex) {
                      $(document.body).data(constants.objStatusKey, false);
                  } else {
                      $(document.body).data(constants.objStatusKey, true);
                  }
                  $(document.body).data(constants.objStatusIndex, thisindex);
              });
              //控件外部的鼠标点击事件处理
              $(document).off('mousedown.selectPage').on('mousedown.selectPage', function (e) {
                  if ($(document.body).data(constants.objStatusKey))
                      $(document.body).data(constants.objStatusKey, false);
                  else {
                      //清除内容
                      var cleanContent = function (obj) {
                          $(obj.elem.combo_input).val('');
                          if (!obj.option.multiple)
                              $(obj.elem.hidden).val('');
                      };
                      $('div.sp_container').each(function () {
                          var d = $(this).data(constants.dataKey);
                          //列表是打开的状态
                          if ($(this).hasClass(d.css_class.container_open)) {
                              //若控件已有选中的的项目，而文本输入框中清空了关键字，则清空控件已选中的项目
                              if (!$(d.elem.combo_input).val() && $(d.elem.hidden).val() && !d.option.multiple) {
                                  d.prop.page_all = 1;//重置当前页为1
                                  cleanContent(d);
                                  d._hideResults(d);
                                  return true;
                              }
                              //匹配项且高亮时，下拉分页控件失去焦点后，自动选择该项目
                              if ($('li', $(d.elem.results)).size() > 0) {
                                  if (d.option.auto_fill_result) {//打开自动内容填充功能
                                      //若已有选中项目，则直接隐藏列表
                                      if ($('li.sp_selected', $(d.elem.results)).size() > 0) {
                                          d._hideResults(d);
                                      } else if ($('li.sp_over', $(d.elem.results)).size() > 0) {
                                          //若控件已有选中的值，则忽略高亮的项目
                                          if ($(d.elem.hidden).val())
                                              d._hideResults(d);
                                          //若没有已选中的项目，且列表中有高亮项目时，选中当前高亮的行
                                          else
                                              d._selectCurrentLine(d, true);
                                      } else if (d.option.auto_select_first) {
                                          //若控件已有选中的值，则忽略自动选择第一项的功能
                                          if ($(d.elem.hidden).val())
                                              d._hideResults(d);
                                          else {
                                              //对于没有选中，没有高亮的情况，若插件设置了自动选中第一项时，则选中第一项
                                              d._nextLine(d);
                                              //self._nextLine(self);
                                              d._selectCurrentLine(d, true);
                                          }
                                      } else {
                                          d._hideResults(d);
                                      }
                                  } else
                                      d._hideResults(d);
                              } else {
                                  //无匹配项目时，自动清空用户输入的关键词
                                  if (d.option.no_result_clean)
                                      cleanContent(d);
                                  else {
                                      if (!d.option.multiple)
                                          $(d.elem.hidden).val('');
                                  }
  
                                  d._hideResults(d);
                              }
                          }
                      });
                  }
              });
          },
  
          /**
           * @private
           * @desc 结果列表的事件处理
           */
          _ehResults: function () {
              var self = this;
              $(self.elem.results).children('li').mouseover(function () {
                  if (self.prop.key_select) {
                      self.prop.key_select = false;
                      return;
                  }
  
                  $(self.elem.results).children('li').removeClass(self.css_class.select);
                  $(this).addClass(self.css_class.select);
                  self._setCssFocusedResults(self);
              }).click(function (e) {
                  if (self.prop.key_select) {
                      self.prop.key_select = false;
                      return;
                  }
                  e.preventDefault();
                  e.stopPropagation();
                  self._selectCurrentLine(self, false);
              });
          },
  
          /**
           * @private
           * @desc 分页导航按钮的事件处理
           * @param {Object} self - 插件内部对象
           */
          _ehNaviPaging: function (self) {
              $('li.csFirstPage', $(self.elem.navi)).off('click').on('click', function (ev) {
                  $(self.elem.combo_input).focus();
                  ev.preventDefault();
                  self._firstPage(self);
              });
  
              $('li.csPreviousPage', $(self.elem.navi)).off('click').on('click', function (ev) {
                  $(self.elem.combo_input).focus();
                  ev.preventDefault();
                  self._prevPage(self);
              });
  
              // the number of page
              /*
               $(self.elem.navi).find('.navi_page').mouseup(function(ev) {
               $(self.elem.combo_input).focus();
               ev.preventDefault();
               
               if (!self.prop.is_suggest) self.prop.page_all     = parseInt($(this).text(), 10);
               else                       self.prop.page_suggest = parseInt($(this).text(), 10);
               
               self.prop.is_paging = true;
               self._suggest(self);
               });
               */
  
              $('li.csNextPage', $(self.elem.navi)).off('click').on('click', function (ev) {
                  $(self.elem.combo_input).focus();
                  ev.preventDefault();
                  self._nextPage(self);
              });
  
              $('li.csLastPage', $(self.elem.navi)).off('click').on('click', function (ev) {
                  $(self.elem.combo_input).focus();
                  ev.preventDefault();
                  self._lastPage(self);
              });
          },
  
          /**
           * @private
           * @desc Ajax请求失败的处理
           * @param {Object} self - 插件内部对象
           * @errorThrom {string} errorThrown - Ajax的错误输出内容
           */
          _ajaxErrorNotify: function (self, errorThrown) {
              console.log(self.message.ajax_error);
          },
  
          /**
           * @private
           * @desc 窗口滚动处理
           * @param {Object} self - 插件内部对象
           * @param {boolean} enforce - 是否定位到输入框的位置
           */
          _scrollWindow: function (self, enforce) {
              var current_result = self._getCurrentLine(self);
  
              var target_top = (current_result && !enforce) ? current_result.offset().top : $(self.elem.container).offset().top;
  
              var target_size;
  
              self.prop.size_li = $(self.elem.results).children('li:first').outerHeight();
              target_size = self.prop.size_li;
  
              var client_height = $(window).height();
              var scroll_top = $(window).scrollTop();
              var scroll_bottom = scroll_top + client_height - target_size;
  
              // 滚动处理
              var gap;
              if ($(current_result).length) {
                  if (target_top < scroll_top || target_size > client_height) {
                      //滚动到顶部
                      gap = target_top - scroll_top;
                  } else if (target_top > scroll_bottom) {
                      //向下滚动
                      gap = target_top - scroll_bottom;
                  } else {
                      //不进行滚动
                      return;
                  }
              } else if (target_top < scroll_top)
                  gap = target_top - scroll_top;
              window.scrollBy(0, gap);
          },
  
          /**
           * @private
           * @desc 输入框获得焦点的样式设置
           * @param {Object} self - 插件内部对象
           */
          _setCssFocusedInput: function (self) {
              $(self.elem.results).addClass(self.css_class.re_off);
              $(self.elem.combo_input).removeClass(self.css_class.input_off);
          },
  
          /**
           * @private
           * @desc 设置结果列表高亮，输入框失去焦点
           * @param {Object} self - 插件内部对象
           */
          _setCssFocusedResults: function (self) {
              $(self.elem.results).removeClass(self.css_class.re_off);
              $(self.elem.combo_input).addClass(self.css_class.input_off);
          },
  
          /**
           * @private
           * @desc 输入框输入值的变化监控
           * @param {Object} self - 插件内部对象
           */
          _checkValue: function (self) {
              var now_value = $(self.elem.combo_input).val();
              if (now_value != self.prop.prev_value) {
                  self.prop.prev_value = now_value;
                  self.prop.first_show = false;
  
                  //原来的设计是在值变化时，都会清空隐藏域的内容，目前去除该功能
                  //if (self.option.plugin_type != 'textarea') $(self.elem.hidden).val('');
  
                  if (self.option.select_only)
                      self._setButtonAttrDefault();
  
  
                  //重置页数
                  self.prop.page_suggest = 1;
                  self.prop.is_suggest = true;
                  self._suggest(self);
              }
          },
  
          /**
           * @private
           * @desc 文本输入框键盘事件处理
           * @param {Object} self - 插件内部对象
           * @param {Object} e - 事件event对象
           */
          _processKey: function (self, e) {
              if (($.inArray(e.keyCode, [27, 38, 40, 9]) > -1 && $(self.elem.result_area).is(':visible')) || ($.inArray(e.keyCode, [37, 39, 13, 9]) > -1 && self._getCurrentLine(self)) || (e.keyCode == 40)) {
                  e.preventDefault();
                  e.stopPropagation();
                  e.cancelBubble = true;
                  e.returnValue = false;
                  switch (e.keyCode) {
                      case 37:
                          // left
                          if (e.shiftKey)
                              self._firstPage(self);
                          else
                              self._prevPage(self);
                          break;
  
                      case 38:
                          // up
                          self.prop.key_select = true;
                          self._prevLine(self);
                          break;
  
                      case 39:
                          // right
                          if (e.shiftKey)
                              self._lastPage(self);
                          else
                              self._nextPage(self);
                          break;
  
                      case 40:
                          // down
                          if ($(self.elem.results).children('li').length) {
                              self.prop.key_select = true;
                              self._nextLine(self);
                          } else {
                              self.prop.is_suggest = false;
                              self._suggest(self);
                          }
                          break;
  
                      case 9:
                          // tab
                          self.prop.key_paging = true;
                          self._selectCurrentLine(self, true);
                          //self._hideResults(self);
                          break;
  
                      case 13:
                          // return
                          self._selectCurrentLine(self, true);
                          break;
  
                      case 27:
                          //  escape
                          self.prop.key_paging = true;
                          self._hideResults(self);
                          break;
                  }
              } else {
                  if (e.keyCode != 16)
                      self._setCssFocusedInput(self); // except Shift(16)
                  self._inputResize(self);
                  self._checkValue(self);
              }
          },
  
          /**
           * @private
           * @desc 中断Ajax请求
           * @param {Object} self - 插件内部对象
           */
          _abortAjax: function (self) {
              if (self.prop.xhr) {
                  self.prop.xhr.abort();
                  self.prop.xhr = false;
              }
          },
  
          /**
           * @private
           * @desc 数据查询
           * @param {Object} self - 插件内部对象
           */
          _suggest: function (self) {
              //搜索关键字
              var q_word;
  
              //q_word = (self.prop.is_suggest) ? $.trim($(self.elem.combo_input).val()) : '';
              //q_word = $.trim($(self.elem.combo_input).val());
              q_word = (self.prop.first_show) ? '' : $.trim($(self.elem.combo_input).val());
              /*
               //取消在输入状态时，判断到输入框里内容为空时，隐藏下拉列表的操作
               if (q_word.length < 1 && self.prop.is_suggest) {
               self._hideResults(self);
               return;
               }
               */
              q_word = q_word.split(/[\s　]+/);
  
              self._abortAjax(self);
              self._setLoading(self);
              if (self.prop.is_paging) {
                  var obj = self._getCurrentLine(self);
                  self.prop.is_paging = (obj) ? $(self.elem.results).children('li').index(obj) : -1;
              } else if (!self.prop.is_suggest) {
                  self.prop.is_paging = 0;
              }
              //var which_page_num = (self.prop.is_suggest) ? self.prop.page_suggest: self.prop.page_all;
              //var which_page_num = (q_word == '' && !self.prop.page_move) ? 1 : self.prop.page_all;
              //var which_page_num = (self.prop.first_show) ? 1 : self.prop.page_all;
              var which_page_num = self.prop.page_all;
              // 数据查询
              if (typeof self.option.source == 'object')
                  self._searchForJson(self, q_word, which_page_num);
              else
                  self._searchForDb(self, q_word, which_page_num);
          },
  
          /**
           * @private
           * @desc 读取中状态显示
           * @param {Object} self - 插件内部对象
           */
          _setLoading: function (self) {
              $(self.elem.navi_info).text(self.message.loading);
              if ($(self.elem.results).html() === '') {
                  $(self.elem.navi).children('p').empty();
                  self._calcWidthResults(self);
                  $(self.elem.container).addClass(self.css_class.container_open);
              }
          },
  
          /**
           * @private
           * @desc 服务端数据查询
           * @param {Object} self - 插件内部对象
           * @param {Array} q_word - 查询关键字
           * @param {number} which_page_num - 目标页
           */
          _searchForDb: function (self, q_word, which_page_num) {
              /**
               * 增加自定义查询参数
               */
              var _paramsFunc = self.option.params;
              var _params = {};
              //原始参数
              var searchKey = self.option.search_field;
              var _orgParams = {
                  q_word: q_word,
                  page: which_page_num,
                  per_page: self.option.per_page,
                  and_or: self.option.and_or,
                  order_by: self.option.order_by,
                  field: self.option.field,
                  pkey_name: self.option.primary_key,
                  search_field: searchKey
              };
              _orgParams[searchKey] = q_word[0];
              if (_paramsFunc) {
                  var result = $.isFunction(_paramsFunc) ? _paramsFunc() : _paramsFunc;
                  if (result && $.isPlainObject(result)) {
                      _params = $.extend({}, _orgParams, result);
                  } else {
                      _params = _orgParams;
                  }
              } else {
                  _params = _orgParams;
              }
              //增加自定义查询参数End
              self.prop.xhr = $.ajax({
                  dataType: 'json',
                  url: self.option.source,
                  data: _params,
                  success: function (returnData) {
                      if (typeof returnData.list === 'undefined' || !$.isArray(returnData.list)) {
                          if (typeof returnData.rows === 'undefined' || !$.isArray(returnData.rows)) {
                              self.prop.xhr = null;
                              self._notFoundSearch(self);
                              return;
                          } else {
                              returnData.list = returnData.rows;
                          }
                      }
                      if (typeof returnData.total === 'undefined') {
                          returnData.total = returnData.list.length;
                      }
                      //数据结构处理
                      var json = {};
                      json.originalResult = returnData.list;
                      json.cnt_whole = returnData.total;
                      json.candidate = [];
                      json.primary_key = [];
                      json.cnt_page = json.originalResult.length;
                      for (var i = 0; i < json.cnt_page; i++) {
                          for (var key in json.originalResult[i]) {
                              if (key == self.option.primary_key) {
                                  json.primary_key.push(json.originalResult[i][key]);
                              }
                              if (key == self.option.field) {
                                  json.candidate.push(json.originalResult[i][key]);
                              }
                          }
                      }
                      self._prepareResults(self, json, q_word, which_page_num);
                  },
                  error: function (jqXHR, textStatus, errorThrown) {
                      if (textStatus != 'abort') {
                          self._hideResults(self);
                          self._ajaxErrorNotify(self, errorThrown);
                      }
                  },
                  complete: function () {
                      self.prop.xhr = null;
                  }
              });
          },
  
          /**
           * @private
           * @desc 对JSON源数据进行搜索
           * @param {Object} self - 插件内部对象
           * @param {Array} q_word - 搜索关键字
           * @param {number} which_page_num - 目标页数
           */
          _searchForJson: function (self, q_word, which_page_num) {
              var matched = [];
              var esc_q = [];
              var sorted = [];
              var json = {};
              var i = 0;
              var arr_reg = [];
  
              //查询条件过滤
              do {
                  //'/\W/g'正则代表全部不是字母，数字，下划线，汉字的字符
                  //将非法字符进行转义
                  esc_q[i] = q_word[i].replace(/\W/g, '\\$&').toString();
                  arr_reg[i] = new RegExp(esc_q[i], 'gi');
                  i++;
              } while (i < q_word.length);
  
              // SELECT * FROM source WHERE field LIKE q_word;
              for (i = 0; i < self.option.source.length; i++) {
                  var flag = false;
                  var row = self.option.source[i];
                  for (var j = 0; j < arr_reg.length; j++) {
                      var itemText = row[self.option.field];//默认获取showField字段的文本
                      if (self.option.format_item && $.isFunction(self.option.format_item))
                          itemText = self.option.format_item(row);
                      if (itemText.match(arr_reg[j])) {
                          flag = true;
                          if (self.option.and_or == 'OR')
                              break;
                      } else {
                          flag = false;
                          if (self.option.and_or == 'AND')
                              break;
                      }
                  }
                  if (flag)
                      matched.push(row);
              }
  
              //若没有匹配项目，则结束搜索
              if (matched.length === undefined) {
                  self._notFoundSearch(self);
                  return;
              }
              json.cnt_whole = matched.length;
  
              // (CASE WHEN ...) 然后 く order 指定列
              var reg1 = new RegExp('^' + esc_q[0] + '$', 'gi');
              var reg2 = new RegExp('^' + esc_q[0], 'gi');
              var matched1 = [];
              var matched2 = [];
              var matched3 = [];
              for (i = 0; i < matched.length; i++) {
                  if (matched[i][self.option.order_by[0][0]].match(reg1)) {
                      matched1.push(matched[i]);
                  } else if (matched[i][self.option.order_by[0][0]].match(reg2)) {
                      matched2.push(matched[i]);
                  } else {
                      matched3.push(matched[i]);
                  }
              }
  
              if (self.option.order_by[0][1].match(/^asc$/i)) {
                  matched1 = self._sortAsc(self, matched1);
                  matched2 = self._sortAsc(self, matched2);
                  matched3 = self._sortAsc(self, matched3);
              } else {
                  matched1 = self._sortDesc(self, matched1);
                  matched2 = self._sortDesc(self, matched2);
                  matched3 = self._sortDesc(self, matched3);
              }
              sorted = sorted.concat(matched1).concat(matched2).concat(matched3);
  
              //page_move参数用于区别数据加载是在初始化列表还是在进行分页的翻页操作
              if (!self.prop.page_move) {
                  //仅单选模式进行选中项目定位页功能
                  if (!self.option.multiple) {
                      //若控件当前已有选中值，则获得该项目所在的页数，并跳转到该页进行显示
                      var currentValue = $(self.elem.hidden).val();
                      if (typeof (currentValue) != 'undefined' && $.trim(currentValue) != '') {
                          var index = 0;
                          $.each(sorted, function (i, row) {
                              if (row[self.option.primary_key] == currentValue) {
                                  index = i + 1;
                                  return false;
                              }
                          });
                          which_page_num = Math.ceil(index / self.option.per_page);
                          if (which_page_num < 1)
                              which_page_num = 1;
                          self.prop.page_all = which_page_num;
                      }
                  }
              } else {
                  //过滤后的数据个数不足一页显示的个数时，强制设置页码
                  if (sorted.length <= ((which_page_num - 1) * self.option.per_page)) {
                      which_page_num = 1;
                      self.prop.page_all = 1;
                  }
              }
  
              // LIMIT xx OFFSET xx
              var start = (which_page_num - 1) * self.option.per_page;
              var end = start + self.option.per_page;
              //储存原始行数据，包括所有属性
              json.originalResult = [];
  
              // 查询后的数据处理
              for (i = start; i < end; i++) {
                  if (sorted[i] === undefined)
                      break;
                  json.originalResult.push(sorted[i]);
                  for (var key in sorted[i]) {
                      if (key == self.option.primary_key) {
                          if (json.primary_key === undefined)
                              json.primary_key = [];
                          json.primary_key.push(sorted[i][key]);
                      }
                      if (key == self.option.field) {
                          if (json.candidate === undefined)
                              json.candidate = [];
                          json.candidate.push(sorted[i][key]);
                      }
                  }
              }
              if (json.candidate === undefined)
                  json.candidate = [];
              json.cnt_page = json.candidate.length;
              self._prepareResults(self, json, q_word, which_page_num);
          },
  
          /**
           * @private
           * @desc 升充排序
           * @param {Object} self - 插件内部对象
           * @param {Array} arr - 结果集数组
           */
          _sortAsc: function (self, arr) {
              arr.sort(function (a, b) {
                  return a[self.option.order_by[0][0]].localeCompare(b[self.option.order_by[0][0]]);
              });
              return arr;
          },
  
          /**
           * @private
           * @desc 降充排序
           * @param {Object} self - 插件内部对象
           * @param {Array} arr - 结果集数组
           */
          _sortDesc: function (self, arr) {
              arr.sort(function (a, b) {
                  return b[self.option.order_by[0][0]].localeCompare(a[self.option.order_by[0][0]]);
              });
              return arr;
          },
  
          /**
           * @private
           * @desc 查询无结果的处理
           * @param {Object} self - 插件内部对象
           */
          _notFoundSearch: function (self) {
              $(self.elem.navi_info).text(self.message.not_found);
              $(self.elem.navi_p).hide();
              $(self.elem.results).empty();
              self._calcWidthResults(self);
              $(self.elem.container).addClass(self.css_class.container_open);
              self._setCssFocusedInput(self);
          },
  
          /**
           * @private
           * @desc 查询结果处理
           * @param {Object} self - 插件内部对象
           * @param {Object} json - 数据结果
           * @param {Array} q_word - 查询关键字
           * @param {number} which_page_num - 目标页
           */
          _prepareResults: function (self, json, q_word, which_page_num) {
              //处理分页栏
              self._setNavi(self, json.cnt_whole, json.cnt_page, which_page_num);
  
              if (!json.primary_key)
                  json.primary_key = false;
  
              //仅选择模式
              if (self.option.select_only && json.candidate.length === 1 && json.candidate[0] == q_word[0]) {
                  self._setHiddenValue(json.primary_key[0]);
                  this._setButtonAttrDefault();
              }
              //是否是输入关键词进行查找
              var is_query = false;
              if (q_word && q_word.length > 0 && q_word[0])
                  is_query = true;
              //显示结果列表
              self._displayResults(self, json, is_query);
              if (self.prop.is_paging === false)
                  self._setCssFocusedInput(self);
              else {
                  //修复单选模式下如果有选择项，则高亮选中项，而不是高亮第一项
                  if (!self.option.multiple) {
                      var liSelected = $('li.sp_selected', $(self.elem.results));
                      if ($(liSelected).size() == 0) {
                          var idx = self.prop.is_paging;
                          var limit = $(self.elem.results).children('li').length - 1;
                          if (idx > limit)
                              idx = limit;
                          var obj = $(self.elem.results).children('li').eq(idx);
                          $(obj).addClass(self.css_class.select);
                      } else
                          $(liSelected).addClass(self.css_class.select);
                  }
  
                  self.prop.is_paging = false; //重置参数，为下次做准备
                  self._setCssFocusedResults(self);
              }
          },
  
          /**
           * @private
           * @desc 生成分页栏
           * @param {Object} self - 插件内部对象
           * @param {number} cnt_whole - 数据总条数
           * @param {number} cnt_page - 页面显示记录数
           * @param {number} page_num - 当前页数
           */
          _setNavi: function (self, cnt_whole, cnt_page, page_num) {
              /**
               * 生成分页条
               */
              var buildPageNav = function (self, pagebar, page_num, last_page) {
                  if ($('li', $(pagebar)).size() == 0) {
                      $(pagebar).empty();
                      //处理当当前页码为1时，首页和上一页按钮不允许点击
                      var btnclass = '', isNewFontAwesome = true;
                      //判断是否使用了font-awesome3.2.1
                      $.each(document.styleSheets, function (i, n) {
                          if (n && n.href && n.href.indexOf('font-awesome-3.2.1') != -1) {
                              isNewFontAwesome = false;
                              return false;
                          }
                      });
                      //为不同版本图标设置样式
                      var iconFist = 'fa fa-step-backward', iconPrev = 'fa fa-backward', iconNext = 'fa fa-forward', iconLast = 'fa fa-step-forward';
                      if (!isNewFontAwesome) {
                          iconFist = 'icon-step-backward';
                          iconPrev = 'icon-backward';
                          iconNext = 'icon-forward';
                          iconLast = 'icon-step-forward';
                      }
  
                      if (page_num == 1)
                          btnclass = ' disabled ';
                      //首页
                      $(pagebar).append('<li class="csFirstPage' + btnclass + '" title="' + self.message.first_title + '" ><a href="javascript:void(0);"> <i class="' + iconFist + '"></i> </a></li>');
                      //上一页
                      $(pagebar).append('<li class="csPreviousPage' + btnclass + '" title="' + self.message.prev_title + '" ><a href="javascript:void(0);"><i class="' + iconPrev + '"></i></a></li>');
                      var pageInfo = '第 ' + page_num + ' 页(共' + last_page + '页)';
                      //设置分页信息
                      $(pagebar).append('<li class="disabled pageInfoBox"><a href="javascript:void(0);"> ' + pageInfo + ' </a></li>');
  
                      if (page_num == last_page)
                          btnclass = ' disabled ';
                      else
                          btnclass = '';
                      //首页
                      $(pagebar).append('<li class="csNextPage' + btnclass + '" title="' + self.message.next_title + '" ><a href="javascript:void(0);"><i class="' + iconNext + '"></i></a></li>');
                      //上一页
                      $(pagebar).append('<li class="csLastPage' + btnclass + '" title="' + self.message.last_title + '" ><a href="javascript:void(0);"> <i class="' + iconLast + '"></i> </a></li>');
                  }
              };
  
              var pagebar = $(self.elem.navi);
              pagebar.toggleClass("hide", cnt_whole < self.option.per_page)
              var last_page = Math.ceil(cnt_whole / self.option.per_page); //计算总页数
              if (last_page == 0)
                  page_num = 0;
              else {
                  if (page_num == 0)
                      page_num = 1;
              }
              buildPageNav(self, pagebar, page_num, last_page);
              //刷新分页信息
              var pageInfoBox = $('li.pageInfoBox', $(pagebar));
  
              var pageInfo = '第 ' + page_num + ' 页(共' + last_page + '页)';
              $(pageInfoBox).html('<a href="javascript:void(0);"> ' + pageInfo + ' </a>');
              //更新分页样式
              var dClass = 'disabled';
              var first = $('li.csFirstPage', $(pagebar));
              var previous = $('li.csPreviousPage', $(pagebar));
              var next = $('li.csNextPage', $(pagebar));
              var last = $('li.csLastPage', $(pagebar));
              //处理首页，上一页按钮样式
              if (page_num == 1 || page_num == 0) {
                  if (!$(first).hasClass(dClass))
                      $(first).addClass(dClass);
                  if (!$(previous).hasClass(dClass))
                      $(previous).addClass(dClass);
              } else {
                  if ($(first).hasClass(dClass))
                      $(first).removeClass(dClass);
                  if ($(previous).hasClass(dClass))
                      $(previous).removeClass(dClass);
              }
              //处理下一页，最后一页按钮的样式
              if (page_num == last_page || last_page == 0) {
                  if (!$(next).hasClass(dClass))
                      $(next).addClass(dClass);
                  if (!$(last).hasClass(dClass))
                      $(last).addClass(dClass);
              } else {
                  if ($(next).hasClass(dClass))
                      $(next).removeClass(dClass);
                  if ($(last).hasClass(dClass))
                      $(last).removeClass(dClass);
              }
  
              if (last_page > 1) {
                  if (self.prop.is_suggest)
                      self.prop.max_suggest = last_page;
                  else
                      self.prop.max_all = last_page;
  
                  self._ehNaviPaging(self); // 导航按钮的事件设置
              } else {
                  //$(self.elem.navi).hide();
              }
          },
  
          /**
           * @private
           * @desc 显示结果集列表
           * @param {Object} self - 插件内部对象
           * @param {Object} json 源数据
           * @param {boolean} is_query - 是否是通过关键字搜索（用于区分是鼠标点击下拉还是输入框输入关键字进行查找）
           */
          _displayResults: function (self, json, is_query) {
              $(self.elem.results).empty();
              var arr_candidate = json.candidate;
              var arr_primary_key = json.primary_key;
              var keystr = $(self.elem.hidden).val();
              var keyArr = $.isArray(keystr) ? keystr : (keystr ? keyArr = keystr.split(',') : new Array());
              for (var i = 0; i < arr_candidate.length; i++) {
                  var itemText = '';
                  if (self.option.format_item && $.isFunction(self.option.format_item)) {
                      try {
                          itemText = self.option.format_item(json.originalResult[i]);
                      } catch (e) {
                          console.error('formatItem内容格式化函数内容设置不正确！');
                          itemText = arr_candidate[i];
                      }
                  } else
                      itemText = arr_candidate[i];
                  //XSS対策
                  var list = $('<li>').html(itemText).attr({
                      pkey: arr_primary_key[i],
                      pvalue: arr_candidate[i],
                      title: itemText
                  });
  
                  if (typeof arr_primary_key[i] !== 'undefined' && $.inArray(arr_primary_key[i].toString(), keyArr) != -1) {
                      $(list).addClass(self.css_class.selected);
                  }
                  //缓存原始行对象
                  $(list).data('dataObj', json.originalResult[i]);
                  $(self.elem.results).append(list);
              }
              //显示结果集列表并调整位置
              self._calcWidthResults(self);
  
              $(self.elem.container).addClass(self.css_class.container_open);
  
              //结果集列表事件绑定
              self._ehResults();
              //若是键盘输入关键字进行查询且有内容时，列表自动选中第一行(auto_select_first为true时)
              if (is_query && arr_candidate.length > 0 && self.option.auto_select_first)
                  self._nextLine(self);
              //按钮的title属性修改
              $(self.elem.button).attr('title', self.message.close_btn);
          },
  
          /**
           * @private
           * @desc 处理结果列表尺寸及位置
           * @param {Object} self - 插件内部对象
           */
          _calcWidthResults: function (self) {
              //若列表已展现，则不再处理
              //###代码已禁用###若启用，在翻页时，会不计算位置，导致数据量不一致时列表不会自动定位
              //if($(self.elem.result_area).is(":visible")) return;
  
              //设置下拉列表与输入框同宽
              //###代码已禁用###因为分页栏是固定宽度的原因，列表与输入框宽度同步功能不能再使用
              /*
               $(self.elem.result_area)
               .width(
               $(self.elem.container).width() -
               ($(self.elem.result_area).outerWidth() - $(self.elem.result_area).innerWidth())
               )
               .show();
               */
              $(self.elem.result_area).show(1, function () {
                  /*
                   //设置外框宽度，只需要初始化时设置即可，不需要在每次展开列表时进行设置，这里暂时屏蔽该功能
                   //单选模式下，设置外框与输入框尺寸一致
                   if(!self.option.multiple){
                   $(self.elem.container).width($(self.elem.combo_input).outerWidth());
                   }
                   */
                  if ($(self.elem.container).css('position') == 'static') {
                      // position: static
                      var offset = $(self.elem.combo_input).offset();
                      $(self.elem.result_area).css({
                          top: offset.top + $(self.elem.combo_input).outerHeight() + 'px',
                          left: offset.left + 'px'
                      });
                  } else {
                      //在展示下拉列表时，判断默认与输入框左对齐的列表是否会超出屏幕边界，是则右对齐，否则默认左对齐
                      var browserWidth = document.body.clientWidth;
                      var browserHeight = document.body.clientHeight;
                      var offset = $(self.elem.container).offset();
                      var listWidth = $(self.elem.result_area).outerWidth();
                      //当前状态，列表并未被显示，数据未被填充，列表并未展现最终高度，所以只能使用默认一页显示10条数据的固定高度进行计算
                      var listHeight = $(self.elem.result_area).outerHeight();
                      //默认方向的坐标，在多选模式下，因为外框架是DIV，所以需要向左靠一个像素
                      var defaultLeft = self.option.multiple ? -1 : 0;
                      var left = (offset.left + listWidth) > browserWidth ? -(listWidth - $(self.elem.container).outerWidth()) : defaultLeft;
                      //控件在当前可视区域中的高度
                      var screenTop = offset.top - $(window).scrollTop();
                      var top = 0;
                      if ((screenTop + $(self.elem.container).outerHeight() + listHeight) > browserHeight) {
                          top = -(listHeight + 1);
                          $(self.elem.result_area).removeClass('shadowUp shadowDown').addClass('shadowUp');
                      } else {
                          top = self.option.multiple ? $(self.elem.container).innerHeight() + 1 : $(self.elem.container).outerHeight();
                          $(self.elem.result_area).removeClass('shadowUp shadowDown').addClass('shadowDown');
                      }
                      // position: relative, absolute, fixed
                      $(self.elem.result_area).css({
                          top: top + 'px',
                          left: left + 'px'
                      });
                  }
              });
          },
  
          /**
           * @private
           * @desc 隐藏结果列表
           * @param {Object} self - 插件内部对象
           */
          _hideResults: function (self) {
              if (self.prop.key_paging) {
                  self._scrollWindow(self, true);
                  self.prop.key_paging = false;
              }
              self._setCssFocusedInput(self);
  
              if (self.option.auto_fill_result) {
                  //self._selectCurrentLine(self, true);
              }
  
              $(self.elem.results).empty();
              $(self.elem.result_area).hide();
              $(self.elem.container).removeClass(self.css_class.container_open);
  
              self._abortAjax(self);
              self._setButtonAttrDefault(); // 按钮title属性初期化
          },
  
          /**
           * @private
           * @desc 跳转到首页
           * @param {Object} self - 插件内部对象
           */
          _firstPage: function (self) {
              if (self.prop.page_all > 1) {
                  self.prop.page_all = 1;
                  self.prop.is_paging = true;
                  self.prop.page_move = true;
                  self._suggest(self);
              }
              /*
               if (!self.prop.is_suggest) {
               if (self.prop.page_all > 1) {
               self.prop.page_all = 1;
               self.prop.is_paging = true;
               self.prop.page_move = true;
               self._suggest(self);
               }
               } else {
               if (self.prop.page_suggest > 1) {
               self.prop.page_suggest = 1;
               self.prop.is_paging = true;
               self._suggest(self);
               }
               }
               */
          },
  
          /**
           * @private
           * @desc 跳转到上一页
           * @param {Object} self - 插件内部对象
           */
          _prevPage: function (self) {
              if (self.prop.page_all > 1) {
                  self.prop.page_all--;
                  self.prop.is_paging = true;
                  self.prop.page_move = true;
                  self._suggest(self);
              }
              /*
               if (!self.prop.is_suggest) {
               if (self.prop.page_all > 1) {
               self.prop.page_all--;
               self.prop.is_paging = true;
               self.prop.page_move = true;
               self._suggest(self);
               }
               } else {
               if (self.prop.page_suggest > 1) {
               self.prop.page_suggest--;
               self.prop.is_paging = true;
               self._suggest(self);
               }
               }
               */
          },
  
          /**
           * @private
           * @desc 跳转到下一页
           * @param {Object} self - 插件内部对象
           */
          _nextPage: function (self) {
              if (self.prop.page_all < self.prop.max_all) {
                  self.prop.page_all++;
                  self.prop.is_paging = true;
                  self.prop.page_move = true;
                  self._suggest(self);
              }
              /*
               if (self.prop.is_suggest) {
               if (self.prop.page_suggest < self.prop.max_suggest) {
               self.prop.page_suggest++;
               self.prop.is_paging = true;
               self._suggest(self);
               }
               } else {
               if (self.prop.page_all < self.prop.max_all) {
               self.prop.page_all++;
               self.prop.is_paging = true;
               self.prop.page_move = true;
               self._suggest(self);
               }
               }
               */
          },
  
          /**
           * @private
           * @desc 跳转到尾页
           * @param {Object} self - 插件内部对象
           */
          _lastPage: function (self) {
              if (self.prop.page_all < self.prop.max_all) {
                  self.prop.page_all = self.prop.max_all;
                  self.prop.is_paging = true;
                  self.prop.page_move = true;
                  self._suggest(self);
              }
              /*
               if (!self.prop.is_suggest) {
               if (self.prop.page_all < self.prop.max_all) {
               self.prop.page_all = self.prop.max_all;
               self.prop.is_paging = true;
               self.prop.page_move = true;
               self._suggest(self);
               }
               } else {
               if (self.prop.page_suggest < self.prop.max_suggest) {
               self.prop.page_suggest = self.prop.max_suggest;
               self.prop.is_paging = true;
               self._suggest(self);
               }
               }
               */
          },
          /**
           * @private
           * @desc 跳转到指定页
           * @param {Object} self
           * @param {number} page 目标页数
           */
          _goPage: function (self, page) {
              if (typeof (page) == 'undefined')
                  page = 1;
              if (self.prop.page_all < self.prop.max_all) {
                  self.prop.page_all = page;
                  self.prop.is_paging = true;
                  self.prop.page_move = true;
                  self._suggest(self);
              }
              /*
               if (self.prop.is_suggest) {
               if (self.prop.page_suggest < self.prop.max_suggest) {
               self.prop.page_suggest = page;
               self.prop.is_paging = true;
               self._suggest(self);
               }
               } else {
               if (self.prop.page_all < self.prop.max_all) {
               self.prop.page_all = page;
               self.prop.is_paging = true;
               self.prop.page_move = true;
               self._suggest(self);
               }
               }
               */
          },
  
          /**
           * @private
           * @desc 选择当前行
           * @param {Object} self - 插件内部对象
           * @param {boolean} is_enter_key - 是否为回车键
           */
          _selectCurrentLine: function (self, is_enter_key) {
              self._scrollWindow(self, true);
  
              var current = self._getCurrentLine(self);
              if (current) {
                  var pkey = $(current).attr('pkey');
                  var text = self.option.format_fill ? $(current).text() : $(current).attr("pvalue");
                  if (!self.option.multiple) {
                      $(self.elem.combo_input).val(text);
                      self._setHiddenValue(pkey);
                  } else {
                      //多选模式的项目选择处理
                      $(self.elem.combo_input).val('');
                      var item = {text: text, value: pkey};
                      if (!self._isAlreadySelected(self, item)) {
                          self._addNewTag(self, item);
                          self._tagValuesSet(self);
                      }
                  }
  
                  if (self.option.select_only)
                      self._setButtonAttrDefault();
                  //触发元素的事件
                  $(self.elem.hidden).trigger("change");
  
                  //回调函数触发
                  if (typeof self.option.callback === 'function') {
                      self.option.callback.call(self, $(current).data('dataObj'));
                  }
                  //触发指定事件
                  if (self.option.bind_to) {
                      $(self.elem.combo_input).trigger(self.option.bind_to, $(current).data('dataObj'));
                  }
  
                  self.prop.prev_value = $(self.elem.combo_input).val();
                  self._hideResults(self);
              }
  
              //$(self.elem.combo_input).focus();
              $(self.elem.combo_input).trigger("change");
              $(self.elem.combo_input).trigger("blur");
              self._setCssFocusedInput(self);
              self._inputResize(self);
          },
  
          /**
           * @private
           * @desc 获得当前行对象
           * @param {Object} self - 插件内部对象
           */
          _getCurrentLine: function (self) {
              if ($(self.elem.result_area).is(':hidden'))
                  return false;
              var obj = $(self.elem.results).children('li.' + self.css_class.select);
              if ($(obj).length)
                  return obj;
              else
                  return false;
          },
  
          /**
           * @private
           * @desc 多选模式下判断当前选中项目是否已经存在已选中列表中
           * @param {Object} self - 插件内部对象
           * @param {Object} item - 选中行对象
           */
          _isAlreadySelected: function (self, item) {
              var isExist = false;
              if (item.value) {
                  var keys = $(self.elem.hidden).val();
                  if (keys) {
                      var karr = $.isArray(keys) ? keys : (keys ? keys.split(',') : new Array());
                      if (karr && karr.length > 0 && $.inArray(item.value, karr) != -1)
                          isExist = true;
                  }
              }
              return isExist;
          },
  
          /**
           * @private
           * @desc 多选模式下增加一个标签
           * @param {Object} self - 插件内部对象
           * @param {Object} item - 选中行对象
           */
          _addNewTag: function (self, item) {
              if (!self.option.multiple || !item)
                  return;
              var tmp = self.template.tag.content;
              tmp = tmp.replace(self.template.tag.textKey, item.text);
              tmp = tmp.replace(self.template.tag.valueKey, item.value);
              $(self.elem.combo_input).closest('li').before($(tmp));
          },
  
          /**
           * @private
           * @desc 多选模式下标签结果值放入隐藏域
           * @param {Object} self - 插件内部对象
           */
          _tagValuesSet: function (self) {
              if (!self.option.multiple)
                  return;
              var tags = $('li.selected_tag', $(self.elem.element_box));
              if (tags && $(tags).size() > 0) {
                  var result = new Array();
                  $.each(tags, function (i, li) {
                      var v = $(li).attr('itemvalue');
                      if ($.type(v) != 'undefined')
                          result.push(v);
                  });
                  if (result.length > 0) {
                      self._setHiddenValue(result);
                  }
  
              }
          },
  
          /**
           * @private
           * @desc 多选模式下输入框根据输入内容调整输入框宽度
           * @param {Object} self - 插件内部对象
           */
          _inputResize: function (self) {
              if (!self.option.multiple)
                  return;
              var width = '';
              var inputLi = self.elem.combo_input.closest('li');
              //设置默认宽度
              var setDefaultSize = function (self, inputLi) {
                  inputLi.removeClass('full_width');
                  var minimumWidth = self.elem.combo_input.val().length + 1;
                  var width = (minimumWidth * 0.75) + 'em';
                  self.elem.combo_input.css('width', width);
                  self.elem.combo_input.removeAttr('placeholder');
              };
              if ($('li.selected_tag', $(self.elem.element_box)).size() == 0) {
                  if (self.elem.combo_input.attr('placeholder_bak')) {
                      if (!inputLi.hasClass('full_width'))
                          inputLi.addClass('full_width');
                      self.elem.combo_input.attr('placeholder', self.elem.combo_input.attr('placeholder_bak'));
                  } else
                      setDefaultSize(self, inputLi);
              } else
                  setDefaultSize(self, inputLi);
          },
  
          /**
           * @private
           * @desc 选择下一行
           * @param {Object} self - 插件内部对象
           */
          _nextLine: function (self) {
              var obj = self._getCurrentLine(self);
              var idx;
              if (!obj)
                  idx = -1;
              else {
                  idx = $(self.elem.results).children('li').index(obj);
                  $(obj).removeClass(self.css_class.select);
              }
              idx++;
              if (idx < $(self.elem.results).children('li').length) {
                  var next = $(self.elem.results).children('li').eq(idx);
                  $(next).addClass(self.css_class.select);
                  self._setCssFocusedResults(self);
              } else
                  self._setCssFocusedInput(self);
              self._scrollWindow(self, false);
          },
  
          /**
           * @private
           * @desc 选择上一行
           * @param {Object} self - 插件内部对象
           */
          _prevLine: function (self) {
              var obj = self._getCurrentLine(self);
              var idx;
              if (!obj)
                  idx = $(self.elem.results).children('li').length;
              else {
                  idx = $(self.elem.results).children('li').index(obj);
                  $(obj).removeClass(self.css_class.select);
              }
              idx--;
              if (idx > -1) {
                  var prev = $(self.elem.results).children('li').eq(idx);
                  $(prev).addClass(self.css_class.select);
                  self._setCssFocusedResults(self);
              } else
                  self._setCssFocusedInput(self);
              self._scrollWindow(self, false);
          }
      });
      return SelectPage;
  }));
  