【问题标题】:"this" problem in jqueryjquery中的“this”问题
【发布时间】:2011-03-05 06:23:29
【问题描述】:

我正在尝试覆盖 jquery ui 自动完成中的一个函数。

当我这样做时

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

我收到 this._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

【问题讨论】:

  • 1) 你为什么用, 而不是; 结束你的行? 2) 你的self 应该在函数之外声明为有用。 3) 什么是_value?它在哪里定义? 4) 你想完成什么?
  • 你能多加一点你的代码吗
  • @Kirk,我认为他只是使用逗号来分隔变量声明 supressKeyPress 只是没有实例化(我根据我所看到的猜测)。但是,我不完全确定您要达到的目标@disappearedng。
  • @vivek this._value,在 jquery.ui.autocomplete.js 的第 414 行定义
  • @kirk 评论,不,那是作者选择使用的。

标签: jquery jquery-ui


【解决方案1】:

我建议不要尝试像这样扩展创建函数,而是前往http://jqueryui.com/demos/autocomplete/#custom-data 并查看源代码。它显示了自定义选择事件,听起来更符合您的需要并且更容易实现。如果所选元素的值为“按回车键创建此标签”,您可以在选择事件中返回 false。

【讨论】:

    【解决方案2】:

    某种突破:

    显然,如果我执行以下操作:

    <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。

    这个问题的根源是什么?

    【讨论】:

    • 我们注意到在使用带有所有组件的 jquery ui 文件时出现了一个问题……还没有弄清楚。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-09-01
    • 2021-02-27
    • 1970-01-01
    • 1970-01-01
    • 2014-01-04
    • 2011-04-26
    相关资源
    最近更新 更多