550 likes | 937 Views
Latest Share Customization Techniques. Dave Draper (@_ DaveDraper ). Session Agenda. (Very quick) overview of Share/Surf Review of customization enhancements What Share customization was like before version 4.0 What was added for Share version 4.0
E N D
Latest Share Customization Techniques • Dave Draper (@_DaveDraper)
Session Agenda • (Very quick) overview of Share/Surf • Review of customization enhancements • What Share customization was like before version 4.0 • What was added for Share version 4.0 • An explanation of the Surf Extensibility Model • What’s New in version 4.2 • What’s next for Share
Key Things To Know • Share is built on Surf • Surf is an extension to Spring MVC “Is Surf moving backing Alfresco?”
History • 2007 • WebScripts • 2008 • Surf • Share 3.0 and 3.1 • 2009 • Share 3.2 • Surf and WebScripts contributed to Spring • 2010 • Share 3.4 • I joined Alfresco • 2011 • Surf converted to extensibility model (Share 4.0)
What Was Life Like Back in 2007 • No iPhone (not until June anyway) • No Android • jQuery only just released (version 1.0, Aug 2006) • Movies were still in 2D • HD-DVD was still a viable option • The global economy was still stable • Spain were still rubbish at football
Anatomy of a Surf Page Component Chrome Region Chrome Page FreeMarker Template Template-Instance Regions Components WebScripts
Share Customization Prior to Version 4.0 • Copy and paste to “web-extension” path • Maintenance problems
Share Customization in version 4.0 • Extensibility Model introduced into Surf • Extension Module configuration • Sub-Components • Customizations • SurfBug • Document Library specific extension points
Document Library Extension Points • Well defined, common, fine-grained use-cases • No Surf changes • Separate development effort
Extension Modules • Three deployment modes: • “auto” • “enable-auto-deploy-modules” • “manual” • Evaluated once per request • Default evaluation configuration can be overridden during manual deployment
Sub-Component extensions • Addressed the problem of 1-1 mapping of Regions to Components • Automatically generated from “legacy” Component configuration • Allow default (Sub-)Components to be removed or replaced and for new Sub-Components to be added before or after • Sub-Component evaluations allow for finer control of rendering
WebScript/Template Customizations • Allows additions and overrides to i18n properties • Allows model created by JavaScript controller to be manipulated • Allows <@region> and <@markup> directives in FreeMarker templates to be replaced or removed • Allows new <@region> and <@markup> directives to be added before or after existing directives
Please request for the <@markup> directives that YOU need to be added to the Share WebScripts!!!
JavaScript Controller Customizations • Run after default controller • An opportunity to alter the model passed to template
Localization Customizations • Update default WebScript properties for each request • Most specific locale “wins”
Configuration Customization • Configuration can be added to a module using <configurations> element • Generates a custom configuration model for each request • Uses underlying ConfigService implementation • Available in 4.0 service packs
<extension> <modules> <module> <id>Site_Conditional_Flash</id> <evaluator type="site.module.evaluator"> <params> <sites>noflash</sites> <sitePresets>.*</sitePresets> </params> </evaluator> <configurations> <config evaluator="string-compare" condition="DocumentLibrary" replace="true"> <file-upload> <adobe-flash-enabled>false</adobe-flash-enabled> <in-memory-limit>262144000</in-memory-limit> </file-upload> </config> </configurations> </module> </modules> </extension> Example taken from: http://blogs.alfresco.com/wp/ddraper/2012/03/05/share-configuration-extensibility/
The Surf Extensibility Model • An in-memory buffer (a linked list of elements) • FreeMarker directives manipulate elements • A new model is opened for each FreeMarker template • The following directives use the model: • <@region> • <@markup> (can be nested) • <@outputCSS> • <@outputJavaScript> • <@script> • <@link> • <@relocateJavaScript> • <@standalone>
How Extensibility Model is Built Up Unbound <!– This is the start a template--> <@markup id=“MARKUP_1”> <span>Some text</span> </@> <!– End of a template --> Open Content Close Unbound
Adding Content Unbound Open “MARKUP_1” <@markup id=“add” target=“MARKUP_1” action=“after”> <span>Some MORE text</span> </@> Content Close Open Unbound Content Close
ExtensibilityModel flush() Writer Unbound Unbound Open Open write() Content Content Close Close Unbound Unbound flush() OutputStream
The Problem: • Only coarse grained customizations were possible The Solution: • Make it easier to customize client-side JavaScript
How Client-Side Widgets Were Instantiated • Region/Component • WebScript • Descriptor • Controller • “head” file • FreeMarker template • Localization Properties • JavaScript resource • CSS resource
Double Pass WebScript Processing WebScripts head.get.head.ftl head.get.html.ftl Styles1.css body1.get.head.ftl Functions1.js body1.get.html.ftl ${head} Styles2.css body2.get.head.ftl Functions2.js body2.get.html.ftl
ExtensibilityModel Unbound Open JavaScript / CSS import Deferred <@outputJavaScript/> <@outputCSS/> Close Open <@link/> render() Content <@script/> Close Unbound
Share WebScript Refactor • Conversion to a common “boiler-plate” template • Client-side JavaScript widget definition moved into JavaScript controller • All logic moved from FreeMarker template to JavaScript controller • All JavaScript and CSS resource import statements moved into FreeMarker template • Deprecation of *.head.ftl files
The “Boilerplate” • <@markup id=“css”> • <@link href=“…” group=“…”/> • </@> • <@markup id=“js”> • <@script src=“…” group=“…”/> • </@> • <@markup id=“widgets”> • <@inlineScript group=“…”/> • <@createWidgets group=“…”/> • <@inlineScript group=“…”/> • </@> • <@markup id=“html”> • <@uniqueIdDiv/> • … • </@> • </@>
Controller Model “widgets” Elements • Object attributes: • “id” • “name” (required) • “initArgs” (defaults to region id) • “useOptions” (defaults to “true”) • “options” • “useMessages” (defaults to “true”) • “assignTo”
Why Refactor? • Consistency between WebScripts • Easier to instantiate custom client-side JavaScript widgets • A step towards performance improvements • Moving towards disabling Surf Chrome and WebScript Head processing by default • Moving towards JavaScript and CSS resource aggregation by default
Using JavaScript Extension Mechanism • Create custom JavaScript widget that extends Alfresco version • Use YAHOO.extend() function • Override default functions • Extend WebScript • Customize FreeMarker template to add import for file containing custom widget • <@markup id=“myWidgetSrc” target=“js” action=“after”> • Customize JavaScript controller to replace widget instantiation object • Use widgetUtils.findObject(model.widgets , “id”, <id>) • Change “name” attribute to reference new JavaScript widget
Module • <module> • <id>Custom DocumentList Widget</id> • <customizations> • <customization> • <targetPackageRoot> • org.alfresco.components.documentlibrary • </targetPackageRoot> • <sourcePackageRoot> • blog.demo.customization • </sourcePackageRoot> • </customization> • </customizations> • </module> Example taken from: http://blogs.alfresco.com/wp/ddraper/2012/05/22/customizing-share-javascript-widget-instantiation-part-1/
Custom JavaScript • // 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!" }); • } • }); • })(); Example taken from: http://blogs.alfresco.com/wp/ddraper/2012/05/22/customizing-share-javascript-widget-instantiation-part-1/
Custom FreeMarker template • <@markup id="custom-documentlist-dependencies" target="js" action="after" scope="global"> • <@script src="${url.context}/res/doclib/extension/custom-documentlist.js" • group="documentlibrary"/> • </@markup> Custom JavaScript controller • // Find the default DocumentList widget and replace it with the custom widget • for (vari=0; i<model.widgets.length; i++) { • if (model.widgets[i].id == "DocumentList") { • model.widgets[i].name = "Blog.custom.DocumentList"; • } • } Example taken from: http://blogs.alfresco.com/wp/ddraper/2012/05/22/customizing-share-javascript-widget-instantiation-part-1/
Surf Configuration Settings • “use-checksum-dependencies” • “aggregate-dependencies” • “calculate-webscript-dependencies” • “generate-css-data-images”
Checksum Dependencies • Processed by the “dependency.handler” Spring bean • org.springframework.extensions.surf.DependencyHandler • Default Spring bean definition can be overridden to change debug and production suffices or the checksum digest (defaults to MD5) • Production suffices: • “-min” • “-minified” • “” • Debug suffices • “” • “_src” • “-debug”
Resource Aggregation • Currently disabled by default (Share can be run with it enabled) • Enabling may break 3rd party extensions • Improves performance by reducing the number of HTTP requests • Includes inline JavaScript • Removes all JavaScript from HTML source
Calculate WebScript Dependencies • Still enabled by default • Can be disabled if you don’t want to use Rich Media AMP • Will be disabled by default in some future release • Required for legacy extensions • Empty *.head.ftl files are still processed so that extension versions are detected • Please try to phase out the use of *.head.ftl files !
Generate CSS Data Images • An alternative to CSS spriting • Too consuming a task to convert Share to CSS sprites • Use of CSS sprites would most likely break 3rd party customizations • Handles CSS @import statements • All CSS @imports must appear first in the file • Relative paths are generated when image cannot be found • Enabled by default
Dojo Support in Surf • Surf now includes support for Dojo applications • Programmatic implementations only • Dojo version 1.7 applications or greater • Uses existing resource aggregation capabilities to simulate Dojo build layers • Dynamic dependency analysis • Supports 3rd party extensions
Why Have We Done This? • Investigating future possibilities for developing Share • YUI 2 is no longer being developed • Simplify page development • Move from coarse-grained, tightly-coupled “flat” widget structure to fine-grained, decoupled, nested widgets • Improve customization/extensibility
Why Dojo? • AMD (Asynchronous Module Definitions) • Simple widget construction • Excellent inheritance patterns • Pub/Sub model • Unit testing framework • Comprehensive & consistent widget library • Accessibility support • Backed by big companies
2012 Summary • Configuration customization support added • Share WebScript refactoring • Repository Extensibility Container • Dynamic extension module support • Surf Maven Archetype • Dojo (1.7+) support in Surf
What Next For Share? • It WON’T be replaced • It WILL still be based on Surf • It WILL feature new pages built on an improved client-side framework
Key Messages and Actions • Performance and extensibility are key objectives for Share • Share is going to continue to move forward • Read the blogs • Use the forums • Ask questions • Request extension points • Raise bugs/feature requests on JIRA • Come along to the Share Customization Live! session to see this in action