3

In an ideal world I would like to separate out Javascript to a completely different file and include it in the JSP page. But there are cases were I struggle to follow this rule simply because dynamically generated Javascript is so much easier to write !!

Couple of examples :

1) Locale specific error messages in alert boxes.

<%
Locale locale = ..//get current locale
%>

<script language="JavaScript">
function checkMessage() {
  if(document.form.msg.value=='') {
    alert(<%= *LocaleHelper.getMessage(locale,"please_provide_message")* %>); //get the locale specific message . mixing Javascript and JSP !!!
  }
}

2) Initializing values .Sometimes you need to get values using JSP which will be used inside a javascript method

function computeExpiry () {
 var creationDate= <%= creationDate =%>
 var currentDate = document.form.date.value;
 var jsCreationDate= converToDate(creationDate);
 return currentDate>creationDate ;
}

3) Initializing config objects dynamically

var myConfig = {
     modal:true,
     resize:true,
   <% if (lastPage) { %>
     showPreviousButton  :true,  
     showNextButton : false ,
     showSubmitButton : true,
   <%}  else  {%>
   showPreviousButton  :true,  
     showNextButton : true ,
     showSubmitButton : false,
   <%} %>  

As you can imagine, without any kind of conventions , all our JSPs will be a unsightly mix of Javascript and JSP, hard to understand and maintain, with lots of non-reusable javascript code

I am not looking for a perfect solution. I know its easier to do this than try to maintain a pure Javascript and JSP separation. I am looking for suggestions to ease this process and hope lots of people have experience worth sharing.

Zenil
  • 1,491
  • 3
  • 12
  • 21

3 Answers3

7

Mixing JavaScript and JSP makes code harder to read, reuse, maintain and also degrades performance(such JS code cannot be externalized and compressed). Avoid that when possible.

One way is collecting all JSP related variables in one place and factoring out non-JSP codes into another pure/static JavaScript files. For example:

<script type='text/javascript' > 
    var app = { // global app "namespace" holds app-level variables
     msg: "<%= *LocaleHelper.getMessage(locale,"please_provide_message")* %>";
     creationDate: <%= creationDate =%>;
     btnConfig: {
       <% if (lastPage) { %>
           showNextButton : false ,
           showSubmitButton : true,
       <%} else  {%>
           showNextButton : true ,
           showSubmitButton : false,
       <%} %>
      }
    };
</script>

// following JS has no JSP, you can externalize them into a separate JS file
// s.t. they can be compressed and cached.
function checkMessage() {
  if(document.form.msg.value=='') {
    alert(app.msg);
  }
}

function computeExpiry () {
    var creationDate= app.creationDate;
    var currentDate = document.form.date.value;
    var jsCreationDate= converToDate(creationDate);
    return currentDate > creationDate;
 }

 var myConfig = _.extend({   // underscore library's extend
     modal: true,
     resize: true,
     showPreviousButton: true,  
 }, app.btnConfig);

BTW, in practical application, I recommend module loader library like RequireJS instead of defining global variables primitively.

Hui Zheng
  • 10,084
  • 2
  • 35
  • 40
  • You mentioned that checkMessage() can be externalized to a JS file. But that becomes an invalid Javascript as it refers to variable "app" which is not defined in that file. Are you okey with that ? If yes, is there some kind of variable naming convention that you follow to tdocument that "app" has to be defined somewghere else for this function to work correctly ? – Zenil Feb 04 '13 at 17:47
  • If you define `app` before including other file, it will be ok(http://stackoverflow.com/questions/2932782/global-variables-in-javascript-across-multiple-files) . Actually, in real app, I recommend module loader library like RequireJS. – Hui Zheng Feb 05 '13 at 02:44
5

I try to avoid this but when I have to pass data from back-end to front-end I use a flat JavaScript Object which is created by a Hash in the backend. You can convert Hashes in any language to JSON strings. Place a <script> tag in your HTML page and dump that JSON string in it and assign it to a JavaScript variable.

For example:

<script>
  var dataFromBackEnd = JSON.parse(<%= Hash.toJSON(); %>); // I'm just assuming JSP part
</script>

From this point JavaScript should take care about logic. If there is a condition that JS need to take action about it pass the boolean value of it to JS. Don't mix logic.

Mohsen
  • 64,437
  • 34
  • 159
  • 186
  • It looks like a nice and clean approach..What you are really saying is initialize all the javascript variables first. Because "Hash" may not be the only variable that JSP has ..There will be static variables, there will be different variables in the request object etc.So for each such "back-end" variable, initialize a javascript variable and then move forward ? – Zenil Feb 04 '13 at 17:51
  • If you dump all those variables in one JS object it's even cleaner. Be careful about security here. You can not pass everything to front-end of course – Mohsen Feb 04 '13 at 18:06
  • Can you clarify with code how to dump different JSP variables in one JS object ? – Zenil Feb 04 '13 at 23:55
0

First you can do is avoing using scriptlets. Instead using it use JSP tags, as JSTL. It will allow you to format your code better.

jddsantaella
  • 3,657
  • 1
  • 23
  • 39