Posts Tagged Javascript

A NetSuite Best Practice – Client JS in Suitelets

Often we need writing Suitelets in Netsuite that have conventional HTML UI elements rather than the objects provided by Netsuite’s UI Builder API. We normally use HTML within javascript string to be sent to client side. To write code against the elements in this HTML, client side javascript also goes within a string. Problems arise when we need to update the code within a string as we are not able to use the features of the IDE to its fullest. This post is all about solving these problems, exploiting the fact that the server-side code written for Suitelets is also in javascript.

The Technique

Good news is that each javascript function object has a toString() method, and a better news is that it works as expected in Netsuite ! :).

So the idea is to write client and server-side code alike and use the toString() method of the client-side functions to aggregate the client-side script.

Example

Lets take a simple scenario. We are creating a user registration form within a Suitelet using plain old HTML form elements.

  • When the user inputs first and last name fields we would like to suggest a user name.
  • When the user inputs a password, we would like to warn if it contains the first or last name.

Here goes the script:

function main(request,response)
{
    response.writeLine(getClientSideCode());
    response.writeLine(getHtml());
}
function getHtml()
{
    var h = '';
    h += 'First Name';
    h += '<input type="text" id="txtFName" onblur="setUserIdFromNames();"/>';
    h += 'Last Name';
    h += '<input type="text" id="txtLName" onblur="setUserIdFromNames();"/>';
    h += 'User Name';
    h += '<input type="text" id="txtUserName" />';
    h += 'Password';
    h += '<input type="password" id="txtPass" onblur="performPasswordSecurityCheck();"/>';
    return h;
}
function getClientSideCode()
{
    var s = '';
    s += '<script type="text/javascript">';
    s += 'function setUserIdFromNames()';
    s += '{';
    s += '  var firstName = document.getElementById("txtFirstName").value;';
    s += '  var lastName = document.getElementById("txtLastName").value;';
    s += '  var userName = firstName.toLowerCase() + \'.\' + lastName.toLowerCase();';
    s += '  document.getElementById("txtUserName").value = userName;';
    s += '}';
    s += 'function performPasswordSecurityCheck()';
    s += '{';
    s += '  var password = document.getElementById("txtPassword").value;';
    s += '  var firstName = document.getElementById("txtFirstName").value;';
    s += '  var lastName = document.getElementById("txtLastName").value;';
    s += '  if(password.indexOf(firstName)!=-1 || password.indexOf(lastName)!=-1)';
    s += '      alert("Using names in password makes it less secure!");';
    s += '}';
    s += '</script>';
    return s;
}

The highlighted lines contain the script that is problematic. Its difficult to read,  refactor and debug.

Here is the improved version of the code:

function getClientSideCode()
{
    var arrFunctions = [setUserIdFromNames,performPasswordSecurityCheck];
    var clientScript = '<script type="text/javascript">';
    for (var i = 0; i < arrFunctions.length; i++)
        clientScript += arrFunctions[i].toString();
    clientScript += '</script>';
    return clientScript;
}

function setUserIdFromNames()
{
    var firstName = document.getElementById('txtFirstName').value;
    var lastName = document.getElementById('txtLastName').value;
    var userName = firstName.toLowerCase() + '.' + lastName.toLowerCase();
    document.getElementById('txtUserName').value = userName;
}

function performPasswordSecurityCheck()
{
    var password = document.getElementById('txtPassword').value;
    var firstName = document.getElementById('txtFirstName').value;
    var lastName = document.getElementById('txtLastName').value;
    if(password.indexOf(firstName)!=-1 || password.indexOf(lastName)!=-1)
        alert('Using names in password makes it less secure!');
}

Notice the changes from the previous version:

  • All the client-side functions now coexist with the server-side code
  • The getClientSideCode() function  has the references of all client side functions. It iterates over all of these to append each to the client-side script.

Pros and Cons

The latter code is much better than the earlier version.

  • The client-side code is easier to maintain. Its free of noisy code/characters like extra semicolons, quotes and annoying escape sequences.
  • One can use the features provided by the IDE to make change in the code such as renaming identifiers and code formatting.

However there are a few limitations to this approach that must be taken care of .

  • The IDE has no means to discriminate between server and client-side functions so the developer has to be careful using intellisense/autocompletion to avoid calling client code in server-side and viceversa.
  • Every time you create/remove a client-side function you need to update the collection of functions(arrFunctions in the code example).
function main(request,response)
{
//response.writeLine(getClientSideCode());
response.writeLine(getHtml());
}function getHtml()
{
var html = ”;
//html += getClientSideCode();
html += ‘<script type=”text/javascript”>’;
html += ‘    function setUserIdFromNames()’;
html += ‘    {‘;
html += ‘        var firstName = document.getElementById(“txtFirstName”).value;’;
html += ‘        var lastName = document.getElementById(“txtLastName”).value;’;
html += ‘        var userName = firstName.toLowerCase() + “.” + lastName.toLowerCase();’;
html += ‘        document.getElementById(“txtUserName”).value = userName;’;
html += ‘    }’;
html += ‘    function performPasswordSecurityCheck()’;
html += ‘    {‘;
html += ‘        var password = document.getElementById(“txtPassword”).value;’;
html += ‘        var firstName = document.getElementById(“txtFirstName”).value;’;
html += ‘        var lastName = document.getElementById(“txtLastName”).value;’;
html += ‘        if(password.indexOf(firstName)!=-1 || password.indexOf(lastName)!=-1)’;
html += ‘            alert(“Using names in password makes it less secure!”);’;
html += ‘    }’;
html += ‘</script>’;
html += ‘<div>’;
html += ‘    First Name<input type=”text” id=”txtFirstName” onblur=”setUserIdFromNames();”/><br />’;
html += ‘    Last Name <input type=”text” id=”txtLastName” onblur=”setUserIdFromNames();”/><br />’;
html += ‘    User Name <input type=”text” id=”txtUserName” /><br />’;
html += ‘    Password  <input type=”password” id=”txtPassword” onblur=”performPasswordSecurityCheck();”/><br />’;
html += ‘    …’;
html += ‘</div>’;
return html;
}

, , , ,

3 Comments

Javascript Gotchas : for vs for…in

Since the day I first acquainted myself with javascript, I thought ‘for’ and ‘for..in’ served pretty much the same purpose. I always considered the latter to be merely of syntactic ease to a developer. Today I found out an important difference between these two constructs.

Suppose we run this code snippet:

var array = [1,2,3,4,5];
array.capacity = 10;

var str = '';
for(var i in array)
  str += array[i];

var str2 = '';
for(i=0; i < array.length; i++)
  str2 += array[i];

So by the end of the code execution, what are the values of str and str2? Before executing this code I always thought both will give the same result but the fact is :
str2 = ‘12345’ while str = ‘1234510’

If the highlighted line(No.2) is removed, both str and str2 give the same value ‘12345’.

If you closely read the description of the for…in consctruct from W3Schools, you’ll find the reason behind this difference in behavior. It says

“The for…in statement loops through the elements of an array or through the properties of an object.”

What entices us to believe that both ‘for’ and ‘for..in’ are alike is the way these have been demonstrated. Almost all the top search result from google, give the code of iterating array elements while explaining the ‘for…in’ construct, so we never use it for accessing properties. Although, we usually do not keep properties in array objects but this behavior results when we get an array object from an external javascript library. Here is the example code for jQuery that reveals this difference:

var a = '[{"a":1},{"a":2},{"a":3}]';
var array = $.parseJSON(a);
for(var i in array)
  //process array[i]

Useful knowledge !

, , ,

8 Comments