Author Archives: zlatko

Reference Error: “json” is not defined – how to fix it in Alfresco webscripts

Since I’m writing a webscript and bumping into this wall for the n-th time, I need to write myself a reminder of what to do in case I repeat it.

I am making a Share client-side POST Ajax call to Alfresco backend, and I get an “Reference Error: “json” is not defined.

Next time, this post and Google will likely save me some three cumulative hours of investigation.

The thing is, Alfresco will only use its automatic json parser if it receives a header with “application/json” encoding.

Anyway a POST webscript call to Alfresco webscript sending “application/json” data,  and having the “json” is not defined probably means that your form is not sent as “application/json”. I’ve just lost several hours again trying to find the problem cause.

Finally I took a look at Chromes’ network console to see that the request was sent as “application/x-www-form-urlencoded“.

So I solved it by calling the webscript with Alfresco.util.Ajax.jsonRequest();. That made it all the difference. Or I could have used Ajax.request, but specify the requestContentType.

So, future Zlatko (or any of you rare visitors), make sure you call jsonRequest directly next time.

Don’t put minus sign in component names for Alfresco dashlets and other page components

I’m writing a dashlet which won’t fire its’ onReady method. It just sits there, never getting called.

Googling it I ran into my own blog post which essentially says: call your dashlet with new Alfresco.Dashlet(“html_element_id”);. If your html_element_id is undefined or anything, dashlet will never get this element ready so it won’t fire.

But my new dashlet is on Alfresco 4.2 – which means it’s instantiated automatically. Then I found out what the problem was: a minus sign in the element id. I had an id like this: template_x002e_functions_x002e_custom-dashboard_x0023_default. See the minus sign in there? That made YUI not aware of the element id and your dashlet would not fire.

How to create Alfresco Share dashlet that does not use authentication

Back to Part I: How to create an Alfresco page that uses no authentication

This post is trying to explain in few short steps how to create an Alfresco dashlet. It was inspired by this question on StackOverflow.

Basically, a dashlet is consisting of a few files (usually 3-4 + internalization files), most of them placed in tomcat shared loader (the usual way I deploy Alfresco extensions). Here are  the typical files we would create:

<TOMCAT>/shared/classes/alfresco/web-extension/site-webscripts/my-dashlet/my-dashlet.get.desc.xml
<TOMCAT>/shared/classes/alfresco/web-extension/site-webscripts/my-dashlet/my-dashlet.get.html
<TOMCAT>/shared/classes/alfresco/web-extension/site-webscripts/my-dashlet/my-dashlet.get.js
<TOMCAT>/shared/classes/alfresco/web-extension/site-webscripts/my-dashlet/my-dashlet.get.properties
<TOMCAT>/shared/classes/alfresco/web-extension/site-webscripts/my-dashlet/my-dashlet.get_de.properties
<TOMCAT>/share/components/dashlets/my-dashlets.css
<TOMCAT>/share/components/dashlets/my-dashlet.js
<TOMCAT>/share/components/dashlets/my-dashlet-min.js

We could do with just the first two, so let’s try. (Alfresco used one more file in versions prior to 4, but the differences are minor. If you run into that, ask me or at the Alfresco forums.)

The first file is my-dashlet.get.desc.xml. When starting, Alfresco will pick up the *desc.xml files from site-webscripts folder and get its configuration. The GET part of the name says that this component will answer to a GET HTTP call. If you named it my-dashlet.post.desc.xml, you would not be able to access the component via GET method.

Anyway, the file:

<webscript>
  <shortname>My Dashlet</shortname>
  <description>Example dashlet</description>
  <family>user-dashlet</family>
  <url>/components/dashlets/my-dashlet</url>
</webscript>

The URL part is the most important thing here – if you remember, in our page template, we reserved a region for such a dashlet.

Now, the second file, my-dashlet.get.html.ftl is the actual HTML that we will use. We can simply say something like this:

<@markup id="html">
  <@uniqueIdDiv>
    <div class="dashlet my-class">
      <div class="title">My Dashlet</div>
        <div class="body">Hello world!</div>
      </div>
    </@>
 </@>

If you now copy the two files in their folders and refresh Share webscripts (http://localhost:8080/share/service/index, click on Refresh webscripts), you would see this dashlet when trying to customize user dashboard.

You can even access the component directly, by going to http://localhost:8080/share/components/dashlets/my-dashlet – you would only get the component (dashlet), not the whole page.

We could make things a bit more fun, you could replace the html content with this:

<@markup id="html">
  <@uniqueIdDiv>
    <div class="dashlet my-class">
      <div class="title">${msg("header.title")}</div>
        <div class="body">${msg("text.hello")}</div>
      </div>
    </@>
 </@>

And then add another file or two, my-dashlet.get.properties (with the default messages) and my-dashlet.get_de.properties (with German language messages).
The default, my-dashlet.get.properties, contains this:

header.title=My dashlet
text.hello=Hello world

The other file could look like this:

header.title=Meine dashlet

If you deploy the two files to their places and refresh the webscripts, you’d get the same result. However, if you change your language setting in the browser and place German above English, you’d get slightly different dashlet title. (That’s how you internationalize dashlets.)

To make things pretty, you would add a CSS call in the html.ftl file, and to make things useful, you could also include some client-side Javascript. Just add the links to them in the my-dashlet.html.ftl file:

<@markup id="css" >
 <#-- Link to your CSS file -->
 <@link rel="stylesheet" type="text/css" href="${url.context}/res/components/dashlets/my-dashlet.css" group="dashlets"/>
</@>
<@markup id="js">
 <#-- Your JavaScript file. You actually only need the my-dashlet-min.js file (unless in development mode), but we usually keep the original source in my-dashlet.js there so we can change it later.
-->
 <@script type="text/javascript" src="${url.context}/res/components/dashlets/my-dashlet.js" group="dashlets"/>
</@>

<@markup id="widgets">
<!-- Now let's initialize those two thingies - put them in the <head> of the page --> 
 <@createWidgets group="dashlets"/>
</@>
<@markup id="html">
 <@uniqueIdDiv>
   <div class="dashlet my-class">
     <div class="title">${msg("header.title")}</div>
       <div class="body">${msg("text.hello")}</div>
     </div>
  </@>
</@>

What you put in the CSS in JS files is…well, out of scope :) .

Now, to make things more dynamic, we could also use something dynamic: we can make a servers-side javascript file my-dashlet.get.js which will be able to show us something dynamic.

Let’s say we want to know what’s the time on the server. We can put this in the JS file:

model.currentTime = new Date();

You see, we placed a currentTime variable into the page modelNow we can use that variable in our HTML template. Put this under our Hello world line:

<p>Current time on the server is ${currentTime?string.medium}.</p>

That’s basically it. You can also call the repository backend unauthenticated, you just need to define the backend webscripts with <authentication>none</authentication> – and you could access some of the public data this way. But that’s another matter for another post and another poster.

Hopefully this made creating some dashlets easier to someone.

How to create an Alfresco Share page that doesn’t use authentication

Here are a few steps and explanations on how to create an Alfresco Share page that do not require authentication.  I’ve read this question on StackOverflow, and I decided I could spare some 15 minutes to write an answer.

So, I’ll write on how to create a basic page, and also how to put one simple component – or a dashlet, on it. The page could even be supported with Alfresco repository (backend) guest webscripts, but that’s out of the scope of this article.. I’m basing this post on Tomcat installation of Alfresco 4.0+, and placing scripts in the extensions folder.

Part I. Page

In Surf (framework Alfresco Share was built on), you can extend a page is done in three files. First, just create the empty files, and later on, we can add some content to it. The files:

<TOMCAT>/shared/classes/alfresco/web-extension/site-data/pages/my-page.xml
<TOMCAT>/shared/classes/alfresco/web-extension/site-data/template-instances/my-page.xml
<TOMCAT>/shared/classes/alfresco/web-extension/templates/org/alfresco/my-page.ftl

The first xml file is a simple declaration of a new page, Alfresco will pick this up on start and add this page to the Share context (share webapp). It should hold something like this:

<?xml version='1.0' encoding='UTF-8'?>
 <page>
 <title>Sample No-auth Page</title>
 <title-id>page.my-page.title</title-id>
 <description>Sample page for guests</description>
 <description-id>page.my-page.description</description-id>
 <template-instance>my-page</template-instance>
 <authentication>none</authentication>
 </page>

The most important part here is the authentication: none part – now anybody can access that page. Also, you say that the template-instance to use is my-page.xml file in template-instances folder. You can internationalize this, notice the page.my-page.title).
The second file is a template-instance file my-page.xml, it defines what components we will put on this page.

<?xml version='1.0' encoding='UTF-8'?>
  <template-instance>
    <template-type>org/alfresco/my-page</template-type>
    <components>
      <component>
         <region-id>my-dashlet</region-id>
         <url>/components/dashlets/my-dashlet</url>
      </component>
    </components>
  </template-instance>

This file defines two important things. The first is the Freemarker template for the page. The second is the url and region our component will use. So, to add more dashlets, add more components like this, but each has it’s own region-id, even if the url-s are the same.

Basically, with templateHeader, templateBody and templateFooter macros, we got some usual HTML we don’t have to write ourselves, and with the regions, we can place our page components (dashlets) to this page.

Now for the last file: Freemarker template for the page. This is the closest thing to an actual page we will be using:

<#include "include/alfresco-template.ftl" />
<@templateHeader>
</@>
<@templateBody>
 <@markup id="alf-hd">
   <div id="alf-hd">
     <h2>My page header</h2>
     <p>This is some lame page header. Normally, we would have put another component here, like Alfresco's header or something.</p>
   </div>
 </@>
 <@markup id="bd">
   <div id="bd">
     <div class="yui-t1" id="my-page">
       <div id="yui-main">
         <div class="yui-b" id="alf-content">
           <@region id="my-dashlet" scope="template" />
         </div>
         <div class="yui-b">
           <p>This is some (not-really)static HTML we'll include in our page. Usually, we'd put more components here (more dashlets or page elements like that).</p>
         </div>
       </div>
     </div>
   </div>
 </@>
</@>
<@templateFooter>
</@>

The important thing is to set the Freemarker macro @region here, and set it to our custom dashlet. We should also make sure that the dashlet with the corresponding URL.

If we restart Alfresco now, we would be able to access this page, although possibly with an error about missing component (our dashlet).

http://localhost:8080/share/page/my-page – try it and see some of this text and !

On to Part II. Simple dashlet without authentication.

How to add a dashlet tooltip in Alfresco Share 4.2

One of the neat features in Alfresco 4.0+ is that you can easily produce a tooltip on any dashlet. It does not show until you’re mouse-overing a dashlet, when it does, you get a styled question-mark on the dashlet title bar, and clicking it shows a tooltip balloon. It looks excellent and here’s the way to do it on a simple GET dashlet:

1. Edit dashlet.get.js to add the dashlet init code:

var dashletTitleBarActions = {
  id : "DashletTitleBarActions", 
  name : "Alfresco.widget.DashletTitleBarActions",
  useMessages : false,
  options : {
    actions: [
    {
      cssClass: "help",
      bubbleOnClick:
      {
        message: msg.get("dashlet.help")
      },
      tooltip: msg.get("dashlet.help.tooltip")
    }
  ]}
};

2. Put the tooltip in the init group:

model.widgets = [myDashlet, dashletResizer, dashletTitleBarActions];

Now you have a working neat little tooltip.

How to add a new action to the Rails 3.2 controller

If you want to add a new controller action to Ruby on Rails controller, you can do by adding the following bit of code.

1st: to the controller file, you add a new action, like:

def myaction
 // hackhackhack
end

Then in your routes.rb file, you add the route (in the section where you define this resource):

resource :myresource do
  collection do
    get 'myaction'
  end
end

More details here.

How did I come to do this?

I am coding together a nice little proof-of-concept app in rails. In this, I have a simple model with standard RESTful controller actions, GET/PUT/POST/DELETE matching new/edit/update/destroy actions in addition to collection type index action.

I needed another action, one that would just list selected properties of those objects (kind of like index but not quite so).

 

A short note on learning TDD

Here is a short advice on how one could learn some test-driven development, and maybe pickup some Ruby and Rails along the way:

follow the free online edition of Rails tutorial!

I’m trying to do something with it for a while now, maybe an hour or two a week, and it’s really fun! I’m learning something about rspec tests, rails development and TDD in general. Some of the points I learned:

- figure out what you want to do

- (almost) always write your tests first

- those tests will probably fail (obviously)

- code your way into passing the tests for your specs.

 

Now a few lines on rspec itself:

You start with a:

describe KEYWORD do

This line will start the test on your keyword. It may be a page, a model file, whatever.

Now you can add a before section:

before {@user = User.new(name: “Example user”, email: “mail@example.com”)}

The before section will setup your requirements. The subject line will tell what you’re testing:

subject {@user}

It could be a @model, @page, whatever. Now, you write your tests:

it{should something}

it {should_not something}

You are saying that your subject should or should not pass something.

You can add more then one describe sections. You can change the before section. You can add more then one it tests in a describe section. Now, back to studying, read you later!

 

About Javascript Constructor pattern

I’m going to try to explain (to myself and some stumbling web surfer) the constructor pattern in Javascript.

Javascript objects inherit properties directly from other objects, and all the way back to the builtin Objects’ prototype. If we create an object by invoking functions, their this keyword is bound to the object whose method created it. Also, all inner properties, and the closure scope will be shared.
Tipically it’s done this way:

var myObject = {
prop: 0, // defaults to 0
add: function (x) {
this.prop += x;
}
};

var otherObj = myObject;
myObject.add(2);
console.log(myObject.prop); // 2
otherObj.add(3);
console.log(otherObj.prop); // 5

So, all objects’ this keyword is bound to that one object.

If we want separate multiple objects, we use the constructor pattern. By convention, we name the constructor functions with a capitalized names.
Here is an example:

// “class” definition
var MyClass = function () {
this.prop = 0;
};

// lets add a getter method
MyClass.prototype.add = function (param) {
this.prop += param;
};

var myInstance = new MyClass();
var otherInstance = new MyClass();

myInstance.add(2);
otherInstance.add(3);

console.log(myInstance.prop); // 2
console.log(otherInstance.prop); // 3

 

When we invoke the object with the new pattern, its this keyword is bound to that object, so every object gets its own closure space.

P.S. I’ve ran into an interesting question on StackOverflow in this comment, so I made a post to try to answer it.

How to make CJUIDatePicker in a form in Yii – three-step example

I’m new to Yii php framework and I’m fiddling about it. I created a database and a date column in it, and pregenerated (with Gii – recommending this!) the controller and views for it.

However, the Create/Update forms made my input field for the date a text field.

So here is a quick recipe on how to use CJUIDatePicker widget (jQuery UI DatePicker object) for it:

1) Open the _form.php file in the view for your desired class. For me, it was in protected/views/guest/.

2) Find your row. My gii-generated form had columns in div’s and each div (each column) had three rows:

<div class="row">
 <?php echo $form->labelEx($model,'created'); ?>
 <?php echo $form->textField($model,'created'); ?>
 <?php echo $form->error($model,'created'); ?>
 </div>

3) Remove the middle row and replace it with the widget you want:

 

$this->widget('zii.widgets.jui.CJuiDatePicker', array(
// 'name'=>'birthdate',
 'name'=>"Guest[created]", // the name of the field
 'value'=>$model->created,  // pre-fill the value
 // additional javascript options for the date picker plugin
 'options'=>array(
 'showAnim'=>'fold',
 'dateFormat'=>'yy-mm-dd',  // optional Date formatting
 'debug'=>true,
),
 'htmlOptions'=>array(
 'style'=>'height:20px;'
 ),
 ));

There, that worked for me, and I’ll update this post when I run into bugs.

How to understand Javascript closures

In writing my programs with JavaScript, I never really completely understood the closure idea. I still think I don’t, but here is how I will try to explain it to myself. The idea and code used is from one of the Youtube videos of Douglas Crockfords ‘the good parts’.

We can start with a simple example. We want to turn digits into strings, something like this:

var names = ['zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'ate', 'nine' ];
function  digit_name(n) {
return names[n];
}
digit_name(4); // returns ‘four’.

This code will run ok, but it has a problem: the names array is global. Any other JavaScript on the page can break our code by writing over our “names” variable.

So we could do this:

function  digit_name(n) {
var names = ['zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'ate', 'nine' ];  // this is now private to our function
return names[n];
}
digit_name(4); // returns ‘four’.

This code is better – we have a self-sufficient function, without polluting global namespace. But now, every time we call the function, we re-initialize our names array.

How to avoid it? Here is an example:

var digit_name = function () {
var names = ['zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'ate', 'nine' ];
return function (n) {
return names[n];
}
}

This is now much better. What happens on executing? First, a private array is initialized and stored to memory. Then we return a function that will look up our names array and find the result.

Wait, what?

Well – the array is initialized and left in memory. And each time somebody calls our returned function from digit_name(n), that returned function will look up into the now-enclosured (in lack of better term) array.
It means that our later function call doesn’t execute digit_name – it only executes the anonymous function we returned. And that function has access to our private variable.
So the anonymous inner function will execute when needed, but our array is only initialized once (and held in a closure).

So the module pattern for creating stuff in closures should be something like this:

var singleton = function () {
var privateVariable; // only created once
function privateFunction() {  // only created once

};
return {
methodOne: function (param) { // this is exported out once.
// so when we call singleton.methodOne(param)
// later, the private stuff above is already there and
// within closure
},
methodTwo: function(a, b) { // another public method
….
},
publicInt: 10
};
}

// now calling and instantiating the object will have the object being created, private vars and methods left there, and public stuff exposed to us.

I think I got it right, hopefully this will help me (and possibly others) in the future.