The engineering team at Alfresco has been working hard over the past year or so to make it easier to customize the Share user-interface. We've now started work on what I’d consider to be the last major piece of the extensibility puzzle – customizing the instantiation of client-side JavaScript widgets for each WebScript rendered Component.
The only way it was previously possible to change the widget(s) instantiated for a WebScript rendered Component was to copy and paste the supporting code to the “web-extension” path and then make the necessary changes to that copy. The major downside of this approach was that it generated an additional maintenance task to keep the copied code up-to-date with any changes that resulted from upgrades, service packs and hot-fixes.
The approach that we’re taking is to move all the logic and metadata about widget instantiation out of the FreeMarker template and to move it into the JavaScript controller as it is inherently easier to customize. The metadata will be stored as a standardized object structure in the model which will then be processed by a new custom directive in the FreeMarker template to output the JavaScript code necessary to instantiate the specified widgets.
This allows us to utilize the existing JavaScript controller extension capabilities so that extension modules can modify the default metadata object(s) to change the following:
As part of these changes we will also be updating the FreeMarker template to use a common “boiler-plate” structure to ensure consistency across WebScript rendered Components. We will utilize updated resource handling features in Surf to move all the CSS and JavaScript dependency requests into the template and remove the associated *.head.ftl file. A consistent pattern of <@markup> directives will be used throughout the template to further enhance customization options.
The first WebScripts converted are those on the Document Library page as these as this is the area most frequently customized – these changes have already been committed to the latest Community source code in SVN.
Let’s consider a simple example of what can be done….
Say we want to pop-up a message every time that a Document Library filter is changed. The obvious place to handle this would be at the end of the “onFilterChanged” function in the “documentlist.js” file. Up until now we had the following options:
Now though we have a slightly better option – we can create our subclass as with option 1, but we can create an Extension Module to the WebScript to both import our new library file and to instantiate our custom widget.
Our module configuration looks like this:
<module>
<id>Custom DocumentList Widget</id>
<description>Instantiate a custom DocumentList widget</description>
<customizations>
<customization>
<targetPackageRoot>org.alfresco.components.documentlibrary</targetPackageRoot>
<sourcePackageRoot>blog.demo.customization</sourcePackageRoot>
</customization>
</customizations>
</module>
This identifies the WebScript package that we want to target – in this case it’s the Document Library related WebScripts. We then create our custom Document List widget in our Extension JAR (“META-INF/doclib/extension/custom-documentlist.js”):
// Declare namespace...
if (typeof Blog == undefined || !Blog) { var Blog = {}; }
if (!Blog.custom) { Blog.custom = {}; }
(function()
{
// Define constructor...
Blog.custom.DocumentList = function CustomDocumentList_constructor(htmlId)
{
Blog.custom.DocumentList.superclass.constructor.call(this, htmlId);
return this;
};
// Extend default DocumentList...
YAHOO.extend(Blog.custom.DocumentList, Alfresco.DocumentList,
{
onFilterChanged: function CustomDL_onFilterChanged(layer, args)
{
// Call super class method...
Blog.custom.DocumentList.superclass.onFilterChanged.call(this, layer,args);
// Pop-up a message...
Alfresco.util.PopupManager.displayMessage({
text: 'Filter Changed!'
});
}
});
})();
Then we create an extension to the “documentlist.get.html.ftl” template to create a dependency to the file containing our custom widget (“webscripts/blog/demo/customization/documentlist.get.html.ftl” in our extension JAR):
<@markup id='custom-documentlist-dependencies' target='js' action='after' scope='global'>
<@script src='${url.context}/res/doclib/extension/custom-documentlist.js' group='documentlibrary'/>
</@markup>
Finally we create an extension to the “documentlist.get.js” controller to change the widget that is instantiated ('webscripts/blog/demo/customization/documentlist.get.js'):
// Find the default DocumentList widget and replace it with the custom widget
for (var i=0; i<model.widgets.length; i++)
{
if (model.widgets[i].id == 'DocumentList')
{
model.widgets[i].name = 'Blog.custom.DocumentList';
}
}
Finally, deploy the module, restart Alfresco and each time you change a filter in the Document Library you should see the popup.
Ask for and offer help to other Alfresco Content Services Users and members of the Alfresco team.
Related links:
By using this site, you are agreeing to allow us to collect and use cookies as outlined in Alfresco’s Cookie Statement and Terms of Use (and you have a legitimate interest in Alfresco and our products, authorizing us to contact you in such methods). If you are not ok with these terms, please do not use this website.