Writing a single library for SSJS and CSJS validation – failed attempt #1

In this article I will demonstrate my first futile attempt to consolidate CSJS and SSJS libraries so that we only have to write validation once. I will also discuss JavaScripts Closures which unless you have already encountered them will make your head hurt thinking about it 🙂

Introduction

I was reminded in one of the comments on my blog last week about how it is still a pain in the butt to have to write client side JavaScript validation (to provide a good user interface) and server side JavaScript validation (to ensure data integrity and because CSJS validation is easy to break). So I set out to try and simplify this process by trying to copy a basic SSJS JavaScript validation routine in CSJS. I figured if the average XPage developer is now used to writing validation in SSJS then why confuse things. Try and mimic the basic functionality client side and away we go – simple right?

Comparing two fields in SSJS

So here is my basic example – comparing two password fields which have been submitted

<xp:validateExpression message="Passwords Must Match">
   <xp:this.expression><![CDATA[#{javascript:
        if (getComponent("Password").getSubmittedValue() != getComponent("ConfirmPassword").getSubmittedValue())
          {
            return false;
          } else {
            return true;
          }
        }]]>
   </xp:this.expression>
</xp:validateExpression>

Here’s my form in Firefox – the Password field is the one we are going to look at in the examples. I want to test if the Password and ConfirmPassword fields have the same value – in the client and on the server. The above code does it on the server. (originally posted here)

fail1

So the trick is to try and mimic getComponent(“Password”).getSubmittedValue() in client side JavaScript and then the code which is already written can serve to validate on the client side as well – well that is the plan anyway.

Not as simple as you’d have thought

So I started by learning about how to chain JavaScript functions and would you believe it is rather mind-bendingly simple and yet amazing complex to get your head around at the same time.

Reading:

http://stackoverflow.com/questions/9338439/how-to-chain-functions-without-using-prototype/9338486#9338486

http://stackoverflow.com/questions/6256016/how-can-i-call-any-function-in-a-chain-of-functions-without-the-chaining

But the basic premise it to be able to “return this” from the original function which therefore returns a function – which means you can then .doSomething to it.

First – Prototypal inheritance

A cool part of the JavaScript language is that you can create prototype (copy) of an object and it inherits all the traits of the originator – the problem I ran into with this is that you have to create a object in the first place to then chain the function to it – that did not mimic the exact syntax I was looking for – maybe another day. (example from this website)

function Pet(name, species){
  this.name = name;
  this.species = species;
}
function view(){
  return this.name + " is a " + this.species + "!";
}
Pet.prototype.view = view;
var pet1 = new Pet('Gabriella', 'Dog');
alert(pet1.view()); //Outputs "Gabriella is a Dog!"

Then closures

OK for those of you who do not understand JavaScript closures:

  1. Join the club
  2. Sit down with a good cup of tea and a blanket
  3. This is going to hurt

As far as I understand it (and it would not be the first time I was wrong) – a JavaScript closure is basically a function within a function which has access to the locally scoped variables after the function has returned.

In the spirit of Hammer Horror films – a closure is a function within a function which can live on after the original function is finished. It can then feed off the innards of the function which is now dead – nice!

Told you your head would hurt – go read this, it might help http://www.crockford.com/javascript/private.html

So I created the getComponent function like this

var getComponent
getComponent = function(key){
    var temp = dojo.query('[id$=:'+key+']')[0].value
    console.log(temp)
    return this
}

And when I run that you can see we get the value from the field logged and then “window” returned which is the namespace for the functions

fail4
Within the getComponent function I then added the getSubmittedValue()

fail5

Without the need for the console.log – we now get “Marky” returned

How does that work then? You’re right my head hurts……

Yeah me too !

  1. We saw the getComponent function on its own created the temp value and returned itself (making it chainable)
  2. The getSubmittedValue function was then called within the getSubmitted function
  3. getSubmittedValue does not have a parameter passed to it through the originating call
    getComponent(“Password”).getSubmittedValue()
  4. But because it is a closure it does have access to the temp variable which was created when the original getComponent function was called
  5. uuurgh *shakes head*
  6. So anyway it works and woooooo – I got what I wanted !!!
  7. WHY do closures work like this? I haven’t figure that out yet. I think it is cos in this case the getSubmitted function is still in memory even though it has been “completed” it still exists and can therefore still be “used” – but that is just a  guess on my part.

This then allows be to create a generic checkPasswords function which should run with the same “JavaScript” for client side or server side – man I was dancing around the room after spending the entire week trying to figure this out 🙂

var getComponent
getComponent = function(key){
    var temp = dojo.query('[id$=:'+key+']')[0].value
    getSubmittedValue = function(){
        return temp
    }
    return this
}

function checkPasswords(){
	if (getComponent("Password").getSubmittedValue() != getComponent("ConfirmPassword").getSubmittedValue()){
      return false;
    } else {
      return true;
    }
}

checkPasswords()

Implementation
Then I tried to implement it in my XPage – and got the face palm moment – ServerSide JavaScript Libraries and Client Side JavaScript libraries are discrete and nether the two shall cross…..

You cannot include an SSJS library on your “web page” and you cannot include a CSJS library in your Server Side code

SON OF A BISCUIT EASTER !

Conclusion

So there’s my fail – but even after elation and then facepalm I am not down about this at all.

I am actually very happy about how much I heave learned about JavaScript this week – I have always considered myself “ok” at JavaScript but never advanced enough to start to write it as a “JavaScript developer”. I think that path has started and I am going to be writing about it I am sure.

If anyone has any suggestions or insight on how I can possibly move this forward please let me know. I would love to be able to create a single method for doing SSJS and CSJS validation without the need for duplicative coding.

🙂

Advertisement

9 thoughts on “Writing a single library for SSJS and CSJS validation – failed attempt #1

  1. You might want to slightly alter the approach. Every validation has two faces: a) aquisition of the value(s) to be validated b) performing the validation. The aquisition of the value is very platform specific (as you figured out in the article) – one detail: if you run code in a validator, you don’t need getComponent(“..”).getSubmittedValue(), but you can use “value” directly. Another populat approach for validation is to catch all fields that have a specific class (e.g. required, numeric, pastDate, futureDate) etc. and pass them to validation functions.
    So I would try to have a set of common functions for b) and let a) happen where and how the platform allows me.

    • Thanks Stephan – is there a way via properties file or something like that which I could have the same functions added (included/looked up) in SSJS or CSJS. I am looking for a common “repository” which could be accessed by either as they are compiled.

  2. Sven – that is exactly the kind of thing I was looking for – brilliant (as ever)

    I would love to be able to get the string form within the database without having to have the backend go to the front end and get the string from a URL.

    Not knowing anything about Java myself – but it would seem that if you can import text from a URL and return it into the function then you should be able to use the same concept to get it from and bundle or properties file within the database in the same way. If we were to store the functions within a notes document could that be retrieved by both the SSJS and the CSJS – parameterized development?

    • To store the function within a document, you can use a view and open the documents as a CSJS library (but you will loose the resource aggregation benefit). I have used this often for old web applications. To load the document as a SSJS library, you have to create your own loader function. This function gets the text of the document and executes the content with “eval”. Then all functions are ready to use in SSJS.

      This can be used a “global” repository database.

      Another idea is to store your JS libs in a file resource: This allows you to access it as a CSJS and a SSJS library. On of the filenames ends with “.jss” you can use the “import” feature of SSJS.

      • Thank you Sven !

        I tried the document route yesterday and finally figured out I needed to eval the incoming string and it worked beautifully 🙂

        I can now import the same function into CSJS and SSJS and run it. I wrote a LOT more code to do it than I would have done to duplicate it in the first place – but the principle still stands 🙂 Will blog.

        So then the next question is: if the libraries within eclipse can be accessed ultimately. It is in the database – so can it be accessed as a text object and then “run” maybe? Or in a properties file which I could at least open in eclipse in a text editor maybe?

        More to play with and ultimately increasing my learning.

      • … just be a little careful if you are running an eval in ssjs on code stored in a document in the database – in the code you could escalate your privileges and get admin access to the server, so if your users can work out where that document is and write to it, its a big security hole

      • @Simon:
        If you implement a bad security concept for your infrastructure then every user will be a possible security hole. Just think twice about access rights and you won’t have any problems.

  3. […] As I have mentioned in other articles – a JavaScript function is easy to over-ride in the console. The global namespace for web browser Javascript is “window” and all functions live there by default. To over ride them we just use window.functionname in the console and create our own function. This demonstration is also applicable to Chrome Dev Tools console. […]

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s