2011-03-05 44 views
4

我想覆蓋jquery ui自動完成功能。「這個」問題在jquery

當我做

$.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

+0

_value? 或 val? – 2011-03-05 06:26:47

+4

1)爲什麼你用','而不是'''結束你的行? 2)你的'self'應該在函數之外聲明是有用的。 3)什麼是_value?它在哪裏定義? 4)你想完成什麼? – 2011-03-05 06:27:08

+1

你可以添加更多的代碼 – 2011-03-05 06:30:05

回答

1

而不是試圖擴展這樣的創建功能,我推薦去這裏http://jqueryui.com/demos/autocomplete/#custom-data並查看源代碼。它顯示了自定義選擇事件,它聽起來更符合你所需要的內容,並且更容易實現。如果所選元素的值爲「按Enter鍵創建此標籤」,則可以在選擇事件中返回false。

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定義=函數(){this._value ..})

但是,如果我這樣做:

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

我會得到_value錯誤。我的jquery.ui.js基本上是jquery ui的壓縮版本,所有組件都是1.8.10。

什麼可能是這個問題的來源?

+0

我們已經注意到在所有組件中使用jquery ui文件時出現問題......還沒有弄清楚。 – 2011-08-16 01:40:51