Apply jQuery autocomplete to cloned element - javascript

I am using jQuery autocomplete which is working fine with existing element but not with dynamically added element.
Here is my autocomplete code (Which I have changed a bit)
$(function() {
(function( $ ) {
$.widget( "ui.combobox", {
_create: function() {
var self = this,
select = this.element.hide(),
selected = select.children( ":selected" ),
value = selected.val() ? selected.text() : "";
var input = this.input = $( ".editableCombobox" ) // your input box
//.insertAfter( select )
.val( value )
.autocomplete({
delay: 0,
minLength: 0,
source: function( request, response ) {
var matcher = new RegExp( $.ui.autocomplete.escapeRegex(request.term), "i" );
response( select.children( "option" ).map(function() {
var text = $( this ).text();
if ( this.value && ( !request.term || matcher.test(text) ) )
return {
label: text.replace(
new RegExp(
"(?![^&;]+;)(?!<[^<>]*)(" +
$.ui.autocomplete.escapeRegex(request.term) +
")(?![^<>]*>)(?![^&;]+;)", "gi"
), "$1" ),
value: text,
option: this
};
}) );
},
select: function( event, ui ) {
ui.item.option.selected = true;
self._trigger( "selected", event, {
item: ui.item.option
});
},
change: function( event, ui ) {
if ( !ui.item ) {
var matcher = new RegExp( "^" + $.ui.autocomplete.escapeRegex( $(this).val() ) + "$", "i" ),
valid = false;
select.children( "option" ).each(function() {
if ( $( this ).text().match( matcher ) ) {
this.selected = valid = true;
return false;
}
});
//if ( !valid ) {
// remove invalid value, as it didn't match anything
//$( this ).val( "" );
//select.val( "" );
//input.data( "autocomplete" ).term = "";
//return false;
// }
}
}
})
.addClass( "ui-widget ui-widget-content ui-corner-left" );
input.data( "autocomplete" )._renderItem = function( ul, item ) {
return $( "<li></li>" )
.data( "item.autocomplete", item )
.append( "<a>" + item.label + "</a>" )
.appendTo( ul );
};
this.button = $( "<button type='button'> </button>" )
.attr( "tabIndex", -1 )
.attr( "title", "Show All Items" )
.insertAfter( input )
.button({
icons: {
primary: "ui-icon-triangle-1-s"
},
text: false
})
.removeClass( "ui-corner-all" )
//.addClass( "ui-corner-right ui-button-icon" )
.live('click',function() {
// close if already visible
if ( $(this).prev().autocomplete( "widget" ).is( ":visible" ) ) {
$(this).prev().autocomplete( "close" );
return;
}
// work around a bug (likely same cause as #5265)
$( this ).blur();
// pass empty string as value to search for, displaying all results
$(this).prev().autocomplete( "search", "" );
$(this).prev().focus();
});
},
destroy: function() {
this.input.remove();
this.button.remove();
this.element.show();
$.Widget.prototype.destroy.call( this );
}
});
})( jQuery );
$( "#combobox" ).combobox();
$( "#toggle" ).live('click',function() {
$( "#combobox" ).toggle();
});
});
Here is my code which adds new element
var selectedRow = $('#contactGroup'+rowId);
var clonedRow = selectedRow.clone();
selectedRow.after(clonedRow);
After reading many similar questions I think .live might help but not sure where to use it.
EDIT:
I tried removing live.
New code for Autocomplete
$(function() {
(function( $ ) {
$.widget( "ui.combobox", {
_create: function() {
var self = this,
select = this.element.hide(),
selected = select.children( ":selected" ),
value = selected.val() ? selected.text() : "";
var input = this.input = $( ".editableCombobox" ) // your input box
//.insertAfter( select )
.val( value )
.autocomplete({
delay: 0,
minLength: 0,
source: function( request, response ) {
var matcher = new RegExp( $.ui.autocomplete.escapeRegex(request.term), "i" );
response( select.children( "option" ).map(function() {
var text = $( this ).text();
if ( this.value && ( !request.term || matcher.test(text) ) )
return {
label: text.replace(
new RegExp(
"(?![^&;]+;)(?!<[^<>]*)(" +
$.ui.autocomplete.escapeRegex(request.term) +
")(?![^<>]*>)(?![^&;]+;)", "gi"
), "$1" ),
value: text,
option: this
};
}) );
},
select: function( event, ui ) {
ui.item.option.selected = true;
self._trigger( "selected", event, {
item: ui.item.option
});
},
change: function( event, ui ) {
if ( !ui.item ) {
var matcher = new RegExp( "^" + $.ui.autocomplete.escapeRegex( $(this).val() ) + "$", "i" ),
valid = false;
select.children( "option" ).each(function() {
if ( $( this ).text().match( matcher ) ) {
this.selected = valid = true;
return false;
}
});
//if ( !valid ) {
// remove invalid value, as it didn't match anything
//$( this ).val( "" );
//select.val( "" );
//input.data( "autocomplete" ).term = "";
//return false;
// }
}
}
})
.addClass( "ui-widget ui-widget-content ui-corner-left" );
input.data( "autocomplete" )._renderItem = function( ul, item ) {
return $( "<li></li>" )
.data( "item.autocomplete", item )
.append( "<a>" + item.label + "</a>" )
.appendTo( ul );
};
this.button = $( "<button type='button'> </button>" )
.attr( "tabIndex", -1 )
.attr( "title", "Show All Items" )
.insertAfter( input )
.button({
icons: {
primary: "ui-icon-triangle-1-s"
},
text: false
})
.removeClass( "ui-corner-all" )
.addClass( "ui-corner-right ui-button-icon" )
.click(function() {
// close if already visible
if ( $(this).prev().autocomplete( "widget" ).is( ":visible" ) ) {
$(this).prev().autocomplete( "close" );
return;
}
// work around a bug (likely same cause as #5265)
$( this ).blur();
// pass empty string as value to search for, displaying all results
$(this).prev().autocomplete( "search", "" );
$(this).prev().focus();
});
},
destroy: function() {
this.input.remove();
this.button.remove();
this.element.show();
$.Widget.prototype.destroy.call( this );
}
});
})( jQuery );
$( "#combobox" ).combobox();
$( "#toggle" ).click(function() {
$( "#combobox" ).toggle();
});
});
Binding newly added element in clone method
var selectedRow = $('#contactGroup'+rowId);
var clonedRow = selectedRow.clone();
selectedRow.after(clonedRow);
$(('#contactGroup'+rowId) .editableCombobox).autocomplete( "search", "" );

You can't use 'live' on autocomplete, as far as I know.
Place your autocomplete options in a function that expects the field as parameter, on which you want to apply the autocomplete method.
function enable_autocomplete(InputField) {
$(InputField).autocomplete({
source: availableTags
});
}
Then, after cloning the field, call this function with the cloned field.
enable_autocomplete(ClonedField);
I've written you an easy example, what makes it much easier to understand what I am trying to say ;-)
Edit: I've written another example based on the combobox example from jQueryUIs website.

You can use 'live', although these days you should be using the 'on' method.
See this thread for working examples (including one that uses 'on' if you drill down in to some of the hidden answers):
Bind jQuery UI autocomplete using .live()
Cheers
Matt

Related

WooCommerce custom checkout.js - Order being placed with billing address as shipping address

I'm using a custom WooCommerce checkout.js file for a plugin I'm creating but I'm having an issue whereby the billing address is getting saved as the shipping address when the order is placed.
Here is the custom 'checkout.js' code:
/* global wc_checkout_params */
jQuery( function( $ ) {
// wc_checkout_params is required to continue, ensure the object exists
if ( typeof wc_checkout_params === 'undefined' ) {
return false;
}
console.log('Start');
$.blockUI.defaults.overlayCSS.cursor = 'default';
var wc_checkout_form = {
updateTimer: false,
dirtyInput: false,
xhr: false,
$order_review: $( '#order_review' ),
$checkout_form: $( 'form.checkout' ),
init: function() {
console.log('Init');
$( document.body ).bind( 'updated_checkout', this.updated_checkout );
$( document.body ).bind( 'update_checkout', this.update_checkout );
$( document.body ).bind( 'init_checkout', this.init_checkout );
$( document.body ).bind( 'country_to_state_changed', this.upgrade_state_fields );
$( document.body ).on( 'change', 'select.country_to_state, input.country_to_state', this.upgrade_state_fields );
$( '.back-to-checkout' ).bind( 'click', this.close_drawer );
// Payment methods
this.$checkout_form.on( 'click', 'input[name="payment_method"]', this.payment_method_selected );
if ( $( document.body ).hasClass( 'woocommerce-order-pay' ) ) {
this.$order_review.on( 'click', 'input[name="payment_method"]', this.payment_method_selected );
}
$( 'button.details-next-button' ).bind( 'click', this.prevent_checkout );
// Form submission
$( document.body ).on( 'click', '#place_order', this.submit );
this.$checkout_form.on( 'submit', this.submit );
// Inline validation
this.$checkout_form.on( 'blur change', '.input-text, select, input:checkbox', this.validate_field );
// Manual trigger
this.$checkout_form.on( 'update', this.trigger_update_checkout );
// Inputs/selects which update totals
this.$checkout_form.on( 'change', 'select.shipping_method, input[name^="shipping_method"], #ship-to-different-address input, .update_totals_on_change select, .update_totals_on_change input[type="radio"]', this.trigger_update_checkout );
this.$checkout_form.on( 'change', '.address-field select', this.input_changed );
this.$checkout_form.on( 'change', '.address-field input.input-text, .update_totals_on_change input.input-text', this.maybe_input_changed );
this.$checkout_form.on( 'change keydown', '.address-field input.input-text, .update_totals_on_change input.input-text', this.queue_update_checkout );
// Address fields
this.$checkout_form.on( 'change', '#ship-to-different-address input.mdl-switch__input', this.ship_to_different_address );
this.$checkout_form.on( 'change', '#order_notes input.mdl-switch__input', this.order_notes );
// Trigger events
this.$checkout_form.find( '#ship-to-different-address input' ).change();
this.init_payment_methods();
// Update on page load
if ( wc_checkout_params.is_checkout === '1' ) {
$( document.body ).trigger( 'init_checkout' );
}
if ( wc_checkout_params.option_guest_checkout === 'yes' ) {
$( 'input#createaccount' ).change( this.toggle_create_account ).change();
} else {
$( 'div.create-account' ).show();
}
jQuery('.woocommerce-message').remove();
},
init_payment_methods: function( selectedPaymentMethod ) {
console.log('Init payment_methods');
var $payment_methods = $( '.woocommerce-checkout' ).find( 'input[name="payment_method"]' );
// If there is one method, we can hide the radio input
if ( 1 === $payment_methods.length ) {
$payment_methods.eq(0).hide();
}
// If there was a previously selected method, check that one.
if ( selectedPaymentMethod ) {
$( '#' + selectedPaymentMethod ).prop( 'checked', true );
}
// If there are none selected, select the first.
if ( 0 === $payment_methods.filter( ':checked' ).length ) {
$payment_methods.eq(0).prop( 'checked', true );
}
// Trigger click event for selected method
$payment_methods.filter( ':checked' ).eq(0).trigger( 'click' );
wc_checkout_form.convert_payment_textinputs();
},
close_drawer: function() {
console.log('close_drawer');
jQuery('.mdl-layout__obfuscator.is-visible').click();
},
updated_checkout: function() {
console.log('updated_checkout');
jQuery('.mdl-layout__drawer .shipping input[type=radio]').each(function() {
var name = $(this).attr('name');
var id = $(this).attr('id');
$(this).attr('name','review_' + name);
$(this).attr('id','review_' + id);
});
componentHandler.upgradeDom();
window.setTimeout(function() {
jQuery('.mdl-textfield').each(function() {
if (!jQuery(this).is('.validate-required')) {
jQuery(this).removeClass('is-invalid');
}
if (jQuery(this).find('.mdl-textfield__input').val() != '') {
jQuery(this).addClass('is-dirty');
}
});
},10);
if (jQuery('.woocommerce-error').length > 0) {
var message ='';
jQuery('.woocommerce-error').find('li').each(function() {
message+= jQuery(this).text();
});
jQuery('.woocommerce-error').remove();
var snackbarContainer = document.querySelector('#error-snackbar');
var data = {
message: message,
timeout: 5000
};
snackbarContainer.MaterialSnackbar.showSnackbar(data);
}
jQuery('.woocommerce-message').remove();
},
convert_payment_textinputs: function() {
console.log('convert_payment_textinputs');
jQuery('.payment_box').find('input[type=text],input[type=tel],input[type=email],input[type=date],input[type=password]').each(function() {
if (jQuery(this).parent().is('[data-upgraded]') || jQuery(this).parent().find('input[type=text],input[type=tel],input[type=email],input[type=date],input[type=password]').length > 1) {
return;
}
jQuery(this).parent().addClass('mdl-textfield mdl-js-textfield mdl-textfield--floating-label');
jQuery(this).addClass('mdl-textfield__input');
jQuery(this).parent().find('label').addClass('mdl-textfield__label');
componentHandler.upgradeElement(jQuery(this).parent()[0]);
});
},
upgrade_state_fields: function() {
console.log('upgrade_state_fields');
$('#billing_state,#shipping_state').addClass('mdl-textfield__input');
$('#billing_state,#shipping_state,#billing_country, #shipping_country').each(function() {
jQuery(this).parent().removeAttr('data-upgraded');
jQuery(this).find('option[value=""]').text('');
componentHandler.upgradeElement(jQuery(this).parent()[0]);
});
window.setTimeout(function() {
jQuery('.mdl-textfield').each(function() { jQuery(this).find('.mdl-textfield__input').each(function() {
if (jQuery(this).val() && jQuery(this).val() != '') {
jQuery(this).parent().addClass('is-dirty');
} else {
jQuery(this).parent().removeClass('is-dirty');
}
if (jQuery(this).attr('placeholder') && jQuery(this).attr('placeholder') != '') {
jQuery(this).parent().addClass('has-placeholder');
} else {
jQuery(this).parent().removeClass('has-placeholder');
}
}); });
},100);
},
get_payment_method: function() {
console.log('get_payment_method');
return wc_checkout_form.$checkout_form.find( 'input[name="payment_method"]:checked' ).val();
},
payment_method_selected: function() {
console.log('payment_method_selected');
if ( $( '.payment_methods input.input-radio' ).length > 1 ) {
var target_payment_box = $( 'div.payment_box.' + $( this ).attr( 'ID' ) );
if ( $( this ).is( ':checked' ) && ! target_payment_box.is( ':visible' ) ) {
$( 'div.payment_box' ).filter( ':visible' ).slideUp( 250 );
if ( $( this ).is( ':checked' ) ) {
$( 'div.payment_box.' + $( this ).attr( 'ID' ) ).slideDown( 250 );
}
}
} else {
$( 'div.payment_box' ).show();
}
if ( $( this ).data( 'order_button_text' ) ) {
$( '#place_order' ).val( $( this ).data( 'order_button_text' ) );
} else {
$( '#place_order' ).val( $( '#place_order' ).data( 'value' ) );
}
},
toggle_create_account: function() {
console.log('toggle_create_account');
$( 'div.create-account' ).hide();
if ( $( this ).is( ':checked' ) ) {
$( 'div.create-account' ).slideDown();
}
},
init_checkout: function() {
console.log('init_checkout');
$( '#billing_country, #shipping_country, .country_to_state' ).change();
$( document.body ).trigger( 'update_checkout' );
},
maybe_input_changed: function( e ) {
console.log('maybe_input_changed');
if ( wc_checkout_form.dirtyInput ) {
wc_checkout_form.input_changed( e );
}
},
input_changed: function( e ) {
console.log('input_changed');
wc_checkout_form.dirtyInput = e.target;
wc_checkout_form.maybe_update_checkout();
},
queue_update_checkout: function( e ) {
console.log('queue_update_checkout');
var code = e.keyCode || e.which || 0;
if ( code === 9 ) {
return true;
}
wc_checkout_form.dirtyInput = this;
wc_checkout_form.reset_update_checkout_timer();
wc_checkout_form.updateTimer = setTimeout( wc_checkout_form.maybe_update_checkout, '1000' );
},
trigger_update_checkout: function() {
console.log('trigger_update_checkout');
wc_checkout_form.reset_update_checkout_timer();
wc_checkout_form.dirtyInput = false;
$( document.body ).trigger( 'update_checkout' );
},
maybe_update_checkout: function() {
console.log('maybe_update_checkout');
var update_totals = true;
if ( $( wc_checkout_form.dirtyInput ).length ) {
var $required_inputs = $( wc_checkout_form.dirtyInput ).closest( 'div' ).find( '.address-field.validate-required' );
if ( $required_inputs.length ) {
$required_inputs.each( function() {
if ( $( this ).find( 'input.input-text' ).val() === '' ) {
update_totals = false;
}
});
}
}
if ( update_totals ) {
wc_checkout_form.trigger_update_checkout();
}
},
ship_to_different_address: function() {
console.log('ship_to_different_address');
if ( $( this ).is( ':checked' ) ) {
$( '#shipping_address_section' ).slideDown();
} else {
$( '#shipping_address_section' ).slideUp();
}
},
order_notes: function() {
console.log('order_notes');
if ( $( this ).is( ':checked' ) ) {
$( '#order_notes_section' ).slideDown();
} else {
$( '#order_notes_section' ).slideUp();
}
},
reset_update_checkout_timer: function() {
console.log('reset_update_checkout_timer');
clearTimeout( wc_checkout_form.updateTimer );
},
validate_field: function() {
console.log('validate_field');
var $this = $( this ),
$parent = $this.closest( '.form-row' ),
validated = true;
if ( $parent.is( '.validate-required' ) ) {
if ( 'checklox' === $this.attr( 'type' ) && ! $this.is( ':checked' ) ) {
$parent.removeClass( 'woocommerce-validated' ).addClass( 'woocommerce-invalid woocommerce-invalid-required-field' );
validated = false;
} else if ( $this.val() === '' ) {
$parent.removeClass( 'woocommerce-validated' ).addClass( 'woocommerce-invalid woocommerce-invalid-required-field' );
validated = false;
}
}
if ( $parent.is( '.validate-email' ) ) {
if ( $this.val() ) {
/* https://stackoverflow.com/questions/2855865/jquery-validate-e-mail-address-regex */
var pattern = new RegExp(/^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))#((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/i);
if ( ! pattern.test( $this.val() ) ) {
$parent.removeClass( 'woocommerce-validated' ).addClass( 'woocommerce-invalid woocommerce-invalid-email' );
validated = false;
}
}
}
if ( validated ) {
$parent.removeClass( 'woocommerce-invalid woocommerce-invalid-required-field' ).addClass( 'woocommerce-validated' );
}
},
update_checkout: function( event, args ) {
console.log('update_checkout');
// Small timeout to prevent multiple requests when several fields update at the same time
wc_checkout_form.reset_update_checkout_timer();
wc_checkout_form.updateTimer = setTimeout( wc_checkout_form.update_checkout_action, '5', args );
},
update_checkout_action: function( args ) {
console.log('update_checkout_action');
if ( wc_checkout_form.xhr ) {
wc_checkout_form.xhr.abort();
}
if ( $( 'form.checkout' ).length === 0 ) {
return;
}
args = typeof args !== 'undefined' ? args : {
update_shipping_method: true
};
var country = $( '#billing_country' ).val(),
state = $( '#billing_state' ).val(),
postcode = $( 'input#billing_postcode' ).val(),
city = $( '#billing_city' ).val(),
address = $( 'input#billing_address_1' ).val(),
address_2 = $( 'input#billing_address_2' ).val(),
s_country = country,
s_state = state,
s_postcode = postcode,
s_city = city,
s_address = address,
s_address_2 = address_2;
has_full_address = true;
if ( $( '#ship-to-different-address' ).find( 'input' ).is( ':checked' ) ) {
s_country = $( '#shipping_country' ).val();
s_state = $( '#shipping_state' ).val();
s_postcode = $( 'input#shipping_postcode' ).val();
s_city = $( '#shipping_city' ).val();
s_address = $( 'input#shipping_address_1' ).val();
s_address_2 = $( 'input#shipping_address_2' ).val();
}
var data = {
security: wc_checkout_params.update_order_review_nonce,
payment_method: wc_checkout_form.get_payment_method(),
country: country,
state: state,
postcode: postcode,
city: city,
address: address,
address_2: address_2,
s_country: s_country,
s_state: s_state,
s_postcode: s_postcode,
s_city: s_city,
s_address: s_address,
s_address_2: s_address_2,
has_full_address: has_full_address,
post_data: $( 'form.checkout' ).serialize()
};
console.log(data);
if ( false !== args.update_shipping_method ) {
var shipping_methods = {};
$( 'select.shipping_method, input[name^="shipping_method"][type="radio"]:checked, input[name^="shipping_method"][type="hidden"]' ).each( function() {
shipping_methods[ $( this ).data( 'index' ) ] = $( this ).val();
} );
data.shipping_method = shipping_methods;
}
$( '.woocommerce-checkout-payment, .woocommerce-checkout-review-order-table' ).block({
message: null,
overlayCSS: {
background: '#fff',
opacity: 0.6
}
});
wc_checkout_form.xhr = $.ajax({
type: 'POST',
url: wc_checkout_params.wc_ajax_url.toString().replace( '%%endpoint%%', 'update_order_review' ),
data: data,
success: function( data ) {
var selectedPaymentMethod = $( '.woocommerce-checkout input[name="payment_method"]:checked' ).attr( 'id' );
// Reload the page if requested
if ( 'true' === data.reload ) {
window.location.reload();
return;
}
// Remove any notices added previously
$( '.woocommerce-NoticeGroup-updateOrderReview' ).remove();
var termsCheckBoxChecked = $( '#terms' ).prop( 'checked' );
window.fragmentss = data.fragments;
// Always update the fragments
if ( data && data.fragments ) {
$.each( data.fragments, function ( key, value ) {
$( key ).replaceWith( value );
$( key ).unblock();
} );
}
// Recheck the terms and conditions box, if needed
if ( termsCheckBoxChecked ) {
$( '#terms' ).prop( 'checked', true );
}
// Check for error
if ( 'failure' === data.result ) {
var $form = $( 'form.checkout' );
// Remove notices from all sources
$( '.woocommerce-error, .woocommerce-message' ).remove();
// Add new errors returned by this event
if ( data.messages ) {
$form.prepend( '<div class="woocommerce-NoticeGroup-updateOrderReview">' + data.messages + '</div>' );
} else {
$form.prepend( data );
}
// Lose focus for all fields
$form.find( '.input-text, select, input:checkbox' ).blur();
// Scroll to top
$( 'html, body' ).animate( {
scrollTop: ( $( 'form.checkout' ).offset().top - 100 )
}, 1000 );
}
// Re-init methods
wc_checkout_form.init_payment_methods( selectedPaymentMethod );
// Fire updated_checkout e
$( document.body ).trigger( 'updated_checkout', [ data ] );
}
});
},
prevent_checkout: function(e) {
console.log('prevent_checkout');
console.log('clickprevent');
e.preventDefault();
},
submit: function(e) {
console.log('submit');
e.preventDefault();
wc_checkout_form.reset_update_checkout_timer();
var $form = $( wc_checkout_form.$checkout_form );
console.log('Form:' + $form);
if ( $form.is( '.processing' ) ) {
return false;
}
$( document )
.on(
'stripeError',
wc_checkout_form.updated_checkout
)
.on(
'checkout_error',
wc_checkout_form.updated_checkout
);
// Trigger a handler to let gateways manipulate the checkout if needed
if ( $form.triggerHandler( 'checkout_place_order' ) !== false && $form.triggerHandler( 'checkout_place_order_' + wc_checkout_form.get_payment_method() ) !== false ) {
$form.addClass( 'processing' );
var form_data = $form.data();
console.log ('Form Data:' + form_data );
if ( 1 !== form_data['blockUI.isBlocked'] ) {
$form.block({
message: null,
overlayCSS: {
background: '#fff',
opacity: 0.6
}
});
}
// ajaxSetup is global, but we use it to ensure JSON is valid once returned.
$.ajaxSetup( {
dataFilter: function( raw_response, dataType ) {
// We only want to work with JSON
if ( 'json' !== dataType ) {
return raw_response;
}
try {
// Check for valid JSON
var data = $.parseJSON( raw_response );
if ( data && 'object' === typeof data ) {
// Valid - return it so it can be parsed by Ajax handler
return raw_response;
}
} catch ( e ) {
// Attempt to fix the malformed JSON
var valid_json = raw_response.match( /{"result.*"}/ );
if ( null === valid_json ) {
console.log( 'Unable to fix malformed JSON' );
} else {
console.log( 'Fixed malformed JSON. Original:' );
console.log( raw_response );
raw_response = valid_json[0];
}
}
return raw_response;
}
} );
console.log($form.serialize());
alert($form.serialize());
$.ajax({
type: 'POST',
url: wc_checkout_params.checkout_url,
data: $form.serialize(),
dataType: 'json',
This is the '$form.serialize()' data that is getting sent by the AJAX request:
billing_first_name=Testname&billing_last_name=Testlastname&billing_phone=0800000000&billing_email=test%40wpmad.com&billing_country=GB&billing_address_1=4+Test+Street&billing_address_2=&billing_city=Test+City&billing_state=Worcestershire&billing_postcode=DY11+1JR&shipping_first_name=Testname&shipping_last_name=Testlastname&shipping_company=&shipping_country=GB&shipping_address_1=99+Test+Street&shipping_address_2=&shipping_city=Worcester&shipping_state=Worcestershire&shipping_postcode=WR1+2DS&order_comments=&shipping_method%5B0%5D=free_shipping%3A1&terms=on&terms-field=1&_wpnonce=34d56c864b&_wp_http_referer=%2F%3Fwc-ajax%3Dupdate_order_review
As above, the order is placed, but the shipping address is replaced with the billing address on the order confirmation page and within the WooCommerce orders in the admin.
Any ideas why? Any help would be greatly appreciated!
Problem solved.
The issue was being caused as the checkbox in the WooCommerce checkout had been changed to a Google Material design checkbox/switch and was not setting the value of the checkbox to '1'.
Effectively, the $form.serialize() data didn't contain the ship_to_different_address=1 that is required in the WooCommerce AJAX request.

Jquery combobox autocomplete

Need some help.
Can I set the custom value to the combobox, the value which is not present in the list.
It means like my own value which is not listed in the list
Here is the code.
(function( $ ) {
$.widget( "ui.combobox", {
_create: function() {
this.wrapper = $( "<span>" )
.addClass( "custom-combobox" )
.insertAfter( this.element )
.attr('id', this.element[0].id+"_combobox");
this.element.hide();
this._createAutocomplete();
this._createShowAllButton();
},
_createAutocomplete: function() {
var selected = this.element.children(":selected");
this.input = $( "<input>" )
.appendTo( this.wrapper )
.attr( "title", '<fmt:message key="page.claim.personalclaimnotification.injury.select_info" />' )
.val(selected.text())
.css({
color: function( index, value ) {
if (this.value == '<fmt:message key="page.claim.search.object.name" />') {
return "#777";
}
},
fontStyle: function( index, value ) {
if (this.value == '<fmt:message key="page.claim.search.object.name" />') {
return "italic";
}
},
width: "286px"
})
.attr("maxlength", 256)
.addClass( "custom-combobox-input ui-widget ui-widget-content ui-state-default ui-corner-left" )
.autocomplete({
delay: 0,
minLength: 3,
source: $.proxy( this, "_source" )
})
// executes when user selects illness from list
this._on( this.input, {
autocompleteselect: function( event, ui ) {
ui.item.option.selected = true;
this._trigger( "select", event, {
item: ui.item.option
});
},
autocompletechange: "_addIfInvalid"
});
}, /* _createAutocomplete close */
_createShowAllButton: function() {
var input = this.input,
wasOpen = false;
$( "<a>" )
.attr( "tabIndex", -1 )
.appendTo( this.wrapper )
.attr( "title", '<fmt:message key="page.claim.personalclaimnotification.injury.select_info" />' )
.button({
icons: {
primary: "ui-icon-triangle-1-s"
},
text: false
})
.removeClass( "ui-corner-all" )
.addClass( "custom-combobox-toggle ui-corner-right" )
.mousedown(function() {
wasOpen = input.autocomplete( "widget" ).is( ":visible" );
})
.click(function() {
// Close if already visible
if ( wasOpen ) {
return;
}
// Pass triple spaces as value to search for, displaying all results (each has triple spaces at the end)
input.autocomplete( "search", " " );
});
}, /* _createShowAllButton close */
_source: function( request, response ) {
var matcher = new RegExp( $.ui.autocomplete.escapeRegex(request.term), "i" );
response( this.element.children( "option" ).map(function() {
var text = $( this ).text();
if ( this.value && ( !request.term || matcher.test(text) ) )
return {
label: text,
value: text,
option: this
};
}) );
},
_addIfInvalid: function( event, ui ) {
// Selected an item, nothing to do
if ( ui.item ) {
return;
}
// Search for a match (case-insensitive)
var value = this.input.val(),
valueLowerCase = value.toLowerCase(),
valid = false;
this.element.children( "option" ).each(function() {
if ( $( this ).text().toLowerCase() === valueLowerCase ) {
this.selected = valid = true;
return false;
}
});
// Found a match, nothing to do
if ( valid ) {
return;
}
alert("value "+ value +" this.element "+ this.element[0].id );
// Remove invalid value
this.input
.val(value)
.attr( "title", value + " didn't match any item" )
.tooltip( "open" );
//this.element.val(value);
//this.input.val(value);
$('select').val(value);
this._delay(function() {
this.input.tooltip( "close" ).attr( "title", "" );
}, 2500 );
this.input.autocomplete( "instance" ).term = "";
},
_destroy: function() {
this.wrapper.remove();
this.element.show();
}
}); /* widget close */
})( jQuery ); /* function close */
$(function() {
$( ".objectComboBox" ).combobox();
});
If the element is not listed in the drop down, that user entered element should be taken as the value and should stay in the combobox field.
Adding the field
I made a script for you. May be it will work for you.
<select id="combobox" >
<option>abc</option>
<option>deg</option>
<option>gcc</option>
</select>
<input type="text" id="addfieldtoddl" /><input type="button" value="add" id="add" onclick="addfieldtoddl()" />
<script>
$(document).ready(function(){
$("#combobox").combobox();
});
function addfieldtoddl() {
var YourValue = $("#addfieldtoddl").val();
$('#combobox').append('<option val="'+ YourValue +'">'+ YourValue +'</option>');
$("#combobox").combobox();
}
</script>
here is fiddle link http://jsfiddle.net/RDd3A/506/
Trying to help...!!!

JQuery doesn't work after the db loading by ajax

guys.
I'm trying develope a webpage which has draggable function.
I found a jQuery theme exactly I wanted, and I'm using that code.
I didnt modify a lot, but just added code that loads database using ajax and mysql.
After loading db, the draggable function doesnt work.
I think it's about the order of running the function.
so I used setTimeout on the function that has draggable function and it worked.
But the problem is that I have to load database every 5 seconds, so I cant keep using setTimeout for the draggable function everytime I load db.
Is there any solutions that I can fix this problem?
Here is the code that I use
main.php
$(document).ready(function database(){
if(window.XMLHttpRequest){
// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp = new XMLHttpRequest();
} else{
// code for IE6, IE5
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.onreadystatechange = function(){
if(xmlhttp.readyState == 4 && xmlhttp.status == 200){
document.getElementById("gallery").innerHTML = xmlhttp.responseText;
}
};
xmlhttp.open("GET","db.php",true);
xmlhttp.send();
init();
});
setTimeout(function (){
var $gallery = $("#gallery");
var $gallery2 = $("#gallery2");
var $trash = $("#trash");
var $trash2 = $("#trash2");
$("li",$gallery).draggable({
cancel: "a.ui-icon",revert:"invalid",containment:"document",helper:"clone",cursor:"move"
});
$("li",$gallery2).draggable({
cancel: "a.ui-icon",revert:"invalid",containment:"document",helper:"clone",cursor:"move"
});
$trash.droppable({
accept: "#gallery > li",
classes: {
"ui-droppable-active": "ui-state-highlight"
},
drop: function( event, ui ) {
deleteImage( ui.draggable );
}
});
$trash2.droppable({
accept: "#gallery2 > li",
classes: {
"ui-droppable-active": "ui-state-highlight"
},
drop: function(event, ui){
deleteImage2(ui.draggable);
}
});
$gallery.droppable({
accept: "#trash li",
classes: {
"ui-droppable-active":"custom-state-active"
},
drop: function(event, ui){
recycleImage(ui.draggable);
}
});
$gallery2.droppable({
accept: "#trash2 li",
classes: {
"ui-droppable-active":"custom-state-active"
},
drop: function(event, ui){
recycleImage2(ui.draggable);
}
});
var recycle_icon = "<a href='link/to/recycle/script/when/we/have/js/off' title='Recycle this image' class='ui-icon ui-icon-refresh'>Recycle image</a>";
function deleteImage( $item ) {
$item.fadeOut(function() {
var $list = $( "ul", $trash ).length ?
$( "ul", $trash ) :
$( "<ul class='gallery ui-helper-reset'/>" ).appendTo( $trash );
$item.find( "a.ui-icon-trash" ).remove();
$item.append( recycle_icon ).appendTo( $list ).fadeIn(function() {
$item
.animate({ width: "100px" })
.find( "img" )
.animate({ height: "150px" });
});
});
}
function deleteImage2( $item ) {
$item.fadeOut(function() {
var $list = $( "ul", $trash2 ).length ?
$( "ul", $trash2 ) :
$( "<ul class='gallery ui-helper-reset'/>" ).appendTo( $trash2 );
$item.find( "a.ui-icon-trash" ).remove();
$item.append( recycle_icon ).appendTo( $list ).fadeIn(function() {
$item
.animate({ width: "100px" })
.find( "img" )
.animate({ height: "150px" });
});
});
}
var trash_icon = "<a href='link/to/trash/script/when/we/have/js/off' title='Delete this image' class='ui-icon ui-icon-trash'>Delete image</a>";
function recycleImage( $item ) {
$item.fadeOut(function() {
$item
.find( "a.ui-icon-refresh" )
.remove()
.end()
.css( "width", "96px")
.append( trash_icon )
.find( "img" )
.css( "height", "72px" )
.end()
.appendTo( $gallery )
.fadeIn();
});
}
function recycleImage2( $item ) {
$item.fadeOut(function() {
$item
.find( "a.ui-icon-refresh" )
.remove()
.end()
.css( "width", "96px")
.append( trash_icon )
.find( "img" )
.css( "height", "72px" )
.end()
.appendTo( $gallery2 )
.fadeIn();
});
}
function viewLargerImage( $link ) {
var src = $link.attr( "href" ),
title = $link.siblings( "img" ).attr( "alt" ),
$modal = $( "img[src$='" + src + "']" );
if ( $modal.length ) {
$modal.dialog( "open" );
} else {
var img = $( "<img alt='" + title + "' width='384' height='288' style='display: none; padding: 8px;' />" )
.attr( "src", src ).appendTo( "body" );
setTimeout(function() {
img.dialog({
title: title,
width: 400,
modal: true
});
}, 1 );
}
}
$( "ul.gallery > li" ).on( "click", function( event ) {
var $item = $( this );
var $target = $( event.target );
if ( $target.is( "a.ui-icon-trash" ) ) {
deleteImage( $item );
} else if ( $target.is( "a.ui-icon-zoomin" ) ) {
viewLargerImage( $target );
} else if ( $target.is( "a.ui-icon-refresh" ) ) {
recycleImage( $item );
}
return false;
});
$( "ul.gallery2 > li" ).on( "click", function( event ) {
var $item = $( this );
var $target = $( event.target );
if ( $target.is( "a.ui-icon-trash" ) ) {
deleteImage2( $item );
} else if ( $target.is( "a.ui-icon-zoomin" ) ) {
viewLargerImage( $target );
} else if ( $target.is( "a.ui-icon-refresh" ) ) {
recycleImage2( $item );
}
return false;
});
}, 1000);
db.php
<?php
$host = "localhost"; // 자신의 mysql
$DB_name = "master"; // 데이터베이스 이름
$user = "root"; // 기본 사용자.
$password = "0000"; // apm 기본 암호
$conn = mysqli_connect($host, $user, $password, $DB_name);
if(!$conn){
echo "fail!\n";
die('Could not connect: ' . mysqli_error($con));
}
//else
$sql = "select * from sensorlist";
$result = mysqli_query($conn,$sql);
$rowcnt = mysqli_num_rows($result);
$filed_name = array('S_Ultrasonic','S_IR','S_Humidity','S_Temperature','S_Heatindex','S_Light','S_Gas'); //센서 필드명 집합
if($rowcnt == 1){ //right (data가 1행만 들어있는 게 맞는 지 체크)
while($row = mysqli_fetch_array($result)){
for($i=0;$i<count($filed_name);$i++){
if($row[$filed_name[$i]] != NULL){
echo "<li class='ui-widget-content ui-corner-tr ui-draggable ui-draggable-handle'>";
echo "<h5 class='ui-widget-header'>" . $filed_name[$i] . "</h5>";
echo "<a href='images/high_tatras.jpg' title='View larger image' class='ui-icon ui-icon-zoomin'> View larger</a>";
echo "<a href='link/to/trash/script/when/we/have/js/off' title='Delete this image' class='ui-icon ui-icon-trash'>Delete image</a></li>";
}
}
}
//echo "No sensor";
} else if($rowcnt == 0) { //data가 하나도 없으면 없다고 출력
//없다고 출력
echo "No sensor";
} else { //이도 저도 아니면 땡!
//db 에러 출력
echo "No sensor";
}
mysqli_close($conn);
?>
Delegate you event if you have dynamically added elements, reinitialize your draggable plugin after the ajax is complete (do all your logic in the if of the onreadystatechange event)

JQuery autocomplete suggestions not sorted [duplicate]

This question already has answers here:
Sort the values in the jQuery Autocomplete
(5 answers)
Closed 7 years ago.
I am having a problem with sorting an auto-complete result with JQuery UI.
from the image above when a user decides to search for garlic and starts by entering "g" it should show "garlic" first and not egg first.
See my code. The ingredients in ingredient.txt at a point is sorted alphabetically so i think that is where the problem is..
How do I go about this
$(function() {
jQuery.get('ingredients.txt', function(data) {
var availableTags = data.split(', ');
availableTags = availableTags.sort();
//console.log("The available Tag are "+ availableTags);
function split( val ) {
return val.split(",");
}
function extractLast( term ) {
return split( term ).pop().sort();
}
// don't navigate away from the field on tab when selecting an item
$( "#tags" ).bind( "keydown", function( event ) {
if ( event.keyCode === $.ui.keyCode.TAB && $( this ).autocomplete( "instance" ).menu.active ) {
event.preventDefault();
}
}).autocomplete({
minLength: 0,
source: function( request, response ) {
// delegate back to autocomplete, but extract the last term
response( $.ui.autocomplete.filter(
availableTags, extractLast( request.term ) ) );
},
focus: function() {
// prevent value inserted on focus
return false;
},
select: function( event, ui ) {
var terms = split( this.value );
// remove the current input
terms.pop();
// add the selected item
// var projectDiv = '<div class="projectBody" id="selectedItems">'+ ui.item.value +'</div>';
terms.push( ui.item.value );
for(var i = 0; i < terms.length; i++) {
var elements = terms[i];
}
// add placeholder to get the comma-and-space at the end
terms.push( "" );
//$("#tags").val().wrap( "<div class='new'>nn</div>" );
this.value = terms.join( "," );
return false;
}
});
});
});
After much looking this is what i came up with.
<script type="text/javascript">
$(function() {
jQuery.get('ingredients.txt', function(data) {
var availableTags = data.split(', ');
availableTags = availableTags.sort();
//console.log("The available Tag are "+ availableTags);
function split( val ) {
return val.split(", ");
}
function extractLast( term ) {
return split( term ).pop();
}
$( "#tags" )
// don't navigate away from the field on tab when selecting an item
.bind( "keydown", function( event ) {
if ( event.keyCode === $.ui.keyCode.TAB &&
$( this ).autocomplete( "instance" ).menu.active ) {
event.preventDefault();
}
})
.autocomplete({
minLength: 0,
source: function( request, response ) {
var term = $.ui.autocomplete.escapeRegex(extractLast(request.term))
// Create two regular expressions, one to find suggestions starting with the user's input:
, startsWithMatcher = new RegExp("^" + term, "i")
, startsWith = $.grep(availableTags, function(value) {
return startsWithMatcher.test(value.label || value.value || value);
})
// ... And another to find suggestions that just contain the user's input:
, containsMatcher = new RegExp(term, "i")
, contains = $.grep(availableTags, function (value) {
return $.inArray(value, startsWith) < 0 &&
containsMatcher.test(value.label || value.value || value);
});
// Supply the widget with an array containing the suggestions that start with the user's input,
// followed by those that just contain the user's input.
response(startsWith.concat(contains));
},
focus: function() {
// prevent value inserted on focus
return false;
},
select: function( event, ui ) {
var terms = split( this.value );
// remove the current input
terms.pop();
// add the selected item
// var projectDiv = '<div class="projectBody" id="selectedItems">'+ ui.item.value +'</div>';
terms.push( ui.item.value );
for(var i = 0; i < terms.length; i++)
{
var elements = terms[i];
}
console.log('<div class="projectBody" id="selectedItems">'+ ui.item.value +'</div>');
$("#selectedItems").css("backgroundColor", "blue");
// add placeholder to get the comma-and-space at the end
terms.push( "" );
this.value = terms.join( "," );
return false;
}
});
});
});
</script>

Problem using jquery ui combobox

I have a jquery combobox. When user selects an product it redirects user to product info page. Unfortunately it does not work as expected. I used a normal select it works great.
(function( $ ) {
$.widget( "ui.combobox", {
_create: function() {
var self = this,
select = this.element.hide(),
selected = select.children( ":selected" ),
value = selected.val() ? selected.text() : "";
var input = $( "<input>" )
.insertAfter( select )
.val( value )
.autocomplete({
delay: 0,
minLength: 0,
source: function( request, response ) {
var matcher = new RegExp( $.ui.autocomplete.escapeRegex(request.term), "i" );
response( select.children( "option" ).map(function() {
var text = $( this ).text();
if ( this.value && ( !request.term || matcher.test(text) ) )
return {
label: text.replace(
new RegExp(
"(?![^&;]+;)(?!<[^<>]*)(" +
$.ui.autocomplete.escapeRegex(request.term) +
")(?![^<>]*>)(?![^&;]+;)", "gi"
), "<strong>$1</strong>" ),
value: text,
option: this
};
}) );
},
select: function( event, ui ) {
ui.item.option.selected = true;
self._trigger( "selected", event, {
item: ui.item.option
});
},
change: function( event, ui ) {
if ( !ui.item ) {
var matcher = new RegExp( "^" + $.ui.autocomplete.escapeRegex( $(this).val() ) + "$", "i" ),
valid = false;
select.children( "option" ).each(function() {
if ( this.value.match( matcher ) ) {
this.selected = valid = true;
return false;
}
});
if ( !valid ) {
// remove invalid value, as it didn't match anything
$( this ).val( "" );
select.val( "" );
return false;
}
}
}
})
.addClass( "ui-widget ui-widget-content ui-corner-left" );
input.data( "autocomplete" )._renderItem = function( ul, item ) {
return $( "<li></li>" )
.data( "item.autocomplete", item )
.append( "<a>" + item.label + "</a>" )
.appendTo( ul );
};
$( "<button> </button>" )
.attr( "tabIndex", -1 )
.attr( "title", "Show All Items" )
.insertAfter( input )
.button({
icons: {
primary: "ui-icon-triangle-1-s"
},
text: false
})
.removeClass( "ui-corner-all" )
.addClass( "ui-corner-right ui-button-icon" )
.click(function() {
// close if already visible
if ( input.autocomplete( "widget" ).is( ":visible" ) ) {
input.autocomplete( "close" );
return;
}
// pass empty string as value to search for, displaying all results
input.autocomplete( "search", "" );
input.focus();
});
}
});
})( jQuery );
$(function() {
$( "#combobox" ).combobox();
});
</script>
I have using change event, it does not work.
$(document).ready(function() {
$("#combobox").change(function() {
location.href = $(this).val();
});
});
I appreciate any help.
Insert between <head> and </head> tags:
<script type="text/javascript" src="js/jquery-ui-combobox.js"></script>
<script type="text/javascript">
$('selector').combobox();
$('selector').change(function(){ ... });
</script>
Code "jquery-ui-combobox.js":
$.widget( "ui.combobox", {
_create: function() {
var self = this,
select = this.element.hide(),
selected = select.children( ":selected" ),
value = selected.val() ? selected.text() : "";
var input = this.input = $( "<input />" )
.insertAfter( select )
.val( value )
.autocomplete({
delay: 0,
minLength: 0,
source: function( request, response ) {
var matcher = new RegExp( $.ui.autocomplete.escapeRegex(request.term), "i" );
response( select.children( "option" ).map(function() {
var text = $( this ).text();
if ( this.value && ( !request.term || matcher.test(text) ) )
return {
label: text.replace(
new RegExp(
"(?![^&;]+;)(?!<[^<>]*)(" +$.ui.autocomplete.escapeRegex(request.term) +")(?![^<>]*>)(?![^&;]+;)",
"gi"
),
"<strong>$1</strong>"
),
value: text,
option: this
};
}) );
},
select: function( event, ui ) {
ui.item.option.selected = true;
self._trigger( "selected", event, {
item: ui.item.option
});
$(select).change(); //Change COMBOBOX
},
change: function( event, ui ) {
if ( !ui.item ) {
var matcher = new RegExp( "^" + $.ui.autocomplete.escapeRegex( $(this).val() ) + "$", "i" ), valid = false;
select.children( "option" ).each(function() {
if ( $( this ).text().match( matcher ) ) {
this.selected = valid = true;
return false;
}
});
if ( !valid ) {
// remove invalid value, as it didn't match anything
$( this ).val( "" );
select.val( "" );
input.data( "autocomplete" ).term = "";
return false;
}
}
}
})
.addClass( "ui-widget ui-widget-content ui-corner-left" )
.css('margin', '0')
.css('padding', '0.48em 0 0.47em 0.45em');
input.data( "autocomplete" )._renderItem = function( ul, item ) {
return $( "<li></li>" )
.data( "item.autocomplete", item )
.append( "<a>" + item.label + "</a>" )
.appendTo( ul )
.css('cursor', 'pointer');
};
this.button = $( "<button> </button>" )
.attr( "tabIndex", -1 )
.attr( "title", "Show All Items" )
.insertAfter( input )
.button({
icons: {
primary: "ui-icon-triangle-1-s"
},
text: false
})
.removeClass( "ui-corner-all" )
.addClass( "ui-corner-right ui-button-icon" )
.css('margin-left','-1')
.css('padding','0.15em')
.click(function() {
// close if already visible
if ( input.autocomplete( "widget" ).is( ":visible" ) ) {
input.autocomplete( "close" );
return;
}
// pass empty string as value to search for, displaying all results
input.autocomplete( "search", "" );
input.focus();
$(select).click(); //Click COMBOBOX
});
},
destroy: function() {
this.input.remove();
this.button.remove();
this.element.show();
$.Widget.prototype.destroy.call( this );
}
});
The answer is quite simple. This worked for me.
$( ".selector" ).autocomplete({
select: function(event, ui) { ... }
});
You can directly specify in the following event like:
select: function( event, ui ) {
ui.item.option.selected = true;
location.href = select.val();
self._trigger( "selected", event, {
item: ui.item.option
});
}

Categories