I have page with around 20 to 30 controls based on the query string values. I need to change a button as disabled based on the value changes in the controls. For examble in the list of Check boxes if something is checked or unchecked, some texts added or removed etc... for all the controls.
The controls are textbox, option buttons, check boxes, select controls and list boxes.
I don't want to add static methods to all controls. I do have an idea of doing the late binding to all the controls and to attach events. And that events will disable the button whenever the event gets fired.
Is there any other way to do this functionality in a simple way(Like Keypress or using event property window object)?
As #ekhaled pointed out you can use the same handler to handle all the click and change events.
Here's a somewhat convoluted example:
<div id="container">
<input id="input1" type="text" value="" />
<select>
<option value="1">ABC</option>
<option value="2">EFG</option>
</select>
<input type="button" value="Submit" />
</div>
and the javascript for it:
$('#container').on("change click", ":input", function (event) {
if (event.target.nodeName == "SELECT") {
if ($(event.target).val() == "2") {
console.log("disable");
$(":button").prop("disabled", true);
} else {
$(":button").prop("disabled", false);
console.log("enable");
}
}
if (event.target.id == "input1" && $(event.target).val() == "") {
$(":button").prop("disabled", true);
}
});
See it working here.
However if you main concern is validation you should have a look at jquery validation
With jQuery validation you can set specific rules for each of the inputs that will make up the validation of the whole form. It is very customizable, you can change where and how the errors are displayed, when is the validation triggered, etc.
You can use event delegation and bind your event to the parent element, and then write all your logic inside that one event handler.
Can't really show you much, because you haven't included any examples or code. But something along the lines of:
$("body").on('change click', 'input, select', function(){
var _this = $(this);
if(_this.is('input[type=checkbox].className')){
//follow one logic
}
if(_this.is('input[type=radio].className')){
//follow another logic
}
//etc, etc
})
Related
I am new to Javascript and trying to add a and Query to a js file.
I have added a checkbox this is required to be checked for the submit button to show.
In the original there was already one checkbox with the js query but I have added a second. How do I make the js only allow the button to be clicked when both are checked?
The current code for the js is
jQuery('.check_policy').on('click', function(){
if(jQuery('#policycheck') .is(':checked')){
jQuery("#listingsubmitBTN").prop('disabled',false);
jQuery("#listingsubmitBTN").removeClass('dissablebutton');
}
else{
jQuery("#listingsubmitBTN").prop('disabled',true);
jQuery("#listingsubmitBTN").addClass('dissablebutton');
}
});
The second check box I have added is called policycheck_2
Thanks in advance for any help. I think this could be one of many js questions
Mark
jQuery('.check_policy').on('click', function(){
if(jQuery('#policycheck').is(':checked') && jQuery('#policycheck_2').is(':checked')){
jQuery("#listingsubmitBTN").prop('disabled',false).removeClass('dissablebutton');
}
else{
jQuery("#listingsubmitBTN").prop('disabled',true).addClass('dissablebutton');
}
});
Edit: Just add an AND (&&) operator with the same syntax with the new ID as the first one in the if statement.
I'll also shortened the rest a little bit, looks nicer. :-)
Separate the responsibilities.
Bind the click event to the checkboxes. The handler only has to trigger the event on the specific button.
Bind a custom event to your button which validates the checked boxes.
Use this condition to disable or enable:
$('.check_policy').length !== $('.check_policy:checked').length
$('.check_policy').on('click', function() {
// Here we trigger the custom event.
$('#listingsubmitBTN').trigger('validatechecked');
// Now this handler only trigger events to specific elements and not
// everything mixed here.
});
$('#listingsubmitBTN').on('validatechecked', function() {
$(this).prop('disabled', $('.check_policy').length !== $('.check_policy:checked').length);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input class='check_policy' type='checkbox'>Check policy#1
<p>
<input class='check_policy' type='checkbox'>Check policy#2
<p>
<input type='button' id='listingsubmitBTN' value="Click me!" disabled>
Your main issue is that your if statement is not checking if both checkboxes are checked - it still only checks to see if #policycheck is checked to determine the disabled status of the button. A simple fix would be to add the jQuery("#policycheck_2").is(":checked") to your if statement, and your code will work - however, you can leverage using an expression in the prop setter function, as well as the toggleClass function to simplify/shorten/clean-up your code a bit.
Here's an example of what that would look like:
jQuery('.check_policy').on('click', function() {
var bothChecked = jQuery("#policycheck").is(":checked") && jQuery("#policycheck_2").is(":checked");
jQuery("#listingsubmitBTN").prop("disabled", !bothChecked).toggleClass("dissablebutton", !bothChecked);
console.log("button", bothChecked ? "enabled" : "disabled");
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="checkbox" id="policycheck" />
<input type="checkbox" id="policycheck_2" />
<button class="check_policy">Check Policy</button>
I have an input field and a button. It is necessary that when the button is clicked the input field gets focus.
I need the behaviour to be slightly different depending on whether the input field was focused manually by the user or if it was focused due the button being clicked.
It seems this would be relatively simple, but I couldn't come up with a solution so far. Any ideas very welcome.
$("button").click(function() {
target_input = $("input");
target_input.focus();
});
$("input").focus(function() {
// if focus done manually by user
// do something
// if focus done via button
// do something else
});
Here is a solution that uses no extra variables, instead it checks the event.
$("button").click(function() {
target_input = $("input");
target_input.focus();
});
$("input").focus(function(e) {
// if focus done manually by user
// do something
// if focus done via button
// do something else
if(e.originalEvent.relatedTarget){
// only from button events
}
// here is from all events
});
this e.originalEvent.relatedTarget will return null if we didn't use the button to originate the focus.
remember to add e to the function.
You should be able to use Event.isTrusted for this:
The isTrusted read-only property of the Event interface is a boolean
that is true when the event was generated by a user action, and false
when the event was created or modified by a script or dispatched via
dispatchEvent.
$("input").focus(function(e) {
if(e.isTrusted) {...} else {...}
});
As noted in the comments, neither IE nor Safari like this.
This works without global variables and it is cross-browser working solution:
$('button').click(function () {
$(this).prev('input').focus()
})
$('input').click(function (e) { // yes, listen to click instead
// original event exists only if input was clicked directly
if (e.originalEvent) {
console.log('manually triggered')
}
})
<div style="background-color: yellow;">
<input type="text">
<button>Focus input</button>
<br>
<input type="text">
<button>Focus input</button>
</div>
<script src="https://unpkg.com/jquery"></script>
The problem I am having is that the radio buttons in my scenario are not being selected when they are clicked. I have created a JSFiddle to show the code and the issue.
For whatever reason, I have an entire area that is surrounded in an element.
<a href="/link">
//some stuff
<div class="protected">
<input type="radio" name="b1" value="1" /> Button 1
<input type="radio" name="b1" value="2" /> Button 2
</div>
//some stuff
</a>
There is a small section within this tag that needs to be protected from the default behaviour of the link. This section contains some radio inputs which need to be selectable.
The way I currently have it, I am protecting the "protected" section with an event listener and:
$('.protected').off('click').on('click', function (e) {
e.preventDefault();
});
I also have an event listener on the radio buttons so that I can perform the change of property when they are clicked.
$('.protected > :radio').off('click').on('click', function (e) {
$(this).siblings(':radio').removeAttr('checked');
$(this).attr('checked', 'checked');
});
Unfortunately, this is setting the checked attribute in the dom however the radio button is not being filled in on the screen for the user.
Any help would be greatly appreciated.
You need to add stopPropagation()
$('.protected > :radio').off('click').on('click', function (e) {
e.stopPropagation();
//$(this).siblings(':radio').removeAttr('checked');
//$(this).attr('checked', 'checked');
});
Also, make sure to comment out
$(this).siblings(':radio').removeAttr('checked');
$(this).attr('checked', 'checked');
You don't need them as the browser handles this for you.
DEMO
What was happening is, since you had preventDefault in the container click handler, the nested click event was propagating to that click handler and was preventing the radio button from being set.
I'm using checkboxes to toggle the enabled and disabled state of some multi-lists on a registration form. The checkbox is labeled with the category, and the multi-list contains the items that belong to that category.
I'm using jQuery 1.7.2.
$('#sch_cat_hockeyschools').toggle(function(ev) {
ev.stopPropagation();
$("#type_select_hockeyschools").prop("disabled", false);
$("#type_select_hockeyschools").removeProp("disabled", "disabled");
$("#sch_cat_hockeyschools").prop("checked", true);
$("#sch_cat_hockeyschools").prop("checked", "checked");
}, function(ev) {
ev.stopPropagation();
$("#type_select_hockeyschools option:selected").removeAttr("selected");
$("#type_select_hockeyschools").prop("disabled", true);
$("#type_select_hockeyschools").prop("disabled", "disabled");
$("#sch_cat_hockeyschools").prop("checked", false);
$("#sch_cat_hockeyschools").removeProp("checked");
});
Sample of corresponding checkbox HTML:
<input class="catmark" type="checkbox" name="sch_categories[]" id="sch_cat_hockeyschools" value="1" />General Hockey Schools
<input class="catmark" type="checkbox" name="sch_categories[]" id="sch_cat_springhockey" value="2" />Spring Hockey
The problem is that the upon clicking the checkbox, the checkbox does not become ticked or checked; it immediately returns to an unchecked state, which I thought the stopPropagation() function would help with. Apparently not. The multi-lists get enabled and disabled as expected, but the checkbox doesn't get ticked.
The result of this problem is that when the form is submitted, the array containing the selected categories is empty; thus, because at least one checked category is a required field in the form, the PHP script that processes the form throws one of my errors which tells me a required field was left blank.
Any ideas on how to make sure that the checkbox actually gets checked, and by extension, POSTS actual data to the processing script?
Thanks guys.
The problem is the use of toggle -- per the documentation:
The implementation also calls .preventDefault() on the event, so links
will not be followed and buttons will not be clicked if .toggle() has
been called on the element.
toggle itself is calling preventDefault, which is stopping the default behavior of the event, checking/unchecking the box.
Rather than toggle, use bind or on (see edit note below) to add a listener for the change event, in which you can examine the state:
$('#sch_cat_hockeyschools').on('change', function () {
if (this.checked) {
// do stuff for a checked box
console.log('check is on');
} else {
// do stuff for an unchecked box
console.log('check is off');
}
});
Try it out at jsFiddle.
EDIT
Please note, this code shows use of the on method, whereas the jsFiddle example uses bind. As pointed out by Sam Sehnert, on is the preferred method for attaching events with > jQuery 1.7. If you are using an older version of jQuery, use bind as in the jsFiddle example.
Documentation
jQuery.toggle
jQuery.bind
jQuery.on
A textbox on my form may change depending on what's selected in various drop down lists.
Is there a way to call a javascript function when the textbox value changes?
Tried onchange event but this only seems to work if a user manually changes the textbox value.
Cheers,
Breandán
No, javascript-triggered changes to form elements don't trigger events. If they did, this would cause all sorts of recursive infinite loops.
The simple solution is to call your onchange function manually whenever you change the value of the textbox, however you could also use some kind of wrapper function. As a very basic example:
function updateTextField(new_text) {
text_field.value = new_text;
text_field.onchange();
}
When setting the content of the text box from your JS code, call out to another function passing in the text to set, you can then call it from where ever you need and do your logic then.
Try to disconnect the logic responsible for changing the control's value from the onchange event's execution path using a setTimeout.
<html>
<head>
<script type="text/javascript">
function setValue(target) {
alert("changed - value: " + target.value);
setTimeout("reallySetValue('" + target.id + "');", 1);
}
function reallySetValue(id) {
var control = document.getElementById(id);
control.value += control.value;
}
</script>
</head>
<body>
<form>
<div>
Enter "a" here:
<input type="text" id="test" onchange="setValue(this)">
<br/>
<br/>
<input type="text">
</div>
</form>
</body>
</html>
It's illustrated here
Changing a Textbox Value in its OnChange Event
In web browsers, programmatic changes on a control won't trigger events on that control. You must instruct the code that changes the textbox value to trigger the onchange event. This is how you can do it in plain javascript:
var textbox = document.getElementById("boxId");
textbox.value = "Abc";
textbox.onchange();
Of course, using a library like jQuery makes it easier and more robust:
$("#boxId").val("Abc").change();
You can use the excellent event.simulate.js to do this. This script does depend on the Prototype.js library, though.
If you'd want to this without relying on an external library, take a look at the fireEvent and createEvent functions. A simple demonstration of how you could implement this:
function triggerEvent(element, eventName)
{
if (document.createEvent)
{
var evt = document.createEvent('HTMLEvents');
evt.initEvent(eventName, true, true);
return element.dispatchEvent(evt);
}
if (element.fireEvent)
return element.fireEvent('on' + eventName);
}
triggerEvent(document.getElementById('myTextbox', 'change'));
Using event.simululate.js, you would do it like this:
Event.simulate('myTextbox', 'change');
A similiar question was asked here: Trigger an event with Prototype.
EDIT: although it is possible to use document.getElementById('myTextbox').change(), I would not recommend doing it, as it makes your code less flexible. When attaching onChange events to the textbox, these would not trigger when manually calling the change() event. Using the above method, events will propagate, just as if the event was a user-triggered one.
Assuming the frontend is in html:
You could install a timout callback and query the contents of the textbox in intervals of, say, 100msecs and compare it to some previous value you store in a variable.
Keywords: window.setTimout(), window.setInterval()
I'd recommend to look over YUI's Custom events for Example:
YUI Custom Event Example Link
All you need is to attach this script with Events manipulations
<script type="text/javascript" src="http://yui.yahooapis.com/2.7.0/build/yahoo-dom-event/yahoo-dom-event.js"></script>
and then you are able to use Custom Events (everywhere in HTML)
fnSubscriberChange - inside this Func you could do whatever you want. You could put your textbox change value logic here and depend on the Changed Select box value - call desired func.
Logic that depends on Event listening is clear and easy to modify;
YUI library supports all browsers so you shouldnt mind about browsers features.
Text box and select boxes:
<input type='text' id='id_text_fld' value=''/>
<select id='id_sel_one'>
<option value="test1">Test1
<option value="test2">Test2
</select>
<select id='id_sel_two'>
<option value="test3">Test3
<option value="test4">Test4
</select>
Script for events:
<script>
(function() {
//create a new custom event, to be fired
var onChangeValue = new YAHOO.util.CustomEvent("onChangeValue");
// Attach change event listener for Select boxes by their IDs
YAHOO.util.Event.on( ['id_sel_one', 'id_sel_two'], 'change', fnCallback, this);
// Function to call when Change event on Select occures
fnCallback = function(e) {
alert("This elem:" + this.id+ " changed value to:" + this.value);
// Fire our Custom event
onChangeValue.fire({dom_el: this}); // passing select box element [this] to function
}
// Listen for Custom event and call our Func
onChangeValue.subscribe(fnSubscriberChange); // Lets listen for ChangeValue event and call our Func
fnSubscriberChange = function(type, args) {
alert("Event type:" + type + " dom el id:" + args[0].dom_el.id );
var dom_el = args[0].dom_el; // Select Box that produces Change
};
})();
</script>