jQuery .change() event not firing in IE - javascript

I've got a dialog that performs a calculation that is dependant on three input fields. When any of them are changed it checks whether they are all filled and if they are it processes and gives its response.
It works absolutely fine in FF, Chrome, Opera etc, but in any version of IE it just stops working. The rest of my jQuery works fine, but I can't work out exactly where the problem is here. I think it might be to do with the .change() event or the multiple event binding but I really don't know.
Here's the offending code:
var loan = $("#ltv-loan-amount");
var mortgage = $("#ltv-mortgage");
var property = $("#ltv-property");
$("#ltv-dialog input").change( function() {
if(loan.val() && mortgage.val() && property.val())
{
var ltv = parseInt( ( ( parseInt(loan.val()) + parseInt(mortgage.val()) ) / parseInt(property.val()) )* 1000 );
ltv /= 10;
if(ltv > 0 && ltv < 85)
{
$("#ltv-result").html("<span id=\"ltv-form-result\">" + ltv + "%</span></p><p><a id=\"ltv-link\" href=\"#sidebar-head\">Congratulations, your LTV has passed. Please now proceed with your application opposite.</a>");
$("#amount").val(loan.val());
$("#mortgage_balance").val(mortgage.val());
$("#prop_value").val(property.val());
$("#ltv-link").click(function() {
$( "#ltv-dialog" ).dialog( "close" );
});
}
else if (ltv > 84)
{
$("#ltv-result").html("<span id=\"ltv-form-result\">" + ltv + "%</span></p><p>Unfortunately your LTV is greater than 85%. You may still qualify for a loan if you reduce the loan amount.");
}
else
{
$("#ltv-result").html("</p><p>Please check your input above as you currently have a negative ltv.");
}
}
});
and the HTML in question:
<div id="ltv-dialog" title="Do You Qualify for a Loan?">
<p>Please enter the fields below and your LTV will be calculated automatically.</p>
<div id="ltv-form">
<div class="ltv-row">
<label for="ltv-loan-amount">Loan Amount:</label>
<input type="text" name="ltv-loan-amount" id="ltv-loan-amount" class="p000" />
</div>
<div class="ltv-row">
<label for="ltv-mortgage">Mortgage Value:</label>
<input type="text" name="ltv-mortgage" id="ltv-mortgage" class="p000" />
</div>
<div class="ltv-row">
<label for="ltv-property">Estimated Property Value:</label>
<input type="text" name="ltv-property" id="ltv-property" class="p000" />
</div>
</div>
<div class="ltv-row">
<p>Loan to Value % (LTV): <span id="ltv-result"></span></p>
</div>
</div>
An Update
The change event appears to be firing, but only when the text box changes from a value to null.

As you are targeting text input elements, have you tried using a different event? So instead of change use, for example, keyup? $("#ltv-dialog input").keyup( function() {. This will fire after every keypress.

Using jQuery .on() also might solve your problem. Use it like this :
jQuery("#ltv-dialog").on("change", "input", function(){
alert("It works !");
//your javascript/jQuery goes here
}
);
jsfiddle

I had the same issue: Below fix worked for me:
Instead of: $("#ltv-dialog input").change( function() {
I used: $('#ltv-dialog').on('input', function() {

Please try with using each instead of change / click , which is working fine even first time in IE as well as other browsers
Not Working a first time
$("#checkboxid").change(function () {
});
Working fine even first time
$("#checkboxid").each(function () {
});

Use the live function, it usually makes it work ...
$("#YOURTHING").live("change", function(){
// CODE HERE
});

Related

For loop with eval not working

My first time writing my own javascript/jQuery for-loop and I'm running into trouble.
Basically, I have a series of divs which are empty, but when a button is clicked, the divs turn into input fields for the user. The input fields are there at the outset, but I'm using CSS to hide them and using JS/jQuery to evaluate the css property and make them visible/hide upon a button click.
I can do this fine by putting an id tag on each of the 7 input fields and writing out the jQuery by hand, like this:
$('#tryBTN').click(function(){
if ( $('#password').css('visibility') == 'hidden' )
$('#password').css('visibility','visible');
else
$('#password').css('visibility','hidden');
}
Copy/pasting that code 7 times and just swapping out the div IDs works great, however, being more efficient, I know there's a way to put this in a for-loop.
Writing this code as a test, it worked on the first one just fine:
$('#tryBTN').click(function() {
for(i = 1; i <= 7; i++) {
if($('#input1').css('visibility') == 'hidden')
$('#input1').css('visibility', 'visible');
}
});
But again, this only works for the one id. So I changed all the HTML id tags from unique ones to like id="intput1" - all the way out to seven so that I could iterate over the tags with an eval. I came up with this:
$('#tryBTN').click(function () {
for (i = 1; i <= 7; i++) {
if ($(eval('input' + i)).css('visibility') == 'hidden')
$('input' + i).css('visibility', 'visible');
}
});
When I put in the eval stuff - it doesn't work. Not sure what I'm doing wrong. A sample of the HTML looks like this:
<form>
<div class="form-group">
<label for="page">Description: Specifies page to return if paging is selected. Defaults to no paging.</label>
<input type="text" class="form-control" id="input7" aria-describedby="page">
</div>
</form>
You were forgetting the #:
$('#tryBTN').click(function () {
for (i = 1; i <= 7; i++) {
var el = $('#input' + i); // <-- The needed `#`
if (el.css('visibility') == 'hidden') {
el.css('visibility', 'visible');
}
}
});
#Intervalia's answer explains the simple error in your code (the missing #), and the comments explain why you should never use eval() unless you absolutely know it's the right tool for the job - which is very rare.
I would like to add a suggestion that will simplify your code and make it more reliable.
Instead of manually setting sequential IDs on each of your input elements, I suggest giving them all a common class. Then you can let jQuery loop through them and you won't have to worry about updating the 7 if you ever add or remove an item.
This class can be in addition to any other classes you already have on the elements. I'll call it showme:
<input type="text" class="form-control showme" aria-describedby="page">
Now you can use $('.showme') to get a jQuery object containing all the elments that have this class.
If you have to run some logic on each matching element, you would use .each(), like this:
$('#tryBTN').click( function() {
$('.showme').each( function( i, element ) {
if( $(element).css('visibility') == 'hidden' ) {
$(element).css( 'visibility', 'visible' );
}
});
});
But you don't need to check whether an element has visibility:hidden before changing it to visibility:visible. You can just go ahead and set the new value. So you can simplify the code to:
$('#tryBTN').click( function() {
$('.showme').each( function( i, element ) {
$(element).css( 'visibility', 'visible' );
});
});
And now that the only thing we're doing inside the loop is setting the new visibility, we don't even need .each(), since jQuery will do the loop for us when we call .css(). (Thanks #TemaniAfif for the reminder.)
So the code becomes very simple:
$('#tryBTN').click( function() {
$('.showme').css( 'visibility', 'visible' );
});

Enter Key on Input Automatically Tab to Next Input with Fields in iFrames

I have a form with inputs which also has an iFrame embedded in the form which also has inputs (pseudo HTML):
<input type="text" name="one" value="one" />
<input type="text" name="two" value="two" />
<input type="text" name="three" value="three" />
<iframe
<input type="text" name="bacon" value="bacon">
</iframe>
<input type="text" name="four" value="four" />
<input type="text" name="five" value="five" />
When the user presses tab they are taken from input to input even inside the iframe fields selecting bacon after three. We all love bacon.
I also have some javascript that attempts to focus the next input on enter key:
$(document).ready(function() {
$(document).on('keydown', 'input', function(ev) {
// Move to next on enter
if (ev.which === 13) {
var inputs = $(':tabbable');
var next = inputs.index(this) + 1;
var input = inputs.eq(next == inputs.length ? 0 : next);
input.focus();
return false;
}
});
});
The problem is the javascript enter key code never focuses the bacon field, it will skip right over it. jsfiddle:
https://jsfiddle.net/54n8mqkh/4/
Let's all skip answers that include not using the iFrame. I know it is not an ideal implementation. However, I would accept ANY answer that allows the enter key to move through all the fields consistently including the iframe using any type of javascript. It does not have to be jquery specific.
I have tried a few different approaches to solve this but none I have found works. Thanks in advance to anyone who has a solution.
You need to focus inside of the iframe like so :
var frameBody = $("#IFrame_input").contents().find("input");
frameBody.focus();
I am going to answer my own question - after a few more hours I was able to solve my use case by expanding my selector to include the iframe. Then I build the array of inputs manually and while iterating I checked the node type for an iframe. If / when I encountered an iframe, I did the same select inside the iframe and added the inputs within the iframe:
$(document).ready(function() {
// Parent level helper function
window.tabToNext = function(me) {
var selector = ':tabbable, iframe';
var inputElems = [];
$(selector).each(function(index) {
var nodeName = $(this).prop('nodeName').toLowerCase();
if (nodeName == 'iframe') {
$(this).contents().find(selector).each(function(index) {
inputElems.push(this);
});
} else {
inputElems.push(this);
}
});
var inputs = $(inputElems);
var next = inputs.index(me) + 1;
if (next == inputs.length) next = 0;
var input = inputs.eq(next);
input.focus();
return false;
}
$(document).on('keydown', 'input', function(ev) {
// Move to next on enter
if (ev.which === 13) {
return window.tabToNext(this);
}
});
// Focus the first input
$('input[name=one]').focus();
});
FWIW: I could not just expand the selector as best I could tell and also I tried to use $.add to build the collection starting with an empty jQuery collection:
var foo = $([]);
foo.add(someElement);
... but it does not honor the order you add. It will re-order to the DOM according to the docs which SEEMS like it should be right, but for some reason my iframe child fields always ended up last and messed up the tab order.
Anyhow, I hope if someone else has this issue some day you find this helpful. Working solution:
https://jsfiddle.net/wbs1zajs/6/

Increment input value using mouse wheel

I'm trying to increase/decrease the value of input field using mouse wheel. I've put together the following code. It's working fine, but there's a small problem.
The behaviour I want is to be able to increment/decrement the input value using mouse wheel once I focus on the element. Mouse doesn't have to be hovering the element. The following code performs this. But if I use wheel while hovering the input element, the value is incremented/decremented by 2 instead of 1.
var hoveredInput = null;
$('input[type="number"]').on("focus", function(e) {
hoveredInput = this;
});
$('input[type="number"]').on("blur", function(e) {
hoveredInput = null;
});
$(window).on("wheel", function(e) {
if (hoveredInput) {
if (e.originalEvent.deltaY < 0) {
var currentValue = parseInt(hoveredInput.value, 10);
var newValue = currentValue + 1;
if (newValue > parseInt(hoveredInput.max, 10)) {
newValue = hoveredInput.max;
}
hoveredInput.value = newValue;
} else {
var currentValue = parseInt(hoveredInput.value, 10);
var newValue = currentValue - 1;
if (newValue < parseInt(hoveredInput.min, 10)) {
newValue = hoveredInput.min;
}
hoveredInput.value = newValue;
}
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="number" value="0" min="0" max="255" />
After some experimenting, I figured that there's a similar behaviour for up and down arrow keys. Up and down arrow keys, on a number input, increments/decrements the value. And I suppose, this behaviour conflicts with my code. Causes it to increment by 2, even though the code doesn't execute twice.
I've just realized that this might be a Chrome specific problem. Chrome let's you increment/decrement number input value using mouse wheel if you focus and hover the element. However, it works in a really weird way.
If I just add <input type="number" /> in a blank HTML page, this mouse wheel increment doesn't work. To make it work, I simply add window.onwheel = function() {};. This doesn't make any sense. Also this seems to work on JSFiddle and JSBin without onwheel assignment on the window.
Going back to the actual problem, can I disable the default mouse wheel increment on the element, so that I can use my custom one? Or is there another approach that I can use?
I'm not sure why you would be considering not using preventDefault() to prevent the default action. You are changing what the UI action will be under these circumstances. You should, of course, use preventDefault() to prevent the default action. If you don't use preventDefault() then there would be some unexpected consequences to using the scroll wheel when the <input type="number"> is focused. Without preventDefault(), what combination of unexpected consequences would occur under those conditions will depend on the browser that is being used to view the page.
I am unable to duplicate a conflict with using the cursor keys to change the input value. Obviously, if all you are using to limit the minimum and maximum values of the <input> is the code for the mouse wheel, then those limits will not function for any other method of entry. You could use the min and max attributes for limiting values. Doing so would be better for multiple reasons, including that it affects all methods of entering a value and as it allows defining those ranges per <input> instead of one set of limits for all <input type="number">. I have changed the code so that your code also uses these attributes.
If you do this, you may want to consider adding a CSS style to indicate that the <input type="number"> element has focus. Doing so will make it more clear to the user why the mouse wheel is not doing what they normally expect from their browser's UI.
I suggest you try this with multiple browsers to see if it is something you desire. Personally, at least in the testing I have done on this page, I like the behavior.
NOTE:
Your use of the focus and blur events is overly complex. I have changed the code to directly find the focused element using document.activeElement.
//Exclude one specific element for comparing this UI vs. the browser's default.
var excludedEl = document.getElementById('exclude');
$(window).on("wheel", function(e) {
focusedEl = document.activeElement;
if(focusedEl === excludedEl){
//Exclude one specific element for UI comparison
return;
}
if (focusedEl.nodeName='input' && focusedEl.type && focusedEl.type.match(/number/i)){
e.preventDefault();
var max=null;
var min=null;
if(focusedEl.hasAttribute('max')){
max = focusedEl.getAttribute('max');
}
if(focusedEl.hasAttribute('min')){
min = focusedEl.getAttribute('min');
}
var value = parseInt(focusedEl.value, 10);
if (e.originalEvent.deltaY < 0) {
value++;
if (max !== null && value > max) {
value = max;
}
} else {
value--;
if (min !== null && value < min) {
value = min;
}
}
focusedEl.value = value;
}
});
input[type="number"]:focus {
box-shadow: 0px 0px 1.5px 1px cyan;
}
/*For comparing UIs: May conflict with browser default, or user's theme.*/
#exclude:focus {
box-shadow: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
NOTE: Events are only caught while the mouse stays within the test portion of the stackoverflow page:<br/><br/><br/>
Uses changed UI (if focused, mouse wheel will increment/decrement):<br/>
<input type="number" value="0" id="firstNumberInput" min="0" max="255"/>
<br/>Uses browser default UI:
<input id="exclude" type="number" value="0" min="0" max="255" style="display:block"/>

Jquery changing css and form data

I'm making a form where the users fill in a title which they can size up or down. I have a preview window that changes when they click on the "size up button". But I want to store this in a hidden form to get the value when posting.
HTML - FORM
<input id="title" name="title" />
<input id="titlesize" name="titlesize" value="50" />
<div id="sizeUp">Size up!</div>
HTML - PREVIEW WINDOW
<h2 id="titlepreview" style="font-size: 50px;">Title</h2>
Javascript
$(document).ready(function() {
$("#sizeUp").click(function() {
$("#titlepreview").css("font-size","+=5"),
$("#titlesize").val("+=5"); // <-- Here's the problem
});
Any ideas?
Try this using the .val( function(index, value) ):
$(document).ready(function () {
$("#sizeUp").click(function () {
$("#titlepreview").css("font-size", "+=5"),
$("#titlesize").val(function (index, value) {
return parseInt(value, 10) + 5;
});
});
});
FIDDLE DEMO
You need parseInt to handle strings as numbers.
$("#sizeUp").click(function () {
var obj = $("#titlesize");
var value = parseInt(obj.val());
obj.val(value + 5);
});
OK, I'm not entirely sure where the problem is here, but here's a way of going about it anyway:
If you want a range of sizes so you can't get a title too big or small, you could (while this is long-winded) make a css class for each size.
Then, you could use JqueryUI's .addClass() and .removeClass. With these you could do something like:
$("#sizeupbutton").click(function(e){
$(#title).removeClass("size45");
$(#title).addClass("size50");
});
Sorry if I've completely got your question wrong, but good luck!
Edit: OK, now i think i understand what you want, I would advise you check out Vucko's answer below.
you can get variable like this:
$(document).ready(function () {
$("#sizeUp").click(function () {
$("#titlepreview").css("font-size", "+=5");
var up=parseInt(($("#titlepreview").css("font-size")),10);
$("#titlesize").val(up);
});
});
example:fiddle

Jquery limit text in input box

I want to limit number of chars in input text field.
Code I'm using:
function limitText(field, maxChar){
if ($(field).val().length > maxChar){
$(field).val($(field).val().substr(0, maxChar));
}
}
Event is onkeyup.
When I type some text in input field cursor stays on the end of text but focus is backed on start of the text so I can't see cursor.
What can be a problem.
Browser is FF, on IE and chrome it is working correctly
you can also do it like this:
<input type="text" name="usrname" maxlength="10" />
to achieve this with jQuery, you can do this:
function limitText(field, maxChar){
$(field).attr('maxlength',maxChar);
}
Your code is working in FF. Here is slightly modified version of your code:
$('input.testinput').on('keyup', function() {
limitText(this, 10)
});
function limitText(field, maxChar){
var ref = $(field),
val = ref.val();
if ( val.length >= maxChar ){
ref.val(function() {
console.log(val.substr(0, maxChar))
return val.substr(0, maxChar);
});
}
}
Demo

Categories