Exit
  • Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
  • 한국 커뮤니티
0

JavaScript question re: calculating BMI

Community Beginner ,
Mar 08, 2018 Mar 08, 2018

I am by no means a programmer but I've been fooling around with JavaScript a little and had enough success to whet my appetite. So I thought this would be a fairly simple problem.

I have a couple of text entry boxes, one of which has a variable, v_Ht and the other which has a variable, v_Wt associated with it. When a slide enters, I want the BMI to appear in a text caption. Here is the JavaScript I've attached to On Enter for that slide:

Height = window.cpAPIInterface.getVariableValue('v_Ht');

Weight = window.cpAPIInterface.getVariableValue('v_Wt');

Kiloweight = Weight * 0.45;

HeightMeters = Height * 0.025;

HeightMetersSquared = HeightMeters * HeightMeters;

BMI = Kiloweight / HeightMetersSquared;

window.cpAPIInterface.setVariableValue('v_BMI', BMI); 

I have created a Captivate variable for BMI as well (v_BMI). What's appearing in the text caption is NaN, which I believe means that the result is not a number. I'm really puzzled as to why I'm getting this result when I followed a similar procedure (successfully) to calculate tax and a discount on a product.

782
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines

correct answers 1 Correct answer

Engaged , Mar 08, 2018 Mar 08, 2018

Your entry box text is a string object by default.

You've got [at least] two options:

Cast your v_Ht and vWt variables as Number datatypes:

Height = Number(window.cpAPIInterface.getVariableValue('v_Ht'));

Weight = Number(window.cpAPIInterface.getVariableValue('v_Wt'));

or

Change your entry box to use numbers:

Style>More Options>Numbers option

Translate
Community Expert ,
Mar 08, 2018 Mar 08, 2018

I am not at all a JS expert, but I believe you have to convert the value of the variable which you get from Captivate's TEB's to a number with the function number(). By default any entry in the TEB is a string.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Beginner ,
Mar 08, 2018 Mar 08, 2018

Thanks for you quick response. You know I thought that might be the case (although I didn't do that when calculating sales tax and a discount on a product previously and it still worked). But I thought I'd try it again, and assuming I did this correctly (I added these two lines after the first two lines and made sure to change the variable names on the subsequent two lines):

NHeight = Number(Height);

NWeight = Number(Weight);

It still didn't work. It's really weird because I definitely had this working in a previous, similar scenario and I can't figure out what's different here.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Engaged ,
Mar 08, 2018 Mar 08, 2018

Your entry box text is a string object by default.

You've got [at least] two options:

Cast your v_Ht and vWt variables as Number datatypes:

Height = Number(window.cpAPIInterface.getVariableValue('v_Ht'));

Weight = Number(window.cpAPIInterface.getVariableValue('v_Wt'));

or

Change your entry box to use numbers:

Style>More Options>Numbers option

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Engaged ,
Mar 08, 2018 Mar 08, 2018

I crossed paths with Lieve's answer...I did a test with what I had done prior to posting and it worked.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Beginner ,
Mar 08, 2018 Mar 08, 2018

Thanks to you both. I decided to go with the number function after all (even though the other option - choosing number format worked as well). I found a more accurate BMI formula:

Height = Number(window.cpAPIInterface.getVariableValue('v_Ht'));

Weight = Number(window.cpAPIInterface.getVariableValue('v_Wt'));

//Kiloweight = Weight * 0.45;

//Kiloweight = Kiloweight.toFixed(2);

Weight = Weight * 703

//HeightMeters = Height * 0.025;

//HeightMeters = HeightMeters.toFixed(2);

newHeight = Height * Height;

BMI = Weight / newHeight;

BMITrimmed = BMI.toFixed(1)

window.cpAPIInterface.setVariableValue('v_BMI', BMITrimmed);

And I used an advanced action to run the JavaScript on tab one and on tab two I used a conditional action to display the value in red if it was over 25, black if it was under. Worked nicely . . . thanks to you again.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Engaged ,
Mar 09, 2018 Mar 09, 2018

You're welcome. That's just one of the great things about using Captivate...you've always got multiple ways to achieve the same goal.

Good thinking on changing the colors. The more clear things are for the learner, the better.

Thanks for sharing your code, too. This Community is such a valuable resource. I've learned so much from everyone.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Beginner ,
Mar 12, 2018 Mar 12, 2018

Sorry to be a pain, but I thought I'd take my little project a bit further and try the same thing with a blood pressure vital, thinking that this would be a bit more challenging, but it turned out to be a bit too challenging for my meager skills. This is what I came up with:

BP = String(window.cpAPIInterface.getVariableValue('v_BP'));

BPSystolic = BP.slice(0, 3);

BPDiastolic = BP.slice(4, 6);

BPSystolicNumber = Number(BPSystolic);

BPDiastolicNumber = Number(BPDiastolic);

window.cpAPIInterface.setVariableValue('v_BPDiastolic', BPDiastolicNumber);

window.cpAPIInterface.setVariableValue('v_BPSystolic', BPSystolicNumber);

The Captivate variable, v_BP is what's entered in a text entry field on the previous slide. I didn't define the variable type in Captivate (Allow All). At least I'm not getting the dreaded NaN message. I'm seeing 0 for both variables (v_BPDiastolic/Systolic) when I view them each in a text caption, because those were the values I originally entered for each. This script runs on entry.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Engaged ,
Mar 12, 2018 Mar 12, 2018

I used your code and created a two slide test, and I am not getting a zero result for either value. Having said that, it's probably not the best approach for a couple of reasons. For instance, if I have low BP, and input 99/80, you'll get NaN for systolic because you're including the slash in BPSystolic var. Also, 190/100 will truncate the diastolic number.

I don't know if this is for your own knowledge or an actual project, but I think a more efficient way to handle this is by using a function and passing two variables. One for systolic and one for diastolic. As it is, you're depending on the user to format the string properly with no absolutely no validation. You could again setup two TEBs, restrict to numbers (or cast as number), and do something like this in JS:

function setBp(systolic, diastolic)

{

    numSystolic = systolic;

    numDiastolic = diastolic;

    return("Your blood pressure is: " + numSystolic + " / " + numDiastolic);

}

After the user enters their numbers, you store the results in a variable:

var myBp setBp(v_BPSystolic, v_BPDiastolic);

user enters 120 for systolic, 80 for diastolic result:

// Your blood pressure is: 120 / 80

Not sure if this helps or hurts, but it's a lot more efficient.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Beginner ,
Mar 12, 2018 Mar 12, 2018

Thanks - I'm just using the project to get a better idea of how to use JS with Captivate and to educate myself. You are no doubt right - I forgot about the two possibilities you mentioned. Your solution makes a lot of sense, but not in this case, because the user has to enter both the systolic and diastolic values in one TEB. But it's a good first lesson in using functions. Once again, thanks for taking the time to help a JS neophyte, with the emphasis on neo.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Engaged ,
Mar 12, 2018 Mar 12, 2018

I have a typo:

var myBp setBp(v_BPSystolic, v_BPDiastolic);

should be:

var myBp = setBp(v_BPSystolic, v_BPDiastolic);

You would have a textbox with $$myBp$$ to show the results on screen.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Engaged ,
Mar 12, 2018 Mar 12, 2018

I would split on the "/" character and not use hard numbers then. You'll get an array of whatever is ahead of the slash and whatever is at the end.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Beginner ,
Mar 12, 2018 Mar 12, 2018

I'm not sure what that means - do you mean find the / character and assign the characters to the left and right to 2 variables in some way? How is that done?

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Engaged ,
Mar 12, 2018 Mar 12, 2018

    var yourString = "120/80";

    var stringBP = yourString.split("/");

    var systolic = stringBP[0];

    var diastolic = stringBP[1];

of course, yourString, in your case would be the user entry variable.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Beginner ,
Mar 13, 2018 Mar 13, 2018
LATEST

Thanks so much - it works! I wasn't aware of the split function, because, strangely, it wasn't mentioned in the JS manual I was referring to, but it sure does make life simple for situations like this one.

One odd thing I noticed with the TE field (and this was by accident): in the window that appears when you click on More options I had Auto Submit checked (for my blood pressure Captivate variable - v_bloodPressure), even though that checkbox was greyed out. So, on a whim, I unchecked it, because my Captivate variables weren't displaying on the entry of the slide comprising your JS code. Lo and behold it worked!

This has been a very educational experience for me and once again thanks for all your help.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Resources
Help resources