Thursday, October 30, 2008

Learning Surf 4 - Modifying Share documentLibrary with Create Content button

This and the next blog entries will walk through the process of adding a new button to the documentLibrary section of Share which will allow the creation of new content using an in-line WYSIWYG editor.

This blog will add a 'Create' button to the toolbar of the Document Library module and open a popup when clicked showing a message 'feature not implemented yet'

Step 1 - mapping the terrain

As I have done in previous blog entries, I will draw a picture of the dependent files (xml, freemarker and javascript) that renders the relevant portion of the document library, and indicate what needs to be modified.

As shown before, the key files are:
  • 'site-data/pages/documentLibrary.xml' page references 'documentLibrary.xml' template-instance
  • 'site-data/template-instances/documentLibrary.xml' contains reference to 'org/alfresco/documentLibrary' template type
  • 'templates/org/alfresco/documentLibrary.ftl' contains the structure of the page with regions containing components including the 'toolbar' region
  • 'site-data/components/template.toolbar.documentLibrary.xml' defines the component to fit in region 'toolbar' of template 'documentLibrary' refrencing a webscript ui component registered to the url '/components/documentlibrary/toolbar'
  • site-webscripts/org/alfresco/components/documentlibrary/toolbar.get.desc.xml' describes the ui webscript registered to the '/components/library/toolbar' url, it includes freemarker renderers 'toolbar.get.head.ftl' and 'toolbar.get.html.ftl'.
  • 'toolbar.get.head.ftl' references toolbar.js and toolbar.css found in 'web/components/documentlibrary/' source folder.
Step 2 - Add the button to the template

The 'toolbar' component contains the space for the 'create' button I wish to add. Within the 'toolbar.get.html.ftl' I have added a couple of lines for the new button:

 <div class="new-folder hideable DocListTree"><button id="${args.htmlid}-newFolder-button" name="newFolder">${msg("")}</button></div>

<!-- Added by EEW 20081030 -->
<div class="separator hideable DocListTree">&nbsp;</div>
<div class="file-create hideable DocListTree"><button id="${args.htmlid}-fileCreate-button" name="fileCreate">${msg("button.create")}</button></div>
<!-- End Added -->

<div class="separator hideable DocListTree">&nbsp;</div>
<div class="file-upload hideable DocListTree"><button id="${args.htmlid}-fileUpload-button" name="fileUpload">${msg("button.upload")}</button></div>

Step 3 - Add Messages for the button

This code also changes the '' file adding the key/value 'button.create=Create',

Step 4 - Add CSS Entries and Images for the button

 and the toolbar.css used to render the button:

/* added by EEW 20081030 */

.toolbar .file-create button
background: transparent url(images/create-16.png) no-repeat 12px 4px;
padding-left: 32px;
.toolbar .file-create .yui-button-disabled button
background-image: url(images/create-disabled-16.png);

/* done added */

As implied by the css above, I have also created two new images to appear with the button: create-16.png and create-disabled-16.png. For testing purposes, I simply copied edit-blog-16.png.

Step 5 - Add the Button as a YUI Button

In 'toolbar.js', I have added a line to instantiate the YUI button named in the toolbar template in the 'onReady' YUI event listener

// added by EEW 20081030

// File Create button: user needs "create" access
this.widgets.fileCreate = Alfresco.util.createYUIButton(this, "fileCreate-button", this.onFileCreate,
disabled: true,
value: "create"
// done added

// File Upload button: user needs "create" access
this.widgets.fileUpload = Alfresco.util.createYUIButton(this, "fileUpload-button", this.onFileUpload,
disabled: true,
value: "create"

In this code, we see that the YUI button ties the name 'fileCreate-button' (which is the id in the button tag defined in 'toolbar.get.html.ftl'), and the event name 'onFileCreate', which will fire when the button is clicked. 

Step 6 - Add the Event Code

The event is also defined in toolbar.js:

* File Create click handler
* @method onFileCreate
* @param e {object} DomEvent
* @param p_obj {object} Object passed back from addListener method
onFileCreate: function DLTB_onFileCreate(e, p_obj)
var url = YAHOO.lang.substitute(Alfresco.constants.URL_CONTEXT + "page/site/{site}/blog-postedit?container={container}",
site: this.options.siteId,
container: this.options.containerId
window.location = url;
var notimpTitle = this._msg("title.notimp");
var notimpMsg = this._msg("message.notimp", "Create Content");

title: notimpTitle,
text: Alfresco.util.decodeHTML(notimpMsg),
noEscape: true,
modal: true,
buttons: [
text: this._msg("button.cancel"),
handler: function DLTB_onActionDelete_cancel()


This event handler will open a popup message for now showing that this feature is not yet implemented.

Step 7 - Add The Messages for the Popup Message Box

At this point I am only defining a placeholder for this event. In order to support the above popup, I have included the message keys to '':

## Added by EEW 20081031

title.notimp=Not Implemented
message.notimp = Feature {0} is not implemented yet.

## Done Added

Step 8 - Build, Deploy and Test

To test, I use ant task 'incremental-slingshot-tomcat' to build and deploy my changes to tomat. As a remider, the ant task requires environment variables TOMCAT_HOME and APP_TOMCAT_HOME to be defined to the installed tomcat.

And you should see this:


Mike H said...

Hey Ed
This tutorial is shaping up nicely - good work!

One (minor) point in your displayPrompt call: it's incorrect to call decodeHTML and have noEscape set. Setting noEscape is used when a component absolutely knows the content of a message and it needs to be displayed as HTML. Leaving noEscape to it's default (false) will cause the displayPrompt code to call encodeHTML which prevents XSS-style script injection.

You'll notice a lot of components alias Alfresco.util.encodeHTML to $html because it's used so often.

Looking forward to see what you do with the platform!

(UI Framework + DocLib Engineer)

edlovesjava said...

Thanks Mike!

Loïc said...

thanks a lot for this very verry interesting articles about surf.

i'm impatient to read the step 5

Davide said...

Hi, thanks for your contribution.
I don't know how to perform Step 8 - Build, Deploy and Test.
Can you give me some tips, please?

keshav chaurasiya said...

Hi Could you just tell the upload button event in the same way.i am getting so confuse to understance default flash uploader in flash-upload.js .my requirment is i want to add upload button on dashlet and want to use default upload button code has been used in alfresco .Kindly give some suggestion.

Thank you.