I'm using the jQuery UI's "autocomplete" function on a search on my site. When you change a radio button from 'area search" to "name search" I want it to disable the autocomplete, and re-enable it when you switch back. However, when you disable the autocomplete it doesn't hide the dropdown, it just dims it to 20% opacity or so. Here's my javascript:
var allFields = new Array(<?php echo $allFields ?>);
$(document).ready(function() {
if ($("input[name='searchType']:checked").val() == 'areaCode') {
$("#siteSearch").autocomplete({
source: allFields,
minLength: 2
});
}
$("input[name='searchType']").change(function(){
if ($("input[name='searchType']:checked").val() == 'areaCode') {
$( "#siteSearch" ).autocomplete( "option", "disabled", false );
alert("enabled");
}
else {
$( "#siteSearch" ).autocomplete( "option", "disabled", true );
alert("disabled");
}
});
});
You can see it happening at http://crewinyourcode.com
First you have to chose an area code to search, and then you can see the issue.
EDIT:
I realize you have to choose an area code before you're given the option to switch search types. If you go to this URL you'll have both of them immediately:
http://crewinyourcode.com/search/choose-category/732/
Just added a CSS rule to display:hidden the autocomplete box. No biggie.
Related
Given the documentation for the search method for the Autocomplete Widget, I would expect a button that calls this method would display a box containing a list of available selections. Nothing happens.
I have the following code that creates the autocomplete widget on a text box:
$("#StateListCoolBox").autocomplete({
source: StateListCoolBoxTags,
focus: function( event, ui ) {
$("#StateListCoolBox").val(ui.item.label);
return false;
},
select: function( event, ui ) {
$("#StateListCoolBox").val(ui.item.label);
$("#StateListCoolBox-id").val(ui.item.value);
return false;
}
});
It works fine.
I have the following code attached to the button I want to display the list. It gets called but nothing happens:
function StateListCoolBox_dropDownClick() {
$("#StateListCoolBox").autocomplete("search", "" );
};
I have tested this with text in the corresponding textbox and with the textbox blank.
How do I get a button to behave like the button on a DropDown Combo, so that when clicked, the list of available selections is displayed?
If you look at the "View Source" for this: http://jqueryui.com/autocomplete/#combobox
You will see:
_createShowAllButton: function() {
var input = this.input,
wasOpen = false;
$( "<a>" )
.attr( "tabIndex", -1 )
.attr( "title", "Show All Items" )
.tooltip()
.appendTo( this.wrapper )
.button({
icons: {
primary: "ui-icon-triangle-1-s"
},
text: false
})
.removeClass( "ui-corner-all" )
.addClass( "custom-combobox-toggle ui-corner-right" )
.on( "mousedown", function() {
wasOpen = input.autocomplete( "widget" ).is( ":visible" );
})
.on( "click", function() {
input.trigger( "focus" );
// Close if already visible
if ( wasOpen ) {
return;
}
// Pass empty string as value to search for, displaying all results
input.autocomplete( "search", "" );
});
}
So this shows all the results by triggering focus event on the text field.
How do I get a button to behave like the button on a DropDown Combo, so that when clicked, the list of available selections is displayed?
I think this fits what you wanted to accomplish. So Try the following with minLength: 0:
function StateListCoolBox_dropDownClick() {
$("#StateListCoolBox").trigger("focus").autocomplete( "search", "" );
};
That said, there should be nothing wrong with your method:
Triggers a search event and invokes the data source if the event is not canceled. Can be used by a selectbox-like button to open the suggestions when clicked. When invoked with no parameters, the current input's value is used. Can be called with an empty string and minLength: 0 to display all items.
Your current code is simply missing: minLength: 0. Try both if you like.
So I've taken over a project that is almost ready to launch, a site where you can lease cars. I've uploaded the main part of the service here: http://erikblomqvist.se/junk/car/
Everything works smoothly except for the color changing function (the colored boxes under the headline Färgalternativ). It's supposed to update the price on the colors from brown to light gray (#4 - #8) – those are a bit more expensive, since they are in metallic.
In Chrome, this works as planned, but in Firefox, if I first select a metallic color, then a non-metallic, and THEN a the same metallic again, the price won't change back. It changes correctly the first time, but not the second time I click that metallic color.
In Safari, the price doesn't change at all (I'm guessing that if the Firefox problem gets solved, Safari gets solved as well).
The function is based on a data-name on the color boxes, that gets checked with this function:
$( '#car-colors .color' ).each(function() {
$( this ).on( 'click', function() {
selected_color = undefined;
var color_name = $( this ).data('name');
$( '#car-colors .color' ).not( this ).removeClass('selected');
$( this ).addClass('selected');
$( 'option', color_select ).each( function() {
if( $( this ).val() == color_name ) {
color_select.find( 'option' ).removeAttr('selected');
$( this ).attr('selected', 'selected');
}
});
$( '.selected-color-name' ).fadeIn();
$( '.selected-color-name span' ).html( color_name );
var selected_color = color_select.children(':selected');
checkSelectedColor(selected_color);
});
});
The variable color_select is defined as $( '#order-color-select' ).
The function checkSelectedColor is defined here:
function checkSelectedColor(selected_color) {
if( selected_color.data('is-metallic') == 'yes' ) {
color_checkbox.prop('checked', true);
} else {
color_checkbox.prop('checked', false);
}
color_input.val( selected_color.val() );
calculatePrice();
}
I've added stuff like selected_color = undefined to make sure that the variable is reseted, but after a color that has an <option data-is-metallic="yes"> (inside of #order-color-select) is selected a second time, it handles the value as "no" instead of "yes".
I can't get my head around on why this is, especially only in Firefox/Safari.
I've included the beautified version of the car functions here: http://pastebin.com/i5bup5rx
Appreciate any kind of help that could lead me in the right direction of getting this solved!
Thanks
I think the error is in setting the selected option in the select element using .attr().
Instead you can just set the value of the select element like
$('#car-colors .color').on('click', function() {
var color_name = $(this).data('name');
$('#car-colors .color').not(this).removeClass('selected');
$(this).addClass('selected');
$('#order-color-select').val(color_name);
$('.selected-color-name').fadeIn();
$('.selected-color-name span').html(color_name);
var selected_color = color_select.children(':selected');
checkSelectedColor(selected_color);
});
Links that are subject to display: none aren't in the default tabbing order. However, when they're revealed - e.g. CSS for a drop-down menu reveals a sub-menu when a parent link gains focus - they still aren't in the tabbing order. Presumably JavaScript is required, but simply setting tabindex="0" does nothing.
The problem here is that as soon as you tab off the "Top level page with child" link, the CSS is updated and the parent of the anchor becomes display:none before the anchor can receive focus. You will need to use JavaScript to solve this problem and delay the change in the CSS using a timeout until you can determine whether the loss of focus has resulted in the focus shifting to the child element.
Setting tabindex="0" when the parent is display:none will not help, display:none means that the content might as well not be in the document.
I've come up with a solution that basically works: http://codepen.io/gyrus/pen/waKjKv/ There seem to be some issues in IE, I'm working on that. But the general idea is:
Add a small delay before hiding the drop-down
Set a data attribute to flag whether any links inside the drop-down have focus, and check this before hiding
This is just the jQuery, check the pen for more:
jQuery( document ).ready( function( $ ) {
$( '.nav' ).on( 'mouseenter focusin', '.menu-level-0.menu-item-has-children', function( e ) {
var el = $( this );
// Show sub-menu
el.attr( 'aria-expanded', 'true' )
.find( '.sub-menu-wrapper' ).show();
}).on( 'mouseleave focusout', '.menu-level-0.menu-item-has-children', function( e ) {
var el = $( this );
// Only hide sub-menu after a short delay, so links get a chance to catch focus from tabbing
setTimeout( function() {
var smw = el.find( '.sub-menu-wrapper' );
if ( smw.attr( 'data-has-focus' ) !== 'true' ) {
el.attr( 'aria-expanded', 'false' );
smw.hide();
}
}, 100 );
}).on( 'focusin', '.sub-menu-wrapper', function( e ) {
var el = $( this );
el.attr( 'data-has-focus', 'true' );
}).on( 'focusout', '.sub-menu-wrapper', function( e ) {
var el = $( this );
el.attr( 'data-has-focus', 'false' );
// Hide sub-menu on the way out
el.hide().parents( '.menu-level-0' ).attr( 'aria-expanded', 'false' );
});
});
I am having a bit of trouble combining the HOVER and FOCUS events with jquery. This is what I had originally:
$("input,textarea").focus(function () {
$(this).parent().siblings('div.exp').removeClass('hide');
$(this).parent().siblings('div.exp').addClass('show');
});
$("input,textarea").blur(function (){
$(this).parent().siblings('div.exp').removeClass('show');
$(this).parent().siblings('div.exp').addClass('hide');
if ($(this).val().length <= 0) {
$(this).siblings('span.warning').removeClass('hide');
$(this).siblings('span.warning').addClass('show');}
else {
$(this).siblings('span.warning').removeClass('show');
$(this).siblings('span.warning').addClass('hide');
}
});
Basically, I have a user contact form with rows like the one below:
<div class="row">
<p><label>Your Name</label><input type="text" name="name" id="name" value=""/><span class="warning">Your name is missing</span></p>
<div class="exp">Who am I to address?</div>
</div>
The point of my Jquery code is to bring forth a hidden div (exp) when the user focuses any one input or textarea element as well as checking if the value of said input is not empty when unfocusing (blur) the element. (I haven't really gotten down to validation yet so checkin for the string length right now is just a temporary filler). Should the element have a string smaller or equal than 0, then span.warning is to be 'shown' to the user.
This is all working nicely.
Where I get stuck is the following:
I want to add in hover but without conflicting with focus. My desired final effect is this:
You hover any input or textarea and you get the div.exp to show up (exp is for explanation). You focus any input or area and the div.exp stays there, even if you go about hovering any other inputs or textareas. Should you hover an input that is already focused, nothing should happen.
So, in a nutshell, the focus and hover elements should work 'independently' so to speak. Not sure if I made myself clear but oh well, I tried =)
Cheers
G
Your code can be significantly shortened by using .hide() and .show() and chaining the events. I posted a demo here.
$(document).ready(function(e){
// hide all explanations and warnings
$('.exp, .warning').hide();
// add focus, blur and hover events to all inputs & textareas
$('input,textarea')
// if focused, show the explanation
.focus(function(){
// show explanation on focus (and add a class so the hover function knows not to hide it
$(this).addClass('focused').closest('.row')
.find('.exp').show()
.find('.warning').hide();
})
.blur(function(){
// hide explanation on blur
$(this).removeClass('focused').closest('.row').find('.exp').hide();
if ($(this).val().length < 1) {
// input is empty, show the warning
$(this).closest('.row').find('.warning').show();
} else {
// input is not empty, hide the warning... you might want to add the validation here
$(this).closest('.row').find('.warning').hide();
}
})
.hover(function(){
// show explanation when hovered
$(this).closest('.row').find('.exp').show();
},function(){
// hide explanation if the input is not focused
if ($(this).is(':not(.focused)')) $(this).closest('.row').find('.exp').hide();
})
});
You can set a flag to the input or textarea while it is focused to avoid conflict with your hover event. If the flag is set to true when the over or out event is fired, its code is not executed. The following code show the idea (I have not test it).
$("input,textarea").focus( function()
{
$(this).parent().siblings( 'div.exp' ).removeClass( 'hide' ).addClass( 'show' );
$(this).data( "hasFocus", true );
} );
$("input,textarea").blur(function()
{
$(this).parent().siblings( 'div.exp' ).removeClass( 'show' ).addClass( 'hide' );
if( $(this).val().length <= 0 )
$(this).siblings( 'span.warning' ).removeClass( 'hide' ).addClass( 'show' );
else
$(this).siblings( 'span.warning' ).removeClass( 'show' ).addClass( 'hide' );
$(this).data( "hasFocus", false );
});
$("input,textarea").hover( function()
{
// Over event
if( typeof $(this).data( "hasFocus" ) != undefined && !$(this).data( "hasFocus" ) )
$(this).parent().siblings( 'div.exp' ).removeClass( 'hide' ).addClass( 'show' );
},
function()
{
// Out event
if( typeof $(this).data( "hasFocus" ) != undefined && !$(this).data( "hasFocus" ) )
$(this).parent().siblings( 'div.exp' ).removeClass( 'show' ).addClass( 'hide' );
} );
I have added the Wordpress Core color picker (iris) to a widget I developed, but when you edit the color, there is no change triggered. As a result, the iframe (live preview) for the customizer does not update unless you trigger a change in another input field.
Javascript to iniitalize the color picker
var myOptions = {
// you can declare a default color here,
// or in the data-default-color attribute on the input
defaultColor: '#000',
// a callback to fire whenever the color changes to a valid color
change: function(event, ui){
},
// a callback to fire when the input is emptied or an invalid color
clear: function() {},
// hide the color picker controls on load
hide: true,
// show a group of common colors beneath the square
// or, supply an array of colors to customize further
palettes: true
};
// Add Color Picker to all inputs that have 'color-field' class
$('.color-field').wpColorPicker(myOptions);
Note:
I tested adding the code below to the change call back.
change: function(event, ui){
$(this).trigger('change');
},
This will trigger a change and update the iframe when the user clicks the color picker, but it happens before the color value is saved.
Does anyone happen to know how to access the event after the color chosen has been saved?
I would appreciate any help.
Thanks!
I'm not sure if this is the best solution, but it's a solution that seems to solve the issue.
add_action( 'admin_footer-widgets.php', array( $this, 'print_scripts' ), 9999 );
public function print_scripts() {
?>
<script>
( function( $ ){
function initColorPicker( widget ) {
widget.find( '.color-field' ).wpColorPicker( {
change: _.throttle( function() { // For Customizer
$(this).trigger( 'change' );
}, 3000 )
});
}
function onFormUpdate( event, widget ) {
initColorPicker( widget );
}
$( document ).on( 'widget-added widget-updated', onFormUpdate );
$( document ).ready( function() {
$( '#widgets-right .widget:has(.color-field)' ).each( function () {
initColorPicker( $( this ) );
} );
} );
}( jQuery ) );
</script>
<?php
}
I believe the workaround here is that you want to activate the ('.color-field').wpColorPicker() -> .on('widget-added widget-updated') as well as when the document is ready.