JQuery callback to Servoy method with params

Using Servoy to administrate the content of your website? Discuss all webrelated Servoy topics on this forum!

JQuery callback to Servoy method with params

Postby GaryDotzlaw » Tue Dec 18, 2012 12:21 am

Trying to call a servoy method from .js and can't seem to get it to work.

1. I add an HTML field to a form and assign it this onShow()
Code: Select all
//   var callback = plugins.WebClientUtils.generateCallbackScript(keyPress, ['keyName']);
//   var script = 'function showInServoy(keyname){' + callback + '}';
   var script = 'function showInServoy(keyname){alert(keyName);}';
   var markup = '<script type="text/javascript">' + script + '</script></head></html>'
   var HTML = ' \
      <html><head> \
         <script src="http://localhost:8080/jquery.js" type="text/javascript" charset="utf-8"></script> \
         <script src="http://localhost:8080/servoy_keys.js" type="text/javascript" charset="utf-8"></script> '
   + markup;


You can see that originally I was trying with the WebClientUtils to generate a callback and pass keyPress() an array of params. However, I couldn't get that to work, so I'm just trying to show an alert dialog with the param for now.

2. This is my external "servoy_keys.js" file. The other .js is jQuery.
Code: Select all
$(document).ready(function(){

    //Map key codes to their corressponding buttons to click
    var triggers = {
        D: 'D key was pressed',
        N: 'N key was pressed',
        L: 'L key was pressed'
    };

    //Listen for keys
    $(document).keyup(function(event){
        var key = String.fromCharCode(event.keyCode);

        if (key in triggers){
//            alert(triggers[key]);
            showInServoy(triggers[key]);
//         javascript:showInServoy(triggers[key]);
        }
    });
})

If I remove the comments from the alert in the .js file above, I do see the alert every time I push one of the keys jQuery is monitoring for in Servoy. However, I cannot show the alert back in Servoy. You will also see that I tried it with javascript:showInServoy() as well as just showInServoy().

The point of this is not to do key listening, but rather to simply understand how to do callbacks to Servoy using a simple example.
Gary Dotzlaw
Dotzlaw Consulting
dotzlaw.com
Version: 7.3.0 - build 2018
Win 7, 64
User avatar
GaryDotzlaw
 
Posts: 38
Joined: Fri Jun 17, 2011 10:00 pm

Re: JQuery callback to Servoy method with params

Postby david » Tue Dec 18, 2012 12:27 am

Did you check out the "exampleGoogleMaps.servoy" solution in the files section of webclientutils plugin?

If that doesn't do it for you we could dig around here and post some better examples.
David Workman, Kabootit

Image
Everything you need to build great apps with Servoy
User avatar
david
 
Posts: 1727
Joined: Thu Apr 24, 2003 4:18 pm
Location: Washington, D.C.

Re: JQuery callback to Servoy method with params

Postby GaryDotzlaw » Tue Dec 18, 2012 3:14 am

The GoogleMaps example is all client-side HTML/javascript, and uses no external .js file. I need to call a Servoy method from a javascript file. As I show in my example, the javascript running the jQuery as a key listener, needs to simply call a method in Servoy and pass it the key that has been pressed as a parameter. I'm hoping someone can help me get this example working, or something similar that is stripped down to bare bones, so it is really clear how to call a Servoy method from a javascript file and pass it parameters. After searching the board I can see that this has been asked several times, but no clear answer has ever been given (that I could find), except for a hack in 2009 where jQuery is used to call a client-side div with custom id and firing its click event method (no passing of a parameter). I also don't want to use deep linking.

Thanks for the help.
Gary Dotzlaw
Dotzlaw Consulting
dotzlaw.com
Version: 7.3.0 - build 2018
Win 7, 64
User avatar
GaryDotzlaw
 
Posts: 38
Joined: Fri Jun 17, 2011 10:00 pm

Re: JQuery callback to Servoy method with params

Postby david » Tue Dec 18, 2012 4:58 am

Ah, my bad. Web client utils plugin isn't what you need. You need to set up an end point on the server. Several options:

1. http://wiki.servoy.com/display/Serv60/R ... b+Services

2. Velocity report plugin

Highly recommended. I'll let Patrick explain more but the basic idea is:

"The Velocity Report plugin uses CSS (2.1 and 3) and XHTML for building complex layout, Apache Velocity for easy templating, any native Servoy objects for data filling (globals, datasets, foundsets, you name it!) ... Report templates are simple (well-formed) HTML documents, which can be saved in a Servoy-server-accessible path ..."

3. Servoy headless client

Servoy has a little known client (but has been around forever) that is instantiated via jsp files on the server. Trigger the jsp via a url and it will call a servoy method for you and return results. Same idea as #2 except except you're in the jsp world now.

I've attached a simple jsp called "endpoint_example.jsp" which you need to drop into Servoy's .../server/webapps/ROOT directory. The code looks like this:

Code: Select all
<%@ page import = "java.util.*" %>
<%@ page import = "com.servoy.j2db.server.headlessclient.*" %>
<%@ page import = "com.servoy.j2db.util.*" %>

<%
   // grab params
   String solution = request.getParameter("s");
   String method    = request.getParameter("m");
   Object[] args    = new Object[]{session, request};

   // start servoy headless client
   ISessionBean servoy_hc = (ISessionBean)application.getAttribute("servoy");
   if (servoy_hc == null) {
      servoy_hc = HeadlessClientFactory.createSessionBean(request, solution);
      application.setAttribute("servoy",servoy_hc);
   }
   
   // call servoy method   
   String results = (String)servoy_hc.executeMethod(null, method, args);
   
   // print out results
   out.print(results);
%>


Also attached is a servoy solution file called "endpoint.servoy". It contains one global method called "get":

Code: Select all
function get(session, request) {
   
   var data    = []
   var row      = {}
   row.type   = (request.getParameter('type')) ? request.getParameter('type') : 'fruit'
   row.name   = (request.getParameter('name')) ? request.getParameter('name') : 'orange'
   row.taste   = (request.getParameter('taste')) ? request.getParameter('taste') : 'fruit'
   data.push(row)
   
   return JSON.stringify(data) // Servoy 6.1 or later only!
   
}


Try out a couple of URL's in your browser once both are installed:

method.png
method.png (62.64 KiB) Viewed 12745 times


method with params.png
method with params.png (66.39 KiB) Viewed 12745 times


Whatever you set up, you can call via ajax. Sencha example:

Code: Select all
proxy: {
                type: 'ajax',
                extraParams: {
                    s: '_ds_CODE_resources',
                    f: 'CODE_0F__sencha',
                    m: 'AJAX_staticData'
                },
                url: 'app/controller/bridge.jsp',
                reader: {
                    type: 'json'
                }
            }


JQuery example:

Code: Select all
function stageOneSubmit(event, url) {

        // block default submit
        event.preventDefault();

      // validate first
      var validator = $('#checkout_1').bValidator();
      if( !validator.validate() ){
         return;
      }

      // don't run if on account
      if ( $('.payment :checked').val() == "terms" ) {
         $('#checkout_1').submit();
         return;
      }

      // TODO: turn on busy-ness

      // validation data
      var data = {
            name      : $('#checkout_1 [name="cc_name"]').val(),
            card      : $('#checkout_1 [name="cc_number"]').val(),
            month      : $('#checkout_1 [name="cc_month"]').val(),
            year      : $('#checkout_1 [name="cc_year"]').val(),
            cvc         : $('#checkout_1 [name="cc_cvc"]').val(),
            address      : {
               line_1      : $('#checkout_1 [name="b_line1"]').val(),
               line_2      : $('#checkout_1 [name="b_line2"]').val(),
               city      : $('#checkout_1 [name="b_city"]').val(),
               state      : $('#checkout_1 [name="b_state"]').val(),
               zip         : $('#checkout_1 [name="b_zip"]').val(),
               country      : "USA"
            }
         }
      

      // verify CC info
      $.ajax( {
            type   : "post",       // the default
            url      : url,
            data   : { params      : JSON.stringify(data),
                  svs         : "lind_WEBlind_website",
                  svf         : "WEBlind_0F__checkout",
                   svm         : "AJAX_verifyCC"
               },
         dataType   : "json",
            success   : function (results) {

            // if success, submit
            if ( results._msg == 1 ) {
               $('#checkout_1').submit();
            }
            else if ( results._msg == 0 ) {               
               alert("CC not validated");
            }
            else {
               // back button trapping
               window.location=window.location;
            }
            
         }
      });      
}
Attachments
endpoint demo files.zip
(3.92 KiB) Downloaded 347 times
David Workman, Kabootit

Image
Everything you need to build great apps with Servoy
User avatar
david
 
Posts: 1727
Joined: Thu Apr 24, 2003 4:18 pm
Location: Washington, D.C.

Re: JQuery callback to Servoy method with params

Postby david » Tue Dec 18, 2012 7:00 am

Heh, again my bad. I don't read the details sometimes and run off with assumptions.

4th option with web client utils (and the answer you wanted initially):

Code: Select all
/**
* @type {String}
*
* @properties={typeid:35,uuid:"43F17E57-C318-4EE5-A6BE-22959B09D12B"}
*/
var markup = null;


/**
* @properties={typeid:24,uuid:"17ABA5AD-19CF-41EA-81CF-0B6FAA1F31F1"}
*/
function onShow() {
   // register callback method and return params
   var callback = plugins.WebClientUtils.generateCallbackScript(forms.blank.callback, ['key'], false);
   // set up js function
   var script = "function keyInit() {\
               $(document).keyup(function(event){\
               var key = String.fromCharCode(event.keyCode);\
               var triggers = {\
                    D: 'D key was pressed',\
                    N: 'N key was pressed',\
                    L: 'L key was pressed'\
                };\
                if (key in triggers){\
                 alert(triggers[key]);" +
                callback +
                "}\
            });\
            }"
   // insert js function ("markup" is a form variable on the form as field type HTML_AREA,non-editable)
   markup = '<html><head><script type="text/javascript">' + script + '</script></head></html>'
   // run the function
   plugins.WebClientUtils.executeClientSideJS('keyInit();')

}

/**
* @properties={typeid:24,uuid:"C64FEB2C-996E-466D-AC55-936F30C6D9FD"}
*/
function callback(param) {
   application.output(param) // outputs D,N and L if they are pressed on the client
}


Setting up callbacks this way can get a bit trippy and hard to debug. Looks like you almost had it.

Attached servoy solution.
Attachments
callback solution.zip
(3.68 KiB) Downloaded 342 times
David Workman, Kabootit

Image
Everything you need to build great apps with Servoy
User avatar
david
 
Posts: 1727
Joined: Thu Apr 24, 2003 4:18 pm
Location: Washington, D.C.

Re: JQuery callback to Servoy method with params

Postby GaryDotzlaw » Tue Dec 18, 2012 3:57 pm

Thanks David, but its still not what I am looking for; the javascript with "keyInit" needs to be in a separate .js file that calls back into Servoy to run the method. What you are showing is the same as the GoogleMaps example, where all code is inline and client-side in Servoy. You need to move the "keyInit" function to a separate .js and include it with something like this:
Code: Select all
<script src="http://localhost:8080/servoy_keys.js" type="text/javascript" charset="utf-8"></script> '

However, I did notice that the syntax that you used with the webclient utils is slightly different from what I tried, so maybe that is what I am doing wrong. Maybe I should try something like this (I did not use a form name or Boolean in the callback I attempted):
Code: Select all
   var callback = plugins.WebClientUtils.generateCallbackScript(form.[myformname].keyPress, ['keyName'], false);
   var script = 'function showInServoy(keyname){' + callback + '}';
//   var script = 'function showInServoy(keyname){alert(keyName);}';
   var markup = '<script type="text/javascript">' + script + '</script></head></html>'
   var HTML = ' \
      <html><head> \
         <script src="http://localhost:8080/jquery.js" type="text/javascript" charset="utf-8"></script> \
         <script src="http://localhost:8080/servoy_keys.js" type="text/javascript" charset="utf-8"></script> '
   + markup;

In this simple example, the simple "keyInit" javascript we are talking about does not need to be in a separate .js file, however, it is just a test case to get this working without complexity. I have complex javascript that I am using, and I do not intend to put that inline into Servoy, it needs to be a separate .js file.
Gary Dotzlaw
Dotzlaw Consulting
dotzlaw.com
Version: 7.3.0 - build 2018
Win 7, 64
User avatar
GaryDotzlaw
 
Posts: 38
Joined: Fri Jun 17, 2011 10:00 pm

Re: JQuery callback to Servoy method with params

Postby GaryDotzlaw » Tue Dec 18, 2012 4:41 pm

Well, this doen't work either:
Code: Select all
        var callback = plugins.WebClientUtils.generateCallbackScript(forms._dev.keyPress, ['keyName'], false);
   var script = 'function getInServoy(keyname){' + callback + '}';
   var markup = '<script type="text/javascript">' + script + '</script></head></html>'
   var HTML = ' \
      <html><head> \
         <script src="http://localhost:8080/jquery.js" type="text/javascript" charset="utf-8"></script> \
         <script src="http://localhost:8080/servoy_keys.js" type="text/javascript" charset="utf-8"></script> \
         '
   + markup;

I'm not sure what else to try. Anyone else have any ideas?
Gary Dotzlaw
Dotzlaw Consulting
dotzlaw.com
Version: 7.3.0 - build 2018
Win 7, 64
User avatar
GaryDotzlaw
 
Posts: 38
Joined: Fri Jun 17, 2011 10:00 pm

Re: JQuery callback to Servoy method with params

Postby david » Tue Dec 18, 2012 6:19 pm

GaryDotzlaw wrote:Thanks David, but its still not what I am looking for; the javascript with "keyInit" needs to be in a separate .js file that calls back into Servoy to run the method.


This is possible as well. Extra step is that you do have to bind them to the callback you generate from Servoy at runtime with web client utils -- no way to just write a client-side function that calls a servoy method. Well, there is: see my previous post about creating your own Servoy endpoints (and why I got off track there).

Here is some simpler code from one of our solutions doing this technique:

Code: Select all
//set up callback on form for navigating when in router wrapper -- see globals.DS_router
if (globals.DATASUTRA_router_enable) {
   var callback = plugins.WebClientUtils.generateCallbackScript(globals.DS_router_callback,null,false)
   var jsCallback = 'function navigate(){' + callback + '}';
   plugins.WebClientUtils.executeClientSideJS('navigateConfig(' + jsCallback + ');')
}


Client side method it calls:

Code: Select all
//   Callback to setup navigation
function navigateConfig(source) {
   var script = document.createElement('script');
   script.type = 'text/javascript';
   script.text = source;
   $("#servoy_page").append(script);
   
   //method is called navigate()
}


Get creative with "script.text = source" part in your test case to combine the callback with your external js.

If you're going with heavy clientside javascript, I recommend running web client in an iframe:

http://wiki.servoy.com/display/public/DOCS/Web+Client
http://wiki.servoy.com/display/public/t ... +an+IFrame

Side trick: instead of including jquery by hand, use this code to force inclusion at solution startup (Servoy uses jquery for certain things when needed, this is to make sure it is loaded all the time):

Code: Select all
plugins.WebClientUtils.addJsReference(SERVOY_WEB_RESOURCES.JQUERY)


This way you don't get jquery included twice.

Hope this gives you some ideas.
David Workman, Kabootit

Image
Everything you need to build great apps with Servoy
User avatar
david
 
Posts: 1727
Joined: Thu Apr 24, 2003 4:18 pm
Location: Washington, D.C.

Re: JQuery callback to Servoy method with params

Postby GaryDotzlaw » Tue Dec 18, 2012 7:04 pm

I was aware aware that I should use an iFrame with heavy js and the servoy jquery reference, but I wanted to minimize all the variables in this example. Thanks David, I'll see if I can get it working with this extra binding step.
Gary Dotzlaw
Dotzlaw Consulting
dotzlaw.com
Version: 7.3.0 - build 2018
Win 7, 64
User avatar
GaryDotzlaw
 
Posts: 38
Joined: Fri Jun 17, 2011 10:00 pm

Re: JQuery callback to Servoy method with params

Postby GaryDotzlaw » Tue Dec 18, 2012 10:52 pm

Okay, I figured this out and am posting the solution for others attempting the same thing in the future.

I did not need to bind with webclient utils a second time. I think the problem all along was with the way I was continuing my HTML lines as I was building them. Somehow the use of "\" as a line continuation messes up the HTML so the callback does not work. :roll:

The following solution works perfectly, calling method "keyPress" in servoy from a .js file, and passing it parameters from the .js file.

Code to build the _html form variable used as a dataprovider an HTML field on the form (notice I am not using "\" to continue my HTML lines, but rather concatenating with "+"):
Code: Select all
_html =
   '<html>'
   +'<head>'
   +'<script type="text/javascript" src="http://localhost:8080/jquery.js"></script>'
   +'<script type="text/javascript" src="http://localhost:8080/servoy_keys.js"></script>'
   +'<script type="text/javascript">'
   +'function getInServoy(keyName){'
   +      plugins.WebClientUtils.generateCallbackScript(keyPress,['keyName'])
   +'}'
   +'</script>'
   +'</head>'
   +'<body>'
   +'</body>'
   +'</html>';


Code in the "servoy_keys.js" file used in this example(the other .js called jquery.js contains latest build of jQuery which can be eliminated if you make reference to Servoy's jQuery as David pointed out):
Code: Select all
$(document).ready(function(){

    //Map key codes to their corressponding buttons to click
    var triggers = {
        D: 'D key was pressed',
        N: 'N key was pressed',
        L: 'L key was pressed'
    };

    //Listen for keys
    $(document).keyup(function(event){
        var key = String.fromCharCode(event.keyCode);

        if (key in triggers){
            getInServoy(triggers[key]);
        }
    });
})


Code for the callback method keyPress (method is in same form as the HTML field):
Code: Select all
function keyPress(sKeyName)
{
   application.output(sKeyName);
}

Pressing the keys "D", "N" or "L" are captured by jQuery in the .js file and output to the console.

This can now be extended to include complex .js files in an iFrame on the page, enabling the use of commercial components like Gantt controls, Scheduler controls, Accordian controls, etc.
Gary Dotzlaw
Dotzlaw Consulting
dotzlaw.com
Version: 7.3.0 - build 2018
Win 7, 64
User avatar
GaryDotzlaw
 
Posts: 38
Joined: Fri Jun 17, 2011 10:00 pm

Re: JQuery callback to Servoy method with params

Postby david » Wed Dec 19, 2012 9:04 pm

Code: Select all
_html =
   '<html>'
   +'<head>'
   +'<script type="text/javascript" src="http://localhost:8080/jquery.js"></script>'
   +'<script type="text/javascript" src="http://localhost:8080/servoy_keys.js"></script>'
   +'<script type="text/javascript">'
   +'function getInServoy(keyName){'
   +      plugins.WebClientUtils.generateCallbackScript(keyPress,['keyName'])
   +'}'
   +'</script>' ...


This is quite a clever find! Who knew a Servoy method call would evaluate in an html area this way. We wouldn't have guessed this would work in a million years.

I wonder if it is just this method that works this way, and if it's a bug or just an undocumented feature.

In any case, it simplifies things a lot. We'll be changing things around to this approach. Good stuff.
David Workman, Kabootit

Image
Everything you need to build great apps with Servoy
User avatar
david
 
Posts: 1727
Joined: Thu Apr 24, 2003 4:18 pm
Location: Washington, D.C.

Re: JQuery callback to Servoy method with params

Postby Harjo » Mon Jan 07, 2013 2:18 pm

David,

this has always worked before,

but you have to look closely, this:

Code: Select all
plugins.WebClientUtils.generateCallbackScript(keyPress,['keyName'])


is not between quotes!, so _html is already evaluated in the method, not by placing it in the html-area...
Harjo Kompagnie
ServoyCamp
Servoy Certified Developer
Servoy Valued Professional
SAN Developer
Harjo
 
Posts: 4321
Joined: Fri Apr 25, 2003 11:42 pm
Location: DEN HAM OV, The Netherlands


Return to Web Development

Who is online

Users browsing this forum: No registered users and 4 guests