Link to home
Start Free TrialLog in
Avatar of badwolfff
badwolfffFlag for United Kingdom of Great Britain and Northern Ireland

asked on

With jQuery how do I change the class of a read-only input field in real-time if it's value becomes negative or positive?

I have a formula made with jcalx on http://demo.missionfamily.org/formula/

There is a read-only field marked ##A13## which displays calculations based on other fields of the equation.
The values in that field are either negative or positive depending on whether the company is making profit or loss.

What I would like to do it make it's background red when the value in it becomes negative and return it to normal when it is positive (basically assign it a class in real-time and take it out in the same way).

If you follow this example you can get positive or negative results:

1.

When you load the page the value is positive so set class 'positive'

2.

Just change the value ni ##A9## to 20 and the value in ##A13## will become negative so set class negative
Please remember that various other combinations of the formula would produce negative results in ##A13## so all have to be considered. Realistically I need the check to be made onBlur of every field that can be edited.

thanks in advance
Avatar of Julian Hansen
Julian Hansen
Flag of South Africa image

So if I understand you, you want to check each text box when a change is made to any text box and set the corresponding <span> that contains the text box to red when the value of the text box is < 0.

So something like this (off the top of my head - I have not tested it so you might have to tweak it)
$('input[type=text]').blur(function() {
  $('input[type=text]:disabled').each(function() {
      if (parseFloat($(this).val()) < 0) {
          $(this).closest('span').addClass('showred');
      }
     else {
          $(this).closest('span').removeClass('showred');
    }
  });
});

Open in new window

Avatar of badwolfff

ASKER

Thanks for the answer. You are slightly off. I need to test all fields for input but the only field that needs to be set as red (class set to negative) or not (class set to positive) is the A13 field ONLY if its value is negative.
Basically any time value in field A13 becomes negative add class "negative" and when it becomes positive add class "positive".

Of course a value change in A13 can only occur if any of the other field values are updated.
I need to test all fields for input but the only field that needs to be set as red (class set to negative) or not (class set to positive) is the A13 field ONLY if its value is negative.

So what you are saying is always check A13 on a blur of any field
Then how about this

$('input[type=text]').blur(function() {
    if ($('#guadagno').val() < 0) {
       $('#guadagnovero').addClass('showred');
    }
    else {
       $('#guadagnovero').removeClass('showred');
    }
});

Open in new window

Hi,

I tried it. Doesn't work. Also you are considering only the inputs of text type, what about other input types like selectors?

I made a few modifications to your code and still it doesn't work properly - sometimes it does and sometimes it doesn't.
$('input, select').blur(function() {
	window.console&&console.log('form updated');
    if ($('#guadagno').val() < 0) {
		window.console&&console.log('value less than 0');
		$('#guadagno').css({'color':'#fff','background-color':'#F00'});
    }
    else {
		window.console&&console.log('value more than 0');
       $('#guadagno').css({'color':'#666','background-color':'#F0F0F0'});
    }
});	

Open in new window


Try it online on my site please.

If you put in a value or select any dropdown that makes the value in A13 negative, the first time the console log tells that the value is still positive even though the value is negative. If you then go and do anything else that will keep the value negative it will turn red. And vice versa. So I have a feeling that the IF/ELSE are happening too fast. Maybe a delay might help? Any suggestions?
Attaching files here: formula.zip
The blur is happening before the change.

What you need to do is trigger a change event after setting the value for A13.

Where is the code that is setting the Value of A13?
.. forgot to add - once you have found that you can do a trigger change on this code

	$('#guadagno').change(function() {
		if (parseFloat($(this).val()) < 0) {
			$(this).closest('span').addClass('showred');
		}
		else {
			$(this).closest('span').removeClass('showred');
		}
	});

Open in new window

A13 input filed has a data-formula:

<input id="guadagno" type="text" data-cell="A13" data-format="0,0.00" data-formula="(((A2/A4)*A6)*(1-  ((SUM(A7:A9)) + (A10*A32*A33))  ))-(A2/A4)-A12" disabled>

That is setting its value using jquery calx.
Thanks. I used your idea and applied it laterally with an idea of mine and it works now.
Your code did not work out of the box as it failed to indicate when value in A13 was changing.

This is how I did it:

/* START: If client is losing money set guadagno to red */
function checkGuadagno(selector, callback) {
   invalue = $(selector);
   existingvalue = invalue.val();
   setInterval(function(){
	  if (invalue.val()!=existingvalue){
		  existingvalue = invalue.val();
		  callback();
	  }
   }, 100);
}

checkGuadagno('#guadagno', function()
{
	window.console&&console.log('form updated');
	if (parseFloat($('#guadagno').val()) < 0) {
		window.console&&console.log('value less than 0');
		$('#guadagno').css({'color':'#fff','background-color':'#F00', 'border':'1px solid #999'});
	}
	else {
		window.console&&console.log('value more than 0');
		$('#guadagno').css({'color':'#666','background-color':'#F0F0F0', 'border':'1px solid #999'});
	}
});
/* END: If client is losing money set guadagno to red */

Open in new window

I've requested that this question be closed as follows:

Accepted answer: 0 points for badwolfff's comment #a40834524
Assisted answer: 500 points for Julian Hansen (JulianH)'s comment #a40834449

for the following reason:

I used an idea that was suggested and made it work with my own code.
Your code did not work out of the box as it failed to indicate when value in A13 was changing.
That was because the calc does not fire a change event on the A13 input. This has to be triggered manually. I have been going through the calcx code looking to see if this is implemented - but was interrupted so have not completed that exercise. Using a timer is one way of doing it but not ideal - the ideal solution is to trigger the change when the calculated value input is set.

Will keep looking and post back if I find something.
Thanks. In any case it works so far. I have tested various scenarios.
I think I found the answer here
http://www.xsanisty.com/project/calx/

The following question was asked in the discussion at the bottom of the page
what kind of event will be triggered after applying the formula IF($B >0,1,2). I am trying to catch the event fired during the auto calculations.
To which the author responds
Hi ks,

currently on 1.1.9 no custom event will be triggered on calculation, but if you don’t mind you can grab the latest development state on github.

you can trigger event on calculation by add onupdate listener

$('#form').calx({
onupdate : function(data){ /** do your stuff here */ }
});

Open in new window

data will be an object containing all cell with it’s unformatted value, e.g data.A1 = 5.9384

If I understand him correclty you can do the following

$('#sheet').calx({
    onupdate: function(date) {
       $('#guadagnovero').removeClass('showRed');
       if (parseFloat(data.A13) < 0){
           $('#guadagnovero').addClass('showRed');
       }
    }
});

Open in new window


Have not tested the above but give it a go and see if it works.
Hi I tried this:

$('#sheet').calx({
    onupdate: function(date) {
		window.console&&console.log('form updated');
		$('#guadagno').css({'color':'#666','background-color':'#F0F0F0', 'border':'1px solid #999'});
		if (parseFloat(data.A13) < 0)
		{
			window.console&&console.log('value less than 0');
			$('#guadagno').css({'color':'#fff','background-color':'#F00', 'border':'1px solid #999'});
       }
    }
});				

Open in new window


It doesn't work. You try it yourself since I provided the code. :(
Nothing gets triggered.
You try it yourself since I provided the code. :(
Sorry code is in a zip and zip files are not generally accepted on EE.

Do you get an error ?
Hi,
sorry about the zip file. I get nothing. The console log is empty.
I am sending the separate files:
index.htmljquery.numeric.min.jsjquery-calx-2.2.2.min.jsnumeral.min.js

The .js files go in a /script folder.

thanks
I will take a look - if it does not work the so be it - the author of the plugin seems to think it does but also says there is no support for catching the event - so it is possible it is not supported in which case you are forced to go the timer route.

I wanted to exhaust these options first before suggesting the timer but you found that on your own.

Give me till tomorrow to take a look at source and see what happens with the onupdate.
Thanks
I remain curious
Ok I found it

The callback to use is onAfterRender
$('#sheet').calx({
	onAfterRender: function() {
		$('#guadagno').css({'color':'#666','background-color':'#F0F0F0', 'border':'1px solid #999'});
		if (this.getCell('A13').getValue() < 0)
		{
			$('#guadagno').css({'color':'#fff','background-color':'#F00', 'border':'1px solid #999'});
       }
    }
});				

Open in new window

Hi, thanks. Tried it. Nothing happens. Nothing gets fired in the console either as I put in a couple of alerts.
Shame really! It looked so promising! I even got all excited when I saw it...
ASKER CERTIFIED SOLUTION
Avatar of Julian Hansen
Julian Hansen
Flag of South Africa image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial