jquery中的“这个”问题

时间:2011-03-05 06:23:30

标签: jquery jquery-ui

我试图在jquery ui autocomplete中覆盖一个函数。

当我这样做时

$.ui.autocomplete.prototype._create = function() {
    var self = this,
    doc = this.element[ 0 ].ownerDocument,
    suppressKeyPress;
    this._value( ... ) ;

我收到了错误._value未定义。

我知道this上下文搞砸了。我该如何解决?

我尝试使用$.proxy,但后来我不知道如何引用原始$.ui.autocomplete内部闭包的上下文。

编辑:

好的,让我打破这个。我想编辑jquery自动完成功能,这样当用户点击自定义内容时,它将忽略它而不是输入它。

原始问题来自:JQuery Autocomplete. If item cannot be found, display "Press Enter to insert into autocomplete"?

让我们分解问题:

我正在扩展这个功能:

$.ui.autocomplete.prototype._create = function() {
  console.log(this, $.ui.autocomplete);
  var self = this,
    doc = this.element[ 0 ].ownerDocument,
    suppressKeyPress;

  this.valueMethod = this.element[ this.element.is( "input" ) ? "val" : "text" ];

  this.element
    .addClass( "ui-autocomplete-input" )
    .attr( "autocomplete", "off" )
    // TODO verify these actually work as intended
    .attr({
      role: "textbox",
      "aria-autocomplete": "list",
      "aria-haspopup": "true"
    })
    .bind( "keydown.autocomplete", function( event ) {
      if ( self.options.disabled || self.element.attr( "readonly" ) ) {
        return;
      }

      suppressKeyPress = false;
      var keyCode = $.ui.keyCode;
      switch( event.keyCode ) {
      case keyCode.PAGE_UP:
        self._move( "previousPage", event );
        break;
      case keyCode.PAGE_DOWN:
        self._move( "nextPage", event );
        break;
      case keyCode.UP:
        self._move( "previous", event );
        // prevent moving cursor to beginning of text field in some browsers
        event.preventDefault();
        break;
      case keyCode.DOWN:
        self._move( "next", event );
        // prevent moving cursor to end of text field in some browsers
        event.preventDefault();
        break;
      case keyCode.ENTER:
      case keyCode.NUMPAD_ENTER:
        // when menu is open and has focus
        if ( self.menu.active ) {
          // #6055 - Opera still allows the keypress to occur
          // which causes forms to submit
          suppressKeyPress = true;
          event.preventDefault();
        }
        //passthrough - ENTER and TAB both select the current element
      case keyCode.TAB:
        if ( !self.menu.active ) {
          return;
        }
        self.menu.select( event );
        break;
      case keyCode.ESCAPE:
        self._value( self.term );
        self.close( event );
        break;
      default:
        // keypress is triggered before the input value is changed
        clearTimeout( self.searching );
        self.searching = setTimeout(function() {
          // only search if the value has changed
          if ( self.term != self._value() ) {
            self.selectedItem = null;
            self.search( null, event );
          }
        }, self.options.delay );
        break;
      }
    })
    .bind( "keypress.autocomplete", function( event ) {
      if ( suppressKeyPress ) {
        suppressKeyPress = false;
        event.preventDefault();
      }
    })
    .bind( "focus.autocomplete", function() {
      if ( self.options.disabled ) {
        return;
      }

      self.selectedItem = null;
      self.previous = self._value();
    })
    .bind( "blur.autocomplete", function( event ) {
      if ( self.options.disabled ) {
        return;
      }

      clearTimeout( self.searching );
      // clicks on the menu (or a button to trigger a search) will cause a blur event
      self.closing = setTimeout(function() {
        self.close( event );
        self._change( event );
      }, 150 );
    });
  this._initSource();
  this.response = function() {
    return self._response.apply( self, arguments );
  };
  this.menu = $( "<ul></ul>" )
    .addClass( "ui-autocomplete" )
    .appendTo( $( this.options.appendTo || "body", doc )[0] )
    // prevent the close-on-blur in case of a "slow" click on the menu (long mousedown)
    .mousedown(function( event ) {
      // clicking on the scrollbar causes focus to shift to the body
      // but we can't detect a mouseup or a click immediately afterward
      // so we have to track the next mousedown and close the menu if
      // the user clicks somewhere outside of the autocomplete
      var menuElement = self.menu.element[ 0 ];
      if ( !$( event.target ).closest( ".ui-menu-item" ).length ) {
        setTimeout(function() {
          $( document ).one( 'mousedown', function( event ) {
            if ( event.target !== self.element[ 0 ] &&
              event.target !== menuElement &&
              !$.contains( menuElement, event.target ) ) {
              self.close();
            }
          });
        }, 1 );
      }

      // use another timeout to make sure the blur-event-handler on the input was already triggered
      setTimeout(function() {
        clearTimeout( self.closing );
      }, 13);
    })
    .menu({
      // custom key handling for now
      input: $(),
      focus: function( event, ui ) {
        var item = ui.item.data( "item.autocomplete" );
        if ( false !== self._trigger( "focus", event, { item: item } ) ) {
          // use value to match what will end up in the input, if it was a key event
          if ( /^key/.test(event.originalEvent.type) ) {
            self._value( item.value );
          }
        }
      },
      select: function( event, ui ) {
        console.log(event, ui);

        var item = ui.item.data( "item.autocomplete" ),
          previous = self.previous;

        // only trigger when focus was lost (click on menu)
        if ( self.element[0] !== doc.activeElement ) {
          self.element.focus();
          self.previous = previous;
          // #6109 - IE triggers two focus events and the second
          // is asynchronous, so we need to reset the previous
          // term synchronously and asynchronously :-(
          setTimeout(function() {
            self.previous = previous;
            self.selectedItem = item;
          }, 1);
        }

        if ( false !== self._trigger( "select", event, { item: item } ) ) {
          self._value( item.value );
        }
        // reset the term after the select event
        // this allows custom select handling to work properly
        self.term = self._value();

        self.close( event );
        self.selectedItem = item;
      },
      blur: function( event, ui ) {
        // don't set the value of the text field if it's already correct
        // this prevents moving the cursor unnecessarily
        if ( self.menu.element.is(":visible") &&
          ( self._value() !== self.term ) ) {
          self._value( self.term );
        }
      }
    })
    .zIndex( this.element.zIndex() + 1 )
    .hide()
    .data( "menu" );
  if ( $.fn.bgiframe ) {
     this.menu.element.bgiframe();
  }
};

直接从jquery.ui.autcomplete.js

复制

为方便起见,找到了jquery自动填充https://github.com/jquery/jquery-ui/blob/master/ui/jquery.ui.autocomplete.js

2 个答案:

答案 0 :(得分:1)

我没有尝试像这样扩展创建功能,而是建议去http://jqueryui.com/demos/autocomplete/#custom-data并查看来源。它显示了自定义选择事件,这些事件听起来更符合您的需求并且更容易实现。如果所选元素的值为“按Enter键创建此标记”,则只能在select事件中返回false。

答案 1 :(得分:0)

某种突破:

显然,如果我做以下事情:

<script src='/static/lib/ui-src/jquery.ui.core.js'></script> 
<script src='/static/lib/ui-src/jquery.ui.widget.js'></script> 
<script src='/static/lib/ui-src/jquery.ui.menu.js'></script> 
<script src='/static/lib/ui-src/jquery.ui.autocomplete.js'></script> 

我不会有任何错误。 (含义this._value在$ .ui.autocomplete.prototype._create = function(){this._value ..})中定义。

但是,如果我这样做:

<script src="/static/lib/jqueryui/jquery-ui.js"></script>

我会得到_value错误。我的jquery.ui.js基本上是jquery ui的压缩版本,所有组件都是1.8.10。

这个问题可能是什么原因?