"this" problem in jquery
I am trying to overwrite a function in jquery ui autocomplete.
When I do
$.ui.autocomplete.prototype._create = function() {
var self = this,
doc = this.element[ 0 ].ownerDocument,
suppressKeyPress;
this._value( ... ) ;
I am getting the error of this._value is undefined.
I know that the this
context is messed up. How do I fix this?
I try to use $.proxy
, but then I don't know how to refer the context of the original $.ui.autocomplete
's inner closure.
EDIT:
Ok let me break this down. I want to edit jquery autocomplete such that when the user clicks on a custom content it will simply ignore it rather than inputting it.
The original question comes from this: JQuery Autocomplete. If item cannot be found, display "Press Enter to insert into autocomplete"?
So let's break down on the questions:
I am extending this function:
$.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 focu开发者_JAVA技巧s
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();
}
};
which is directly copied from jquery.ui.autcomplete.js
For your convenience, jquery autocomplete is found https://github.com/jquery/jquery-ui/blob/master/ui/jquery.ui.autocomplete.js
Instead of trying to extend the create function like this I recommend going here http://jqueryui.com/demos/autocomplete/#custom-data and viewing the source. It shows custom select events which sounds more along the lines of what you need and is easier to implent. If the value of the selected element is "Press enter to create this tag" you can just return false in your select event.
Some kind of break through:
So apparently, if I do the following:
<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>
I won't get any errors. (Meaning this._value is defined inside $.ui.autocomplete.prototype._create = function() { this._value .. })
However, if I do this:
<script src="/static/lib/jqueryui/jquery-ui.js"></script>
I will get the _value error. My jquery.ui.js is basically the compressed version of jquery ui with ALL components of 1.8.10.
What could be a source for this problem?
精彩评论