See for a B4JS introduction: https://www.b4x.com/android/forum/threads/abmaterial-b4js-0-9.90249/
Note: for this tutorial, I may use some typical ABM things. You can ignore them as they are just to show the result of the code in this tutorial.
-------------------------------------------------------------------------------
This is another one of those fantastic B4X features that I wanted in B4JS: Inline Javascript.
Just like its big brothers, you can easily put javascript functions in a B4JS class. This last part is important: it will ONLY work in a B4JS class. But, as we will see further, you will be able to call the method in your normal ABM Page class.
So, suppose we found a nice method in Javascript to check a credit card. In your B4JS class, you can use #If JAVASCRIPT and #End If to define a javascript region. You can add multiple methods in one block if you want.
The result in the browsers console:
Pretty cool no?
A couple of things we see here in the code (besides the #if JAVASCRIPT part.
1. Calling a javascript function in your B4JS code using Page.B4JSRunInlineJavascriptMethod:
It is VERY important (unlike we are used in B4J, that the method name (here validateCCNum) matches the case. e.g. VAlidateCCNum will NOT work!
2. Calling a B4JS function in your B4JS code using Page.B4JSRunMethod:
And we're back on familiar B4X ground The case of the method (or class) does not matter as all is lowercased anyway. Why do we have to mention the class, I hear you think. Well this is because we can call a method from ANOTHER B4JS class too!
And moreover, we can also call these methods in our normal ABM webpage!
So the result of method 1 (in the Browser log)
And the result of method 2 (in the B4J log)
In the next tutorial (04 - Running Javascript on the server side) I'll show how you can even run this on the server side, not even needing a browser open.
A final note: #if JAVASCRIPT regions do not really belong to the class. They are shared between all B4JS classes you create.
This concludes this tutorial.
Alwaysbusy
Note: for this tutorial, I may use some typical ABM things. You can ignore them as they are just to show the result of the code in this tutorial.
-------------------------------------------------------------------------------
This is another one of those fantastic B4X features that I wanted in B4JS: Inline Javascript.
Just like its big brothers, you can easily put javascript functions in a B4JS class. This last part is important: it will ONLY work in a B4JS class. But, as we will see further, you will be able to call the method in your normal ABM Page class.
So, suppose we found a nice method in Javascript to check a credit card. In your B4JS class, you can use #If JAVASCRIPT and #End If to define a javascript region. You can add multiple methods in one block if you want.
B4X:
Public Sub InitializeB4JS
Page.B4JSRunMethod("B4JSCalculateDistance", "cHECKCard", Array As String("5105105105105100"))
Page.B4JSRunMethod("B4JSCalculateDistance", "CheckCard", Array As String("111111"))
End Sub
public Sub CheckCard(cardNumber As String)
Dim isValid As Boolean = Page.B4JSRunInlineJavascriptMethod("validateCCNum", Array As Object(cardNumber))
If isValid Then
Log("Card '" & cardNumber & "' is a valid card. Please continue...")
Else
Log("Card '" & cardNumber & "' is NOT valid. Please check the number...")
End If
End Sub
#If JAVASCRIPT
function validateCCNum(ccnum) {
var ccCheckRegExp = /[^\d\s-]/;
var isValid = !ccCheckRegExp.test(ccnum);
var i;
if (isValid) {
var cardNumbersOnly = ccnum.replace(/[\s-]/g,"");
var cardNumberLength = cardNumbersOnly.length;
var arrCheckTypes = ['visa', 'mastercard', 'amex', 'discover', 'dinners', 'jcb'];
for(i=0; i<arrCheckTypes.length; i++) {
var lengthIsValid = false;
var prefixIsValid = false;
var prefixRegExp;
switch (arrCheckTypes[i]) {
case "mastercard":
lengthIsValid = (cardNumberLength === 16);
prefixRegExp = /^5[1-5]/;
break;
case "visa":
lengthIsValid = (cardNumberLength === 16 || cardNumberLength === 13);
prefixRegExp = /^4/;
break;
case "amex":
lengthIsValid = (cardNumberLength === 15);
prefixRegExp = /^3([47])/;
break;
case "discover":
lengthIsValid = (cardNumberLength === 15 || cardNumberLength === 16);
prefixRegExp = /^(6011|5)/;
break;
case "dinners":
lengthIsValid = (cardNumberLength === 14);
prefixRegExp = /^(300|301|302|303|304|305|36|38)/;
break;
case "jcb":
lengthIsValid = (cardNumberLength === 15 || cardNumberLength === 16);
prefixRegExp = /^(2131|1800|35)/;
break;
default:
prefixRegExp = /^$/;
}
prefixIsValid = prefixRegExp.test(cardNumbersOnly);
isValid = prefixIsValid && lengthIsValid;
// Check if we found a correct one
if(isValid) {
break;
}
}
}
if (!isValid) {
return false;
}
// Remove all dashes for the checksum checks to eliminate negative numbers
ccnum = ccnum.replace(/[\s-]/g,"");
// Checksum ("Mod 10")
// Add even digits in even length strings or odd digits in odd length strings.
var checksum = 0;
for (i = (2 - (ccnum.length % 2)); i <= ccnum.length; i += 2) {
checksum += parseInt(ccnum.charAt(i - 1));
}
// Analyze odd digits in even length strings or even digits in odd length strings.
for (i = (ccnum.length % 2) + 1; i < ccnum.length; i += 2) {
var digit = parseInt(ccnum.charAt(i - 1)) * 2;
if (digit < 10) {
checksum += digit;
} else {
checksum += (digit - 9);
}
}
return (checksum % 10) === 0;
}
#End If
The result in the browsers console:
B4X:
Card '5105105105105100' is a valid card. Please continue...
Card '111111' is NOT valid. Please check the number...
Pretty cool no?
A couple of things we see here in the code (besides the #if JAVASCRIPT part.
1. Calling a javascript function in your B4JS code using Page.B4JSRunInlineJavascriptMethod:
B4X:
Dim isValid As Boolean = Page.B4JSRunInlineJavascriptMethod("validateCCNum", Array As Object(cardNumber))
It is VERY important (unlike we are used in B4J, that the method name (here validateCCNum) matches the case. e.g. VAlidateCCNum will NOT work!
2. Calling a B4JS function in your B4JS code using Page.B4JSRunMethod:
B4X:
Page.B4JSRunMethod("B4JSCalculateDistance", "cHECKCard", Array As String("5105105105105100"))
And we're back on familiar B4X ground The case of the method (or class) does not matter as all is lowercased anyway. Why do we have to mention the class, I hear you think. Well this is because we can call a method from ANOTHER B4JS class too!
And moreover, we can also call these methods in our normal ABM webpage!
B4X:
sub ConnectPage()
...
' method 1: calling our own B4JS sub and handeling the result on thebrowser side
page.B4JSRunMethod("B4JSCalculateDistance", "cHECKCard", Array As String(CardNumber))
' method 2: directly calling the Javascript function and handeling the result on the server side
Dim isValid As Boolean = page.B4JSRunInlineJavascriptMethod("validateCCNum", Array As Object(CardNumber))
If isValid Then
Log("Server Card '" & CardNumber & "' is a valid card. Please continue...")
Else
Log("Server Card '" & CardNumber & "' is NOT valid. Please check the number...")
End If
...
End Sub
So the result of method 1 (in the Browser log)
B4X:
Card '5105105105105100' is a valid card. Please continue...
Card '111111' is NOT valid. Please check the number...
And the result of method 2 (in the B4J log)
B4X:
Server Card '5105105105105100' is a valid card. Please continue...
In the next tutorial (04 - Running Javascript on the server side) I'll show how you can even run this on the server side, not even needing a browser open.
A final note: #if JAVASCRIPT regions do not really belong to the class. They are shared between all B4JS classes you create.
This concludes this tutorial.
Alwaysbusy
Last edited: