I have a form where people sign up for a shift. There are multiple shifts on the page, and I have an onchange event that sends the sign-up via Ajax.
<select name="user" class="assign_user" id="user1">
<option value="user1234" selected="selected">Joe Bloggs</option>
<option value="">No-one</option>
<option value="user1235">Jane Mahon</option>
<option value="user1236">Ahmed Kitab</option>
<option value="user1237">Dave Smew</option>
</select>
If <option value="">No-one</option> is selected, I want to highlight the select element in yellow.
I cannot think of a way to do this with just CSS. I tried
select[value=''] {
background-color:lightyellow;
}
but the attribute filter in the square brackets doesn't accept empty values, as far as I know.
EDIT: just to be clear, empty select elements should be highlighted when the page loads, as well as when the element changes
CSS
.empty {
background-color: lightyellow;
}
Javascript
function userChanged(select) {
select = $(select);
if (select.val() === "") select.addClass("empty");
else select.removeClass("empty");
}
// UPDATED: Initialization
$(function() {
var user1 = $("#user1");
user1.change(function() { userChanged(user1); });
// Highlights select when page loads.
userChanged(user1);
});
UPDATE: Future solution uses CSS only. From: Is there a CSS parent selector?
select:has(option:checked[value='']) {
background-color: lightyellow;
}
This is my solution
jQuery
$(document).ready(function() {
$('.assign_user').on('change', function() {
var user_number = $(this).val();
var shiftid = $(this).siblings('input[name=shiftid]').val();
/*send data to database via Ajax*/
$.ajax({
url: "/admin/saveshift",
type: "GET",
data: { 'action': 'update', 'shiftid': shiftid, 'user_number': user_number },
success: function()
{
console.log("added a shift ");
/* message to user to say the record is updated */
$('#assigned').html('Updated');
$('#assigned').show();
setTimeout(function () {
$('#assigned').fadeOut();
return false;
}, 10000);
}
});
/* if null is selected, add class unassigned */
if ($(this).val() == '') {
$(this).addClass('unassigned');
} else {
$(this).removeClass('unassigned');
}
});
/* when page loads, if null is selected, add class unassigned */
$('.assign_user').each(function() {
if ($(this).val() == '') {
$(this).addClass('unassigned');
}
});
});
CSS
select.unassigned {
background-color:lightyellow;
}
I couldn't think of a way to do this with just CSS, hence the jQuery.
Related
I would like to validate my select option list in HTML.
The full code is available here:
https://jsfiddle.net/crgfp8ud/
Where I want to distinguish the one option, which will make the other query below active.
I found a couple of solutions:
Jquery Conditional validation based on select text
https://www.py4u.net/discuss/962973
from where I've picked up the code and tried to adapt it for my purposes. Unfortunately they didn't work properly:
$(document).ready(function(){
$('input[name=proposed_cable_route]').validate({
rules: {
cname: { required: true },
select1: { valueNotEquals: "0" },
other: { required: function(element){
return $("#cf_proposed_cable_route option:selected").text() == "Internal";
}
}
}
});
and the other one
/*
$('select').change(function() {
var text = $('select option:selected').text();
if(text == 'Internal') {
$('input[name=building_post_2000]').attr('disabled', true);
}
});
*/
the last one tried was:
$("input[name=proposed_cable_route]").on('select', function() {
var blockNumber = $('#cf_building_post_2000');
// if is company
if ($(this).val() == "Internal") {
// show panel
blockNumber.show();
// remove disabled prop
blockNumber.find('input,select,radio').prop('disabled', false);
} else {
// if is not company, hide the panel and
add disabled prop
//blockNumber.hide();
blockNumber.find("input").val("");
blockNumber.find('input,select,radio').prop('disabled', true);
}
});
Is there any way to make the validation based on the select option value?
I think this would do the trick. It gets the currently relevant SELECT and gets its value:
$('#cf_proposed_cable_route').change(function() {
var text = $(this).val();
console.log(text);
$('input[name=building_post_2000]').prop("disabled", text === 'Internal');
});
i think that you don't need to select event you just need to change event when you select one option the value of select tag will be change to be the same value of selected option
For Example
<select>
<option value="0">Select car:</option>
<option value="1">Audi:</option>
<option value="2">BMW</option>
<option value="3">Citroen</option>
<option value="4">Ford</option>
</select>
JS Validation
var sel = $("select");
sel.change(function () {
var opt = $("select option:checked")
if(opt.text() === "BMW") {
console.log(opt.text())
}
});
or you can create a loop
Example
var sel = $("select");
sel.change(function () {
for(var i = $("option").length; i >= 1; i--) {
if($(this).val() === $("option:nth-child("+i+")").val()) {
if($("option:nth-child("+i+")").text() === "BMW") {
console.log($("option:nth-child("+i+")").text())
}
}
}
});
Here is a simplified version of my problem:
The HTML:
<select id="mySelect">
<option value="1">One</option>
<option value="2">Two</option>
<option value="3">Three</option>
</select>
The jQuery:
$('#mySelect').change( function() {
// do stuff
} );
The problem is that when I move my mouse cursor over the options, do stuff happens as I hover over one of the options, before I actually select the new option. How do I avoid this behaviour so that .change() is triggered only when I have finished choosing a new option in the select?
Edit 1: Further information
Apparently this code would not cause behaviour described. In the actual code the select boxes are being updated as further data is loaded via .get() and processed.
Edit 2: Actual function that updates a select box
This function is the one in my code that updates one of the select boxes after more data has loaded. The global variable padm_courses is an array of course objects, that have a code and name property used to populate the course filter select box.
function loadCourseFilter() {
var selected = '';
var sel = $('<select>').attr('id','padmCourseFilter');
$(padm_courses).each(function() {
sel.append($("<option>").attr('value',this.code).text(this.name));
});
if($('#padmCourseFilter').length) {
selected = $('#padmCourseFilter').val();
$('#padmCourseFilter').replaceWith(sel);
if(selected != '') $('#padmCourseFilter option[value="'+escape(selected)+'"]').prop('selected', true);
} else {
sel.appendTo('#padm_hub_filters');
}
$('#padmCourseFilter').change( function() {
processMCRsByCourse($('#padmCourseFilter').val());
var tables = $('.sv-datatable').DataTable();
tables.rows('.duplicate').remove().draw();
filterTheBlockFilter();
} );
}
Try changing your change event
$(document).on('change', '#mySelect', function() {
// do stuff
});
Okay, I found a solution. It seems that when triggered, the function loadCourseFilter was recreating the selectbox from scratch each time and overwriting the old one. This caused weird behaviour when hovering over one of the options.
A revised version of the function adds only new options, and does not update the filter if nothing was actually added...
function loadCourseFilter() {
var sel, output;
if($('#padmCourseFilter').length) {
var count = 0;
sel = $('padmCourseFilter');
output = [];
$(padm_courses).each(function() {
if($('#padmCourseFilter option[value="'+this.code+'"]').length == 0) {
count++;
output.push('<option value="'+this.code+'">'+this.name+'</option>');
}
});
if(count > 0) {
sel.append(output.join(''));
sortDropDownListByText('padmCourseFilter');
}
} else {
sel = $('<select>').attr('id','padmCourseFilter');
$(padm_courses).each(function() {
sel.append($("<option>").attr('value',this.code).text(this.name));
});
sel.appendTo('#padm_hub_filters');
}
$('#padmCourseFilter').change( function() {
processMCRsByCourse($('#padmCourseFilter').val());
var tables = $('.sv-datatable').DataTable();
tables.rows('.duplicate').remove().draw();
filterTheBlockFilter();
} );
}
I've created a script to clone a div, which works fine, however but the javascript chained function within it no longer works for any cloned elements. Works ok for the first one as expected.
I've created a jsfiddle here: https://jsfiddle.net/bvcebmbw/
The javascript is as follows (for both chained and clone functions)
$(document).ready(function () {
$(".Targeting").each(function () {
$('#TargetingAdd').click(function () {
var num = $('.clonedTargeting').length, // Checks to see how many "duplicatable" input fields we currently have
newNum = new Number(num + 1), // The numeric ID of the new input field being added, increasing by 1 each time
newElem = $('#entryTargeting' + num).clone().attr('id', 'entryTargeting' + newNum).fadeIn('slow'); // create the new element via clone(), and manipulate it's ID using newNum value
// Insert the new element after the last "duplicatable" input field
$('#entryTargeting' + num).after(newElem);
// Enable the "remove" button. This only shows once you have a duplicated section.
$('#TargetingDel').attr('disabled', false);
init(newElem.children(".Targeting"));
// Right now you can only add 4 sections, for a total of 5. Change '5' below to the max number of sections you want to allow.
if (newNum == 5)
$('#TargetingAdd').attr('disabled', true).prop('value', "You've reached the limit"); // value here updates the text in the 'add' button when the limit is reached
});
$('#TargetingDel').click(function () {
// Confirmation dialog box. Works on all desktop browsers and iPhone.
if (confirm("Are you sure you wish to remove this Targeting?")) {
var num = $('.clonedTargeting').length;
// how many "duplicatable" input fields we currently have
$('#entryTargeting' + num).slideUp('slow', function () {
$(this).remove();
// if only one element remains, disable the "remove" button
if (num - 1 === 1)
$('#TargetingDel').attr('disabled', true);
// enable the "add" button
$('#TargetingAdd').attr('disabled', false).prop('value', "add section");
});
}
return false; // Removes the last section you added
});
});
// Enable the "add" button
$('#TargetingAdd').attr('disabled', false);
// Disable the "remove" button
$('#TargetingDel').attr('disabled', true);
});
;(function($, window, document, undefined) {
"use strict";
$.fn.chained = function(parent_selector, options) {
return this.each(function() {
/* Save this to child because this changes when scope changes. */
var child = this;
var backup = $(child).clone();
/* Handles maximum two parents now. */
$(parent_selector).each(function() {
$(this).bind("change", function() {
updateChildren();
});
/* Force IE to see something selected on first page load, */
/* unless something is already selected */
if (!$("option:selected", this).length) {
$("option", this).first().attr("selected", "selected");
}
/* Force updating the children. */
updateChildren();
});
function updateChildren() {
var trigger_change = true;
var currently_selected_value = $("option:selected", child).val();
$(child).html(backup.html());
/* If multiple parents build classname like foo\bar. */
var selected = "";
$(parent_selector).each(function() {
var selectedClass = $("option:selected", this).val();
if (selectedClass) {
if (selected.length > 0) {
if (window.Zepto) {
/* Zepto class regexp dies with classes like foo\bar. */
selected += "\\\\";
} else {
selected += "\\";
}
}
selected += selectedClass;
}
});
/* Also check for first parent without subclassing. */
/* TODO: This should be dynamic and check for each parent */
/* without subclassing. */
var first;
if ($.isArray(parent_selector)) {
first = $(parent_selector[0]).first();
} else {
first = $(parent_selector).first();
}
var selected_first = $("option:selected", first).val();
$("option", child).each(function() {
/* Remove unneeded items but save the default value. */
if ($(this).hasClass(selected) && $(this).val() === currently_selected_value) {
$(this).prop("selected", true);
trigger_change = false;
} else if (!$(this).hasClass(selected) && !$(this).hasClass(selected_first) && $(this).val() !== "") {
$(this).remove();
}
});
/* If we have only the default value disable select. */
if (1 === $("option", child).size() && $(child).val() === "") {
$(child).prop("disabled", true);
} else {
$(child).prop("disabled", false);
}
if (trigger_change) {
$(child).trigger("change");
}
}
});
};
/* Alias for those who like to use more English like syntax. */
$.fn.chainedTo = $.fn.chained;
/* Default settings for plugin. */
$.fn.chained.defaults = {};
})(window.jQuery || window.Zepto, window, document);
$(document).ready(function(){
$("#connectionSub").chained("#connectionType");
$("#apppagesoptions").chained("#connectionSub");
$("#phoneVersion").chained("#phoneBrand");
$("#osVersionMin").chained("#phoneVersion");
$("#osVersionMax").chained("#phoneVersion");
});
and the HTML is 3 chained inputs:
<div class="Targeting">
<select id="connectionType" name="connectionType[]">
<option disabled value="">--</option>
<option value="pages">Facebook Pages</option>
<option value="apps">Apps</option>
<option disabled value="">--</option>
<option value="advanced">Advanced Connections</option>
</select>
<select id="connectionSub" name="connectionSub[]">
<option value="">--</option>
<option value="page_like" class="pages">People who like your Page</option>
<option value="page_friend" class="pages">Friends of people who like your Page</option>
<option value="page_exclude" class="pages">Exclude people who like your Page</option>
<option value="app_like" class="apps">People who like your App</option>
<option value="app_friend" class="apps">Friends of people who like your App</option>
<option value="app_exclude" class="apps">Exclude people who like your App</option>
</select>
<select id="apppagesoptions" name="apppagesoptions[]" multiple>
<option>test</option>
</select>
</div>
</div><!-- end #entry1 -->
<div id="addDelButtons">
<input type="button" id="TargetingAdd" value="add section">
<input type="button" id="TargetingDel" value="remove section above">
</div>
Appreciate any help with this!
For all the <div class="Targeting"> the select element's ids are remain same. that's why it's only working for first one.
I have read about filtering table plugins. What I'm searching for is like this popup window.
(source: staticflickr.com)
When the user starts typing in the search-box, the relevant channel/category (as selected on previous dropdown box) should filter up. Also some animated loading action should happen while the filter process is going on.
I am looking for jQuery plugins which will make my filter-job easier to implement.
I think it is to ambigous to have a plugin for it. Just do something like this:
function filter($rows, category, search) {
$rows.each(function() {
if (category == ($("td:eq(2)", this).text() || category == "all") && (search. === "" || $("td:eq(1)", this).text().indexOf(search) !== -1) {
$(":checkbox", this).removeAttr("disabled");
$(this).show();
}
else
$(this).hide(function(){
$(":checkbox", this).attr("disabled", "disabled");
});
});
}
$("select.category").change(function() {
filter ($(this).closest("form").find("tr"), $(this).val(), $(this).closest("form").find("input.search").val());
});
$("input.search").keyUp(function() {
filter ($(this).closest("form").find("tr"), $(this).closest("form").find("select.catagory").val(), $(this).val());
});
You may need to make a few adjustments in order to make it work with the exact format of html.
Update to make it into a PLUGIN
$.fn.filter_table = function(options) {
options = $.extend(options, {
show: $.noop(), //Callback when a row get shown
hide: $.noop(), // Callback when a row gets hidden
entries: "table tr", // Selector of items to filter.
map: {} //Required parameter
//TODO Add default ajustment parameters here to remove ambiguity and assumptions.
});
return this.each(function() {
var form = this;
function each(callback) {
for (var selector in options.map) {
var check = options.map[selector];
$(selector, form).each(function(){
callback.call(this, check);
});
}
}
function show(row) {
if (!$(row).is(":visible")) {
options.show.apply(row);
$(row).show();
}
}
function hide(row) {
if ($(row).is(":visible"))
$(row).hide(options.hide);
}
function run_filter() {
$(options.entries, form).each(function() {
var row = this, matched = true;
each(function(check) {
matched &= check.call(this, row);
});
matched ? show(this) : hide(this);
})
}
//Bind event handlers:
each(function() {
$(this).bind($(this).is(":text") ? "keyup" : "change", run_filter);
});
});
};
You can use this plugin as follows:
$("form").filter_table({
map: {
//These callback define if a row was matched:
"select.category": function(row) {
//this refers to the field, row refers to the row being checked.
return $(this).val() == "all" || $(this).val() == $("td:eq(2)", row).text();
},
"input.search": function(row) {
return $(this).val() == "" || $(this).val() == $("td:eq(1)", row).text();
}
},
entries: "tr:has(:checkbox)", //Filter all rows that contain a checkbox.
show: function() {
$(":checkbox", this).removeAttr("disabled");
},
hide: function() {
$(":checkbox", this).attr("disabled", "disabled");
}
});
Okay it should work once it was debugged. I haven't tested it. I think that part is up to you.
If your HTML looks like this:
<form id="filterForm">
<input type="text" id="filterBox">
<input type="submit" value="Filter">
</form>
<div id="checkboxContainer">
<label><input type="checkbox" id="checkbox123"> Checkbox 123</label>
</div>
You could do something like...
//Set variables so we only have to find each element once
var filterForm = $('#filterForm');
var filterBox = $('#filterBox');
var checkboxContainer = $('#checkboxContainer');
//Override the form submission
filterForm.submit(function() {
//Filter by what the label contains
checkboxContainer.find('label').each(function() {
//If the value of filterBox is NOT in the label
if ($(this).indexOf(filterBox.val()) == -1) {
//Hide the label (and the checkbox since it's inside the label)
$(this).hide();
} else {
//Show it in case it was hidden before
$(this).show();
}
});
//Prevent the form from submitting
return false;
});
You can use this tablesorterfilter plugin to achieve what you need
Working Fiddle
And also please have a look at http://datatables.net/
There are many options out there. Here is a good place to start: http://www.wokay.com/technology/32-useful-jquery-filter-and-sort-data-plugins-62033.html
Filtering like this isn't incredibly complicated. It may be worth looking at the source of a couple plugins that come close to what you want and then try to write your own. You'll learn a lot more if you do it yourself!
I have nearly finished writing this code: http://jsfiddle.net/2Jkk9/11/
but I can't figure out how to search the select box for the value in my text box and enable/disabled the button accordingly.
That's probably enough explanation.. the code explains all...
Thank you :).
EDIT Here's my original code from jsfiddle:
<select id="myselect">
<option>apple</option>
<option>banana</option>
<option>pear</option>
</select>
<br><br>
<input id="filter" type="text"/>
and
$(function() {
$('#filter').keyup(function() {
// if select box contains input then
// $('#mybtn').attr(disabled, 'disabled');
//}
//else {
// $('#mybtn').removeAttr('disabled');
//}
});
});
This should do what you want by filtering the options for ones matching the text and checking the length:
$('#filter').keyup(function() {
var text = $(this).val();
if ($('#myselect option').filter(function() {
return $(this).text() === text;
}).length) {
$('#mybtn').attr('disabled', 'disabled');
}
else {
$('#mybtn').removeAttr('disabled');
}
});
http://jsfiddle.net/infernalbadger/2Jkk9/16/
Use each() to loop through to traverse your list and get value by .val()
check modified code.
(function() {
$('#filter').keyup(function() {
$('#myselect option').each(function(){
if($(this).val() == $('#filter').val())
{
$('#mybtn').attr('disabled', 'disabled');
alert('hello');
}
else
{
$('#mybtn').removeAttr('disabled');
}
});
// if select box contains input then
// $('#mybtn').attr(disabled, 'disabled');
//}
//else {
// $('#mybtn').removeAttr('disabled');
//}
});
$(function() {
$('#filter').keyup(function() {
if($("#filter").val().split($("#myselect").val()).length > 1) {
$('#mybtn').removeAttr('disabled');
}
else {
$('#mybtn').attr('disabled', 'disabled');
}
});
});
this works if the filter contains the selected value, not only when the same.
What about:
give your options a value like:
<select>
<option value="1"></option>
</select>
$('#myselect').change(function () {
if ($(this).val() == "1") {
//do this
} else {
//do this
}
});