cancel
Showing results for 
Search instead for 
Did you mean: 

Extending Share widgets

stuartleyland
Champ on-the-rise
Champ on-the-rise
Hi all. This is somewhat related to my previous question (http://forums.alfresco.com/forum/developer-discussions/alfresco-share-development/customising-share-...) which I am using as a stepping stone for my next task. My ultimate goal is to be able to make the preview on the document details page "float" down the page when you scroll down the page so that it is always visible. For example when you look at the version history the document is often out of sight. However as a baby step I would like to customise the preview widget so that it pops up a message when some event occurs. The problem I am having is that the document-details page tries to instantiate my component before the script containing it has been loaded. The actual error is:

<blockquote>
Uncaught ReferenceError: Training is not defined document-details?nodeRef=workspace://SpacesStore/e0d90fa6-580c-408a-9b52-d0cb330cfac7:212
</blockquote>

Here is my code:

/src/main/resources/alfresco/site-data/extensions/floating-preview.xml

<extension>
    <modules>
        <module>
            <id>Floating Document Preview</id>
            <description>Keeps the preview visible even when scrolling</description>
            <auto-deploy>true</auto-deploy>
            <customizations>
                <customization>
                    <targetPackageRoot>org.alfresco.components.preview</targetPackageRoot>
                    <sourcePackageRoot>com.XXX.training.components.preview.customization</sourcePackageRoot>
                </customization>
            </customizations>
        </module>
    </modules>
</extension>


/src/main/resources/alfresco/site-webscripts/com/XXX/training/components/preview/customization/web-preview.get.html.ftl

<<@markup id="custom-preview-dependencies" target="js" action="after" scope="global">
   <@script type="text/javascript" src="${url.context}/res/jquery/jquery-1.6.2.js" group="web-preview"/>
   <@script type="text/javascript" src="${url.context}/res/components/preview/extensions/floating-preview.js" group="web-preview"/>
</@markup>


/src/main/resources/alfresco/site-webscripts/com/XXX/training/components/preview/customization/web-preview.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.id == "WebPreview") {
      model.widgets.name = "Training.custom.WebPreview";
   }
}


/src/main/resources/META-INF/components/preview/extensions/floating-preview.js

// Declare Training namespace…
if (typeof Training == undefined || !Training) {
    var Training = {};
}

if (!Training.custom) {
    Training.custom = {};
}

(function() {
  // Define constructor…
  Training.custom.WebPreview = function CustomWebPreview_constructor(containerId) {
    Training.custom.WebPreview.superclass.constructor.call(this, containerId);
    return this;
  };

  // Extend default DocumentList…
  YAHOO.extend(Training.custom.WebPreview, Alfresco.WebPreview,
  {
     onReady: function CustomWP_onReady(layer, args)
     {
      // Call super class method…
      Training.custom.WebPreview.superclass.onReady.call(this);

      // Pop-up a message…
      Alfresco.util.PopupManager.displayMessage({
        text: "Hello!"
      });
    }
  });
})();


I have attached two files showing the where the widget is instantiated and where the JavaScript file that contains its definition is - note the line numbers, the widget is instantiated before the JavaScript file is included.

I imagine that the problem is due to how I change the WebPreview component - simply by changing the name when I find it in the list of widgets. This is how Dave Drapper does it in the blog post linked in my other question but I can't help but feel it's a fairly flaky way of doing business.

Any advice would be much appreciated.
7 REPLIES 7

scouil
Star Contributor
Star Contributor
Hi,

Very nicely written extension.
Only thing I'd change might be the use of widgetUtils in the .get.js if you're >= 4.2.e or 4.2.0 enterprise

For your problem I don't really know. Can you check if your cleint-side javascript is being correctly imported.
Could you just try to use the console to see if Training.custom.WebPreview actually exists once the page is fully loaded?

Thanks for your reply. Could you explain what you mean by the following please?

Only thing I'd change might be the use of widgetUtils in the .get.js if you're >= 4.2.e or 4.2.0 enterprise





I've been doing some further experimentation and found that if I take the two <@script> lines from my web-preview.get.html.ftl file and add them to web-preview-js-dependencies.lib.ftl in site-webscripts\org\alfresco\components\preview\include in the exploded war file everything works as expected, ie: I get a popup when the web previewer is ready.

So now my question becomes, how can I extend the web-preview-js-dependencies.lib.ftl file? I have tried the following:

  1. Renamed the web-preview.get.html.ftl file in my extension to match the one in the source.
  2. Copied the existing <customization> tag from the extension XML file and pasted it underneath and added '.include' to the end of the <targetPackageRoot>, ie:


  3. <customizations>
        <customization>
            <targetPackageRoot>org.alfresco.components.preview</targetPackageRoot>
            <sourcePackageRoot>com.XXX.training.components.preview.customization</sourcePackageRoot>
        </customization>

        ///New Tag
        <customization>
            <targetPackageRoot>org.alfresco.components.preview.include</targetPackageRoot>
            <sourcePackageRoot>com.XXX.training.components.preview.customization</sourcePackageRoot>
        </customization>
    </customizations>


  4. Modified the <sourcePackageRoot> tag in the new <customization> tag to add '.include' and moved the FTL file into an include folder in my extension
I worked through these in the order above without undoing the previous change, ie: i tried step 1, it didn't work so I tried step 2 but left the project as it was at the end of step 1. None of these changes have worked.

Is what I'm trying to achieve possible? Should I being going about it some other way?

scouil
Star Contributor
Star Contributor
Hi,

For my first point, starting the versions I quoted you have a new root object called widgetUtils.
With "widgetUtils.findObject" you can do the same as your loop in a single call (no doubt there is a loop behind the call but I still find it cleaner).
c.f. http://blogs.alfresco.com/wp/developer/2013/11/25/webscript-javascript-controller-extensions-recap/  for an example.

About extending the lib, first I'm not sure it's possible this way (don't think so), second I don't think it's a good idea.
For example the documentlist component includes that same lib. I'm not sure you want to append your js in that context too (even though it would have no effect since the js object is not instantiated)
Also, according to your second screenshot, if I understand well, your javascript is correctly included, right?
At least the javascript line to import it is there. Which is why I was wondering if it actually imported your js and if your self-contained function actually got executed.

Hello,

Thanks for pointing out the widgetUtils.findObject() method, now you mention it I have seen it used elsewhere and I'll clean my code up to use that - like you say it's more obvious what is going on there.

I've spent some more time today investigating this and I've had another idea. I feel like I should include my JavaScript files in the document-details.ftl file in alfresco\templates\org\alfresco as this is the file that deals with bringing in all of the components for that page. However I have so far been unable to get this to work. This is my document-details.ftl file:


<@region id="custom-javascript" target="web-preview" action="before" scope="template">
   <@script type="text/javascript" src="${url.context}/res/jquery/jquery-1.6.2.js" group="web-preview"/>
   <@script type="text/javascript" src="${url.context}/res/components/preview/extensions/floating-preview.js" group="web-preview"/>
</@>


Going to the document details page results in a blank page with nothing more enlightening in the logs than:

2014-01-13 17:54:08,428  WARN  [extensibility.impl.ExtensibilityModelImpl] [http-apr-8081-exec-3] The 'before' action was attempted to used when defining the base model by directive:ID: custom-javascript, ACTION:before

Does this seem like a better route to take? If so, any advice on how to resolve this problem?

Thanks very much for your help.

I have managed to fix my problem. Let's ignore the problems I had with the intermediate steps and go back to the original problem. The issue was that the JavaScript file containing the definition for a component was being included in the page after the page had tried to instantiate the component. The reason for this was because of the
group
element within the
<@script>
tag in the FreeMarker Template file. If you look at the original code the value was 'web-preview'. To fix the problem I changed this value to 'document-details'. This blog post by Dave Draper explains in further detail but a summary (and the specific details of my problem) will probably help.

Summary
The
group
element of the
<@script>
tag is used by Alfresco so that it can make one request for all files in a group.

Example - taken from the blog post
FreeMarker Template

<@script src="/aaa.js" group="1"/>
<@script src="/bbb.js" group="2"/>
<@script src="/ccc.js" group="3"/>
<@script src="/ddd.js" group="2"/>
<@script src="/eee.js" group="1"/>


HTML output

<script src="/aaa.js"></script>
<script src="/eee.js"></script>
<script src="/bbb.js"></script>
<script src="/ddd.js"></script>
<script src="/ccc.js"></script>


Note the aaa.js and eee.js were in the same group and were requested and output before bbb.js.

Specifics
webapps\share\WEB-INF\classes\alfresco\templates\org\alfresco\document-details.ftl
The following lines are at the top of this file, well before any components are added to the page (including the previewer):


<@templateHeader>
   <@script type="text/javascript" src="${url.context}/res/modules/documentlibrary/doclib-actions.js" group="document-details"/>
   <@link rel="stylesheet" type="text/css" href="${url.context}/res/components/document-details/document-details-panel.css" group="document-details"/>
   <@templateHtmlEditorAssets />
</@>


Note the
group
value for the
@script
tags - "document-details".

By changing the
group
value in my extension class to "document-details" I could ensure that these files were loaded before the component was instantiated. For completeness here is my extension file:

web-preview.get.html.ftl

<@markup id="custom-javascript" target="js" action="after" scope="global">
    <@script type="text/javascript" src="${url.context}/res/jquery/jquery-1.6.2.js" group="document-details"/>
    <@script type="text/javascript" src="${url.context}/res/components/preview/extensions/floating-preview.js" group="document-details"/>
</@markup>


Hopefully this will be of use to the next person who comes across this problem.

scouil
Star Contributor
Star Contributor
Hi,

Here you're extending a region not a markup section.
Regions are there to bind components to, not to append inline code.
I suspect this is the reason for your error.

More about regions and markup here:
http://blogs.alfresco.com/wp/developer/2011/08/12/customizing-alfresco-share-freemarker-templates/

Anyway, I like that approach less than your original one. I like the idea of having everything related to a component contained in that component and not in the global template.
I still don't understand why it doesn't work and don't have the time to build a project to test and debug it right now. Sorry.

Just to be sure:
in the .html.ftl you initially copy/pasted, there are 2 "<" in "<<@markup id"
It's a typo and not your actual code, right?

Hi Scouil,

Thanks for your reply. As you can see I've solved my problem. Thanks for your help.

Stuart