cancel
Showing results for 
Search instead for 
Did you mean: 
cancel
Showing results for 
Search instead for 
Did you mean: 

Community Tip - Did you get called away in the middle of writing a post? Don't worry you can find your unfinished post later in the Drafts section of your profile page. X

MathCAD Prime 10 - Advanced Controls - ES6 JavaScript Methods

TK421
3-Newcomer

MathCAD Prime 10 - Advanced Controls - ES6 JavaScript Methods

I just got a hold of MCP10 and started playing around with the new Advanced Controls.

 

It appears that these controls are using Microsoft's Jscript version 5.8.  This is semi-equivalent to JavaScript/ES3 which is 11 versions behind the current version.  There are a lot of missing features that are commonly used in modern JavaScript, and I would like to at least upgrade to ES6.

 

I was able to add the methods for working with JSON using this code in the TextBoxEvent_Start function to download and execute the json3 polyfill...

 

 

 

var xhr = new ActiveXObject("Msxml2.XMLHTTP");
xhr.onreadystatechange = function(){ if(xhr.readystate == 4){ eval(xhr.responseText) } }
xhr.open("GET", "https://cdnjs.cloudflare.com/ajax/libs/json3/3.3.2/json3.min.js");
xhr.send();

 

 

 

Tangent: Yes, I know eval() is evil, and this opens me up to security risks if cloudflare ever starts sending me something malicious instead of the json3 polyfill.  If anyone has a safer solution I am happy to hear it.

 

...but I haven't been able to get a shim working so I can use other missing methods such as string.includes(), array.find(), etc., etc.  I even tried shimming ES5 before I shimmed ES6 but no go... I get the "Object doesn't support this property or method" error at line 18 where I try to use Outputs[0].Value = myString.includes("world");

 

 

 

function TextBoxEvent_Start(Inputs, Outputs) {
    var xhr = new ActiveXObject("Msxml2.XMLHTTP");
    xhr.onreadystatechange = function(){ if(xhr.readystate == 4){ eval(xhr.responseText) } }
    xhr.open("GET", "https://cdnjs.cloudflare.com/ajax/libs/es5-shim/4.5.14/es5-shim.min.js");
    xhr.send();
    xhr.open("GET", "https://cdnjs.cloudflare.com/ajax/libs/es6-shim/0.35.5/es6-shim.min.js");
    xhr.send();
};

function TextBoxEvent_Exec(Inputs, Outputs) {
    var myString = "Hello world, welcome to the universe.";
    Outputs[0].Value = myString.includes("world");
};

function TextBoxEvent_Stop(Inputs, Outputs) {
};

 

 

 

Anyone have any ideas on how I could get ES6 methods working? 

 

Update: ES5 methods work (tried string.trim), just not ES6 methods.

5 REPLIES 5
StuartBruff
23-Emerald III
(To:TK421)

Very interesting.  This almost makes JScript worth learning!  

 

However, after just a few minutes of playing around I've encountered several other problems when using a TextBox control.

 

1.  The const keyword isn't supported.

2.  String.codepoint() isn't supported.

 

I don't know how to:

 

3.  Create multiline JScript strings.

4.  Create arguments of the form "string": x in Mathcad and pass them to the control.  I could play around with parsing inputs, but that rather defeats the point of the exercise.

 

The control doesn't seem to like nested arrays as an input argument, either - throws an exception with references to a non-existent code line; it doesn't seem to matter is the nested array is regular in shape or irregular.

 

Perhaps time, the random bashing of keys, and meditation upon a Himalayan mountain top will bring enlightenment ... although, I suspect anoxia is more likely. 

 

Stuart

TK421
3-Newcomer
(To:StuartBruff)

Yeah, const, [string].codePointAt()[string].codePointFrom() are all from ES6.  You would need to find or write a shim to get that functionality.  Unfortunately there doesn't seem to be much in the way of shims for JScript.  Some Javascript ones work, but most fail.  I haven't found one that includes any functionality above ES5 that works,

 

I'm not 100% sure what you mean by multiline strings....

To get multiline text output from your JScript you can add a newline character "\n" to your string:

 

TextBox.Text("This is the first line. \n This is the second line.")

 

Just make sure that the Multiline box is checked on the Properties tab of your Text Box.

 

To break a string variable over multiple lines so it is more readable in your script you would type:

 

myString = "This is multiple lines in your code,";
myString += " but will be returned to the TextBox as one line";

 

 

String template literals that use the backtick character in place of the quotes and give you the ability to insert variable values into the string is an ES6 feature and you would need a working shim for that.

 

As far as passing objects from MathCad to your JScript, I would recommend:

  1. Add a JSON shim in your _Start function for your Advanced Control
  2. Create a MathCad string in the format of a JSON object literal, except you will have to use something other than double quotes around the labels.  I used single quotes in this example, but any character or substring that isn't used for anything else in the object literal works just as well.  my Object Literal string looks like myJSON:="{'foo': 'hello world'}" in MathCad.
  3. Pass that string as an input to your Advanced Control
  4. Read the input with JScript, use a Regular Expression to globally replace the single quotes with double quotes, then parse it with JSON.parse()

 

function TextBoxEvent_Start(Inputs, Outputs) {
	var xhr = new ActiveXObject("Msxml2.XMLHTTP");
	xhr.onreadystatechange = function(){ 
		if(xhr.readystate == 4){
			var res = eval(xhr.responseText);
			TextBox.Text( TextBox.Text() += "\n" + res )
		}
	}
	xhr.open("GET", "https://cdnjs.cloudflare.com/ajax/libs/json3/3.3.2/json3.min.js")
	xhr.send();
};

function TextBoxEvent_Exec(Inputs, Outputs) {
	var myJSON = Inputs[0].Value
	myJSON = myJSON.replace(/'/g,'"')
	var myObj = JSON.parse(myJSON);
	TextBox.Text(myObj.foo);
};

function TextBoxEvent_Stop(Inputs, Outputs) {
};

 

 

StuartBruff
23-Emerald III
(To:TK421)


@TK421 wrote:

Yeah, const, [string].codePointAt()[string].codePointFrom() are all from ES6.  You would need to find or write a shim to get that functionality.  Unfortunately there doesn't seem to be much in the way of shims for JScript.  Some Javascript ones work, but most fail.  I haven't found one that includes any functionality above ES5 that works,

 

I'm not 100% sure what you mean by multiline strings....

I meant strings of the form:

 

var jsonText = `{
  "browsers": {
    "firefox": {
      "name": "Firefox",
      "pref_url": "about:config",
      "releases": {
        "1": {
          "release_date": "2004-11-09",
          "status": "retired",
          "engine": "Gecko",
          "engine_version": "1.7"
        }
      }
    }
  }
}`;

 

From the next part of your message, am I right in thinking that is an example of a string template literal that uses the backtick character?

 

I shall read the rest of your message carefully and see what I can do.  My Javascript knowledge is pretty minimal as I've never had much cause to use it.

 


@TK421 wrote:

To get multiline text output from your JScript you can add a newline character "\n" to your string:

 

TextBox.Text("This is the first line. \n This is the second line.")

 

Just make sure that the Multiline box is checked on the Properties tab of your Text Box.

 

To break a string variable over multiple lines so it is more readable in your script you would type:

 

myString = "This is multiple lines in your code,";
myString += " but will be returned to the TextBox as one line";

Yes, I already do that, thanks.  However, LF didn't consistently appear in a string returned from a control. 

 

Interestingly, LF, CR, and TAB work as you might expect hope when viewing Mathcad strings.  

 

2024 10 17 E.png

 

Stuart

TK421
3-Newcomer
(To:StuartBruff)

That nested array thing is pretty weird.  Even if you have no code whatsoever it gives an error on a non-existent line.  You would think that PTC would catch that error and return a message that is descriptive of the fact that they haven't implemented that functionality.

 

My first thought for a work-around would be to use a program in MathCad to convert the nested array into a JScript Array Literal string and then JSON.parse to get the values - just like with the Object Literal string.

StuartBruff
23-Emerald III
(To:TK421)


@TK421 wrote:

That nested array thing is pretty weird.  Even if you have no code whatsoever it gives an error on a non-existent line.  You would think that PTC would catch that error and return a message that is descriptive of the fact that they haven't implemented that functionality.


Yes, passing complex data structures into an advanced control must surely be a necessity for many use cases?  Passing strings into a control and then parsing them smacks entirely too much of buy dog, bark self syndrome ..,  

 


@TK421 wrote:

My first thought for a work-around would be to use a program in MathCad to convert the nested array into a JScript Array Literal string and then JSON.parse to get the values - just like with the Object Literal string.


... although using JSON methods should let me bark-share with the "dog".

 

Converting a nested array to a string is worth trying.  I have an old M11..15 worksheet that has a string parser for interpreting Matlab arrays.  I might even be able to find it some year soon!

 

Stuart

Announcements

Top Tags