I am building a search form that filters the results based on the a text input as well as select options from four separate drop-downs (category, sub-category, location, etc).
The following two functions work well, but I just realized that if I type a search term in the input, make my drop-down selections and then go back and type a different search term, my drop-downs are ignored.
I've found solutions for similar problems across this site, but nothing that pertains to my particular situation.
This is the filter for the drop-downs:
$("select.filterby").change(function(){
var filters = $.map($("select.filterby").toArray(), function(e){
return $(e).val();
}).join(".");
$("div#flatdiv").find("article").hide();
$("div#flatdiv").find("article." + filters).show();
});
and Here is the one the filters based on the search input:
$(document).ready(function(){
$("#title").on("keyup", function() {
var value = $(this).val().toLowerCase();
$("#flatdiv article").filter(function() {
$(this).toggle($(this).text().toLowerCase().indexOf(value) > -1)
});
});
});
One is using true .filter() and the other is using .find to show() and hide().
I'm not sure where to go from here. I've made various attempts but each results in neither working so I'm hoping someone can help me out.
UPDATE:
Here is the final that ended up working beautifully!
//apply selection form any drop down forms
$("select.filterby").change(function(){
var filters = $.map($("select.filterby").toArray(), function(e){
return $(e).val();
}).join(".");
$("div#flatdiv").find("article").addClass("hidden-by-category-filter");
$("div#flatdiv").find("article." + filters).removeClass("hidden-by-category-filter");
});
//apply text input from search form
$("#title").blur(function(){
var textFilters = $(this).val().toLowerCase();
$("article:contains(" + textFilters +")").removeClass("hidden-by-text-filter");
$("article:not(:contains(" + textFilters +"))").addClass("hidden-by-text-filter");
});
In such cases, instead of using .hide() and .show(), it is often better to just add CSS classes to elements to hide them.
I would create classes such as .hidden-by-text-filter and .hidden-by-category-filter, each would individually hide the elements:
.hidden-by-text-filter, .hidden-by-category-filter {
display: none;
}
Then in the event handler just add or remove a specific class. For example, the event handler on text input would add/remove the class .hidden-by-text-filter, while the category drop-down would add/remove the class .hidden-by-category-filter.
$("select.filterby").change(function() {
var filters = $.map($("select.filterby").toArray(), function(e) {
return $(e).val();
}).join(".");
$("div#flatdiv").find("article").addClass(".hidden-by-text-filter");
$("div#flatdiv").find("article." + filters).removeClass(".hidden-by-text-filter");
});
This way both those filters wouldn't interfere with each other. If an element is meant to be hidden through both criteria, it would have both those classes, and still remain hidden. If one such element is made visible by one of the filters, it would still have the other class, and will remain hidden.
Related
I want to have some form fields mutually exclusive.It is a payment form with a lot of different categories.
Researching I got the code below
$('document').ready( function() {
$("#zero-out :input").each( function() {
$(this).keydown( function() {
$("#zero-out :input").not(this).val("");
});
});
});
This code assumes I could just wrap a div with Id zero-out on the fields I want to be exclusive - that is for those grouped fields only one can have a value. But I have about 4 different field groups. For example one group has textfield and textfield3. Another group has textfield2, textfield4 andtextfield7. Another group has textfield5,textfield6 and textfield8. These fields are not arranged in order(they are arranged in two columns and arranged in some order of convenience) so it is not easy to just wrap a div around a group.
Each textfield already has an onkeyup="javascript:PaySum() function to add up input values.
I need help to get an elegant way to achieve this goal.
I would give each grouping of mutually exclusive inputs some attribute (data-grouping=1, data-grouping=2, etc for example) and then update the code you have above to something like:
$('document').ready( function() {
$("input").each( function() {
$(this).keydown( function() {
$("input").not("[data-grouping='" + this.data("grouping") + "']").val("");
});
});
});
Depending on your page size and usage, blur might be a better event than keydown, and you may be able to further restrict inputs to only those within a particular parent.
Iam trying to bring some records using php and do some calculations. What iam doing now is that, each rows is having a dropdown with different currencies. When i select each currency, it calculates and shows certain values. Till here its working fine.
What i am trying to achieve is that if i select first currency dropdown, it should calculate the complete records calculations instead of selecting the currency of each rows. I guess i need to do some kind of loop in the jquery which calculates the rows.
Fiddle
Following is the part of jquery script for the currency dropdown.
$(window).load(function() {
$(document).ready(function() {
$("select").on('change', function() {
var dept_number = $(this).val();
var price = $(this).find(':selected').data('price');
var selected = $(this).find('option:selected').text();
if (selected == "INR") {
$(this).closest('table').find('.total1').val($(this).closest('table').find('.total').val());
} else {
$(this).closest('table').find('.total1').val((($(this).closest('table').find('.total').val() * price) / $(this).closest('table').find('.inrvalue').val()).toFixed(3));
}
$(this).closest('table').find('.price_unit').val(($(this).closest('table').find('.total1').val() / $(this).closest('table').find('.qty').val()).toFixed(3));
});
});
});
i guess i need to add some loops here in this jquery. Anyone to guide me how to do this. Or i need to follow a different step.
This is what i have tried as per the suggestion from Leonix.
$(document).ready(function(){
$(this).closest('table').find("select").each(function() {
var dept_number = $(this).val();
var price = $(this).find(':selected').data('price');
var selected = $(this).find("select");
if(selected=="INR")
{
$(this).closest('table').find('.total1').val($(this).closest('table').find('.total').val());
} else
{
$(this).closest('table').find('.total1').val((($(this).closest('table').find('.total').val() * price) / $(this).closest('table').find('.inrvalue').val()).toFixed(3));
}
$(this).closest('table').find('.price_unit').val(($(this).closest('table').find('.total1').val()/$(this).closest('table').find('.qty').val()).toFixed(3));
});
});
In your select change function, do a each for all rows of your table and find the dropdown:
$(this).closest('table').find("select").each(function() {
/* Each SELECT here, use $(this) */
})
or, depending of your needs :
$(this).closest('table').find("select").each(function() {
/* Each TR here, use selectInput */
var selectInput = $(this).find("select");
})
With the select in hands, use selectInput.val(changedSelectInput.val())
changedSelectInput is the jquery object containing the select who changed.
Using nested anonymous functions, take care, they are executed in the object context, so this and $(this) change depending on the object affected by function.
Advice: Use specific css classes for JS, as select.select-currency instead of select only, put these classes in your code. it will prevent so many mistakes and will save your time.
Note: currency_change[] is not a valid ID, if you dont need to set one, dont.
EDIT
Some code: https://jsfiddle.net/btpxq5ow/6/
What I did ?
Fix tags issues
Fix input in tbody issues, NEVER put it in a tr, tbody, table directly.
Fix some indentation issues
Apply the currency change to all rows
Prevent change event to call itself in an infinite loop
Apply calculation to all rows when they are updated
Fix some code syntax & performance issues
Please check your calculation are right since i modified it, see calculateRowTotals().
There are still a few html/js errorsthat must be fixed.
You will rarely get code from stackoverflow
I'm using the code from the accepted answer here
How do you limit options selected in a html select box?
to count the selected options in a 'select multiple' menu:
var last_valid_selection = null;
$("#select_options").change(function(event) {
if ($(this).val().length > 10) {
$(this).val(last_valid_selection);
} else {
last_valid_selection = $(this).val();
$("#select_options_text").text("Please select at least one, and up to ten options. You have currently selected "+$(this).val().length);
}
});
The menu is divided into six optgroups. When I hit 10 selections I can no longer make selections, as expected. But I can also no longer use CTRL+click on selected options to deselect them.
If I remove all optgroups, the menu functions correctly. It also functions correctly with one and two optgroups. It only seems to be when a third optgroup is added that the problem described above appears.
I have tested in Chrome and Firefox and the problem occurs in both.
Problem
You have duplicate options, so when try to restore the last selection by calling $(this).val(last_valid_selection), you could be selecting more than one value than you actually want (i.e. you end up selecting more than 10).
For example, you have more than one Biochemistry, so when last_valid_selection contains one instance of Biochemistry, all the duplicate Biochemistry options will be selected.
Solution
Use a different way of remembering the last valid selections.
Here I present a solution using data attribute and individually store whether or not an option has been previously selected.
function save_selected(select){
$(select).find("option").each(function(){
var t = $(this);
t.data("last-selected", t.is(":selected"));
});
};
function load_selected(select){
$(select).find("option").each(function(){
var t = $(this);
t.attr("selected", t.data("last-selected"));
});
};
$("#select_options").change(function(event) {
if ($(this).val().length > 10) {
load_selected(this);
} else {
save_selected(this);
}
});
Using this method, each individual option element has its own "last selected" state stored in its own data attribute. There would be no duplicate conflicts.
Demo: https://jsfiddle.net/alan0xd7/gzdrL5wu/12/
My app has a form which uses checkboxes to sort results by type and area. There are 2 fieldsets, one for the types and one for the areas.
The area checkboxes are linked to areas of an imagemap so it too can be used to select multiple areas to sort by.
I have this javascript:
This links the area checkboxes and the areas of the imagemap so they both act as form inputs
var $area = $('area');
$area.click(function(){
var $checkbox = $('#' + $(this).data("areanum"));
$checkbox.attr('checked', !$checkbox.attr('checked')).button('refresh');
});
$('label').click(function () {
$area.filter('[data-areanum="' + $(this).attr('for') + '"]').trigger('click');
return true;
});
This breaks the type checkboxes (they won't register as being checked when the form is submitted), unless I change the bit:
$('label').click(function () {
$area.filter('[data-areanum="' + $(this).attr('for') + '"]').trigger('click');
return false;
});
to
$('label').click(function () {
$area.filter('[data-areanum="' + $(this).attr('for') + '"]').trigger('click');
return true;
});
(changed the last line to return true)
But this makes the checkboxes difficult to select, they respond to a single click if the tick area is clicked but only respond to a double click if the checkbox label is clicked.
I hope this makes sense, if any clarification is needed I'll try to word the problem better.
Thanks for any help.
I think you don't need the label click handler at all because you are just toggling the checkbox checked property by triggering the area click handler which will be taken care by label's default behavior itself when it's for attribute is set to the checkbox id.
see this demo from jquery ui
you have to hold down the Ctrl key to make multiple selections
I really like the code but I don't want to force my visitor to press ctrl key
I want the code to allow multiple selections without holding ctrl key
is this possible?
I asked you a questions in the comments but I'll just write up a simple selection solution so you can see what I was thinking.
So basically you can use the jquery toggle() effect to roll your own selector. When a user clicks you'll add the orange class, when he clicks again it will remove the orange class.
$(document).ready( function() {
$('ul#selectable li').toggle( function() {
$(this).addClass('orange'); }, function() {
$(this).removeClass('orange'); } );
});
Then all your job is to grab all the li elements with the orange class and post them to a form or whatever your end goal is. Haven't checked this code but what your doing is asking for all the li elements within selectable that have the orange value at the end of the class attribute.
With the code below I'm creating a new array and then adding the text() value of each "orange li" into it.
var theSelections = new Array();
$('ul#selectable li[class$="orange"]').each( function(i) {
theSelections[i] = $(this).text();
});
Yes. However, the implementation would have to allow selected items to be deselected when clicked on a second time. You would just need to modify the code slightly to achieve this.
Do a .selectable( 'Enable' ) on all the items.
Then you will need to do a .selectable( 'toggle' ) onClick on all items.
That should do the trick.