cancel
Showing results for 
Search instead for 
Did you mean: 

Adding YUI Widgets Using Webscripts

stevericker
Champ in-the-making
Champ in-the-making
Hello All,

We're adding a YUI widget (a treeview) as a dashlet.  But we have some questions as to how to do this correctly using webscripts.  There seem to be several examples of similar things built into Share, but we get lost as we try to plow through all the technologies that are involved (e.g., YUI, Freemarker, webscripts, Share).

Here's what we've tried:

- Built a webscript called "treenav" (treenav.get.desc.xml, *.get.html.ftl, *.get.head.ftl, *.get.js)
- Made the <family> a dashlet in the descriptor
- Added all the YUI treeview javascript code to the response template, treenav.get.html.ftl (see below)

<html>
<head>
</head>
<body>

Test dashlet
<div id="treeDiv1">gee</div>

<script type="text/javascript">//<![CDATA[

var tempobject = [ { type: "text", label: "node1" } ];

//instantiate the TreeView control:
var tree = new YAHOO.widget.TreeView("treeDiv1", tempobject);

//render it
tree.draw();

//]]></script>

</body>
</html>
- Registered it
- Added the dashlet to a dashboard
- It works (the YUI treeview shows up)

Here's one question:

- It doesn't seem like adding the javascript to the response template (*.get.html.ftl) is all that elegant (and kind of messes up the MVC pattern)
- But the YUI treeview seems to need its target (the <DIV> tag where the treeview will go) before being instantiated
- So putting the javascript in the controller (treenav.get.js) or in a client side file (treenav.js) doesn't seem to work
- Is there a more correct way to do this?

Here's another question:

- We want to try to get some user site information while we're building the treeview in the response template (treenav.get.html.ftl)
- When we try to use "remote.call" in our javascript, we get the error "remote is not defined" (in Firebug)
- But the remote object seems accessible per http://wiki.alfresco.com/wiki/Surf_Platform_-_Freemarker_Template_and_JavaScript_API#remote?
- Is it not possible to use the root object "remote" within javascript embedded in the response template?

And a final, more general, question:

- Let's say, from our controller script, we put data in our model root object
- How can we access that model root object data from our response template w.o. using a Freemarker interpolation (${somedata})?
- In particular, if we have javascript in our response template, can we get access to the model root object?

Hopefully this is not too longwinded.  But any help on the above would be really appreciated and would really help us as we try to continue to figure out how best to use the platform (by the way, we're using Alfresco Share 3.2r community w. Tomcat).  It seems like our troubles and questions are probably due to some misunderstandings we have about webscripts.

Thank you!
19 REPLIES 19

zladuric
Champ on-the-rise
Champ on-the-rise
The docprops.get.json.ftl (in /alfresco) looks like:

{
"dokumenti" : [
<#list companyhome.childByNamePath["Sites/"+args.company+"/documentLibrary"].children as child>
        {
            "name" : "${jsonUtils.encodeJSONString(child.properties.name)}" ,
            "nodeRef" : <#if child.isContainer>"FOLDER"<#else>"${jsonUtils.encodeJSONString(child.nodeRef)}"</#if>,
             "clientUser" : "${child.properties["custom:prop1]}",
             "clientPay" : ${child.properties["custom:prop2"]}"
        }<#if child_has_next>, </#if>
</#list>
        ]
}

I just changed the names of custom model namespace and prop from the original script.
When I call it directly ( http://serverSmiley Tongueort/alfresco/service/sample/docprops.json?company=testtvrtka ) I get a valid JSON in response.
When I call it via remote call ( var data = connector.get("/sample/docprop.json?tvrtka=testtvrtka"); var result = eval ('('+data+')');  ) catalina.out shows the error. So, I guess I'm not sending the argument properly, but I don't know how else to form the call.

mikeh
Star Contributor
Star Contributor
Could you post the docprops.get.desc.xml please?

Thanks,
Mike

zladuric
Champ on-the-rise
Champ on-the-rise
Yes, here:
<webscript>
<shortname>Document Property</shortname>
<description>Get doc properties for Share Upload dashlet</description>
<default>json</default>
<url>/sample/docprop.json</url>
<authentication>user</authentication>
<transaction>required</transaction>
</webscript>

It is not the auth thing, I tried actually manually writting a json in the response, then I can get the result. It is just the argument passing that bugs me.

mikeh
Star Contributor
Star Contributor
This: var data = connector.get("/sample/docprop.json?tvrtka=testtvrtka");
Should be this: var data = connector.get("/sample/docprop.json?company=testtvrtka");

Thanks,
Mike

zladuric
Champ on-the-rise
Champ on-the-rise
Hi Mike,

Thanks again. Anyway, I changed the argument name in the /alfresco script, but it's still not processing the argument:
Caused by: freemarker.core.InvalidReferenceException: Expression companyhome.childByNamePath["Sites/"+args.tvrtka+"/documentLibrary"] is undefined on line 3, column 8 in org/alfresco/sample/docprop.get.json.ftl.
Can you please point me to an example of how to past GET or POST argument from /share server-side .js or client .js to /alfresco webscript? I tried this in various ways, didn't work.

mikeh
Star Contributor
Star Contributor
There are loads of examples throughout the Share source code, e.g.
      var connector = remote.connect("alfresco");
      result = connector.get("/slingshot/doclib/container/" + siteId + "/" + containerId + "?type=" + toRepoType(appType));
      if (result.status == 200)
      {
         var data = eval('(' + result + ')');
         containerType = data.container.type;
      }

From config/alfresco/templates/org/alfresco/documentlibrary.js

Thanks,
Mike

zladuric
Champ on-the-rise
Champ on-the-rise
Hi mike,

Well, this still doesn't work:

var connector = remote.connect("alfresco");
      result = connector.get("/sample/docprop.json?tvrtka=" + model.site );
      if (result.status == 200)
      {
         var data = eval('(' + result + ')');
         model.docprop = data["dokumenti"];
}
  

I stripped the webscript to just return the name and nodeRef, and it still doesn't work.
When I call it like this:
http://localhost:8080/alfresco/service/sample/docprop.json?tvrtka=testtvrtka
I get a valid json, when I call it through the remote.connect, it triggers the error:
Caused by: freemarker.core.InvalidReferenceException: Expression companyhome.childByNamePath["Sites/"+args.tvrtka+"/documentLibrary"] is undefined on line 3, column 8 in org/alfresco/sample/docprop.get.json.ftl.
It's like a wall, can't get through it.

stevegreenbaum
Champ in-the-making
Champ in-the-making
I just found this post and had already started working on a different approach.  Is there a third method to make the data available to the YUI widget?  I am trying to use Stringify in the controller and then JSON.parse in the HTML .FTL response template.  Does this seem feasible?  I tried it, but the JSON.parse doesn't complete successfully.  Wasn't sure if I didn't implement the stringify correctly or if this just doesn't make sense. 

var tempobject = [ { type: "text", label: "node1" } ];
x = json.stringify (tempobject);
model.x = x;

In the template:
jsonObject= JSON.parse(${x});

stevericker
Champ in-the-making
Champ in-the-making
Hi Steve,

I'm not sure you have access to the model (model.x) in the script portion of your template–the model really is for the Freemarker engine I think.  So you can try some of the tricks Mike and Zaizi mentioned (like using a ${x.property} Freemarker construct but within your HTML code).  It doesn't feel super elegant but that's what a templating engine does I guess (purely just substitutes).  Otherwise you can turn your server-side code maybe into a webscript (like Zaizi said) and then call your webscript right from the javascript portion of your template (which would be client-side).

Hope that helps a bit.

Steve

mikeh
Star Contributor
Star Contributor
var tempobject = [ { type: "text", label: "node1" } ];
x = json.stringify (tempobject);
model.x = x;

In the template:
jsonObject= JSON.parse(${x});
Sorry, hadn't spotted this post until steve r replied… I use that pattern in the DocLib webscripts
model.x = jsonUtils.toJSONString(tempobject);
YUI is effectively doing the JSON.parse() part in the DataSource code, so that should work ok as you've got it.

Thanks,
Mike