Adobe CQ5.5-How to display Page Thumbnail using API - aem

I have configured image for my page using sidekick >Page properties>Images tab. Now I want to fetch my this page image(thumbnail) in one of my jsp. Can someone give me pointers or code snippet for api class and method that I can use to achieve this.
Thanks,
Rajeev

I would suggest using the default image component as an example - /libs/foundation/components/image.
If you're putting your code into a component for your specific page type though, your code should be something like this:
if (currentNode.hasNode("image")) {
String imagePath = currentNode.getNode("image").getPath();
Resource imageRes = resourceResolver.getResource(imagePath);
image = new Image(imageRes);
image.loadStyleData(currentStyle);
image.setSelector(".img");
if (!currentDesign.equals(resourceDesign)) {
image.setSuffix(currentDesign.getId());
}
image.draw(out);
}
Keep in mind though, even though you set an image, it does NOT mean it will show up - if you're using the default page dialog for page properties, it will only show a broken image. That's because there is a bug in CQ where the sling:resourceType property of the image doesn't get set, and thus it won't show up. This is because the .img selector that gets put on the image doesn't know what to do, unless it get's pointed to a resource type with a definition for the .img selector, so it can properly render the image.
I've uploaded a package that you can use as a hotfix for the issue with the default /libs/foundation/components/page component dialog, so that it will actually set the resource type when you upload an image. You can find/download the package from my Google Drive
Hopefully that helps. Let me know if you need more help.
EDIT
If you're trying to get the page properties image from one page on another page, you just need to use a resource resolver. You should have one available to you in CQ, so this would essentially be the code:
Resource imageRes = resourceResolver.getResource(pathFromYourDialog);
Image image = new Image(imageRes);
The rest would be the same - you're just giving it a different path to start from.

I think Nicholaus was more on point with his EDIT answer to your immediate need. If the user is providing you a path to the thumbnail via the dialog (i.e. a DAM image).
You can simply create the image, or if it has DAM information you can load it as a DAM Asset and pull the necessary information.
Image image = new Image();
Resource imageResource = resourceResolver.getResource(imageUrl);
Asset imageAsset = imageResource.adaptTo(Asset.class);
Map<String, Object> valueMap = imageAsset.getMetadata();
long width = Long.parseLong(valueMap.get("tiff:ImageWidth").toString());
long height = Long.parseLong(valueMap.get("tiff:ImageLength").toString());
Object titleObject = valueMap.get("tiff:ImageTitle");
String title = (titleObject == null) ? null : titleObject.toString();
if (title != null)
{
image.setTitle(title);
}
image.setWidth(width);
image.setHeight(height);
image.setUrl(imageUrl);
This is a little long hand for what Nicholaus had suggested, the Image class will create itself based off the Resource you pass it. (actually upvoted Nicholaus for that, have some optimizations we can make).
Another, simpler option would be to just use the src that the user passes through, in the event that all you're doing is setting a thumbnail. I'm guessing you could be safe in doing something like:
in java:
String thumbSrc = properties.get("thumbSrc", "defaultThumbnail.path");
if (!thumbSrc.isEmpty())
{
pageContext("thumbSrc", thumbSrc);
}
in jsp:
<img alt="thumbnail" src="${thumbSrc}"/>
or if you don't want to do anything in the java you could just do something like
<c:if test="${not empty properties.thumbSrc}">
<img alt="thumbnail" src="${properties.thumbSrc}"/>
</c:if>
In order to get the same result as the first part in just jsp, you'd need to wrap it in a choose, because passing it through some processing before sending to view makes it easier to set default values.

Related

How to convert nodes to uris in TYPO3 Neos

I created a custom node type with a link field in TYPO3 Neos 1.2.1. When I pass the property value to the template, and try to render it as a link, then an execption is thrown:
Paths must not contain two consecutive slashes.
The link property value is »node://c969f0d4-2e01-87b9-25a8-6079c5a292fe«. I have read, that the link has to be converted to an URI first. However, the suggested processor has no effect on my site.
TypoScript2
prototype(Acme.MySitePackage:Teaser) < prototype(TYPO3.Neos:Content) {
templatePath = 'resource://Acme.MySitePackage/Private/Templates/NodeTypes/Teaser.html'
title = ${q(node).property('title')}
text = ${q(node).property('text')}
image = ${q(node).property('image')}
link = ${q(node).property('link')}
link.#process.convertUris = TYPO3.Neos:ConvertUris {
#forceConversion = true
}
}
Fluid Template
<f:debug>{link}</f:debug>
<neos:link.node node="{link}" />
I bet if you keep the processor and remove the neos:link.node from your template then the
<f:debug>{link}</f:debug>
will show a http:// link to the node.
The error happens with the link ViewHelper which expects a node or node path but neither a node:// not a href:// link (maybe we should support that in the future). So you can use a plain <a href="{link}">

Liferay6.0:Rendering DL portlet URL after clicking on custom TreeView portlet

I am using 6.0.6 CE to develop a requirement where a page has two portlets. One at left and other at right hand side.
1. Custom portlet which loads list of folders in a Tree structure for a given community. Here I am using jQuery zTree where doView get me the list of folders in JSON array.
http://www.ztree.me/v3/demo.php#_102
Document Library portlet
Every node folder has URL of document library such as:
http://yourdomain.com/web/oracle/home/-/document_library/view/11614
When I click any of it, reloads the entire page and DL portlet shows children of the given folder id 11614.
But because of this left hand side tree structure gets collapsed.
I wanted to retain the user selection on left side. For this I just thought of rendering only document library portlet on clicking on the folder but I am not able to achieve it thru any of the IPC.
Any suggestions would be appreciated.
Thanks
Prasad
Currently I am following this approach:
During page load I am getting the folderId from URL and in doView(), I am passing it as renderRequest param.
long selectedFolderId = 0;
String friendlyUrlValue = PortalUtil.getCurrentURL(renderRequest);
String[] urlArray = friendlyUrlValue.split("/");
String secondLastword = urlArray[urlArray.length - 2];
if (urlArray.length > 0) {
if (secondLastword.equalsIgnoreCase("view")) {
selectedFolderId = Long.valueOf(urlArray[urlArray.length - 1]);
}
}
JSONObject jSONObject = JSONFactoryUtil.createJSONObject();
createJson(themeDisplay.getScopeGroupId(), 0, jSONObject, renderRequest, fridendlyUrl);
if(selectedFolderId>0){
renderRequest.setAttribute("selectedFId", String.valueOf(selectedFolderId));
}
Refer this post https://www.liferay.com/community/forums/-/message_boards/message/47300920
There should be another approach to achieve reloading of only document Library portlet instead of entire page reload. Please let me know if there is any better approach for this.

How to get user's input from WicketStuff's TinyMCE

Pretty straight-forward question, but I can't find this anywhere. I'm using WicketStuff's TinyMCE to make a Rich Text Editor in my application, and can't find anywhere how to get the input from the text area. For brevity's sake, the following is a simplified version of the code I'm using.
private String input;
...
TinyMCESettings settings = new TinyMCESettings(TinyMCESettings.Theme.simple);
TextArea<String> textArea = new TextArea<String>("editor", new PropertyModel<String>(this, "input"));
textArea.add(new TinyMceBehavior(settings));
form.add(textArea);
Using this, I would expect the usual manner to simply use my String 'input' since it's set as the model. This always results in null as the model isn't being updated.
I tried using the auto-save plugin in case it was expecting the save button to be clicked (which doesn't update the model either), and neither worked. The only thing I've been able to do to get the user's input is to add a HiddenField, with a new model, and make a JavaScript call like
document.getElementById('hiddenField').value = tinyMCE.get('editor').getContent();
but this has led to other problems with trying to call the JS in the desired place and to get it to work properly. I feel this shouldn't be necessary anyways, as surely someone must have implemented a method to get the contents of the text area being used.
Any help would be greatly appreciated.
Thanks to a blog post at Nevermind Solutions, the way to get the model updated is to add the following JavaScript to the form's submitting button:
onclick="tinyMCE.triggerSave(true,true);"
My text area is inside a panel with the button outside of the panel, so it doesn't directly work for me. The trick was to add the JavaScript call to the button's onSubmit, move the logic into the onAfterSubmit, and to make the button MultiPart so that it could call the save trigger before doing the other logic associated to the model.
Hope this might help some others in the future.
You have to add a modifier to the submit button so that the model can update.
AjaxButton btnSubmit = new AjaxButton("btnSubmit", new Model()) {
#Override
public void onSubmit(AjaxRequestTarget target, Form<?> form) {
doSomething();
}
};
btnSubmit.add(new TinyMceAjaxSubmitModifier());
Have a look here for more info

tt_news: use news title as download title in list view

My news should not contain any text, except for the title. Instead, in the list view the title should directly point to the first attached file (a PDF).
Now I thought the simplest solution for that would be to hide the title, show only the attached files and give them the title of the related news entry via TypoScript.
For the detail view this code works fine:
plugin.tt_news.newsFiles {
labelStdWrap.cObject = TEXT
labelStdWrap.cObject.dataWrap = DB:tt_news:{GPvar:tx_ttnews|tt_news}:title
labelStdWrap.cObject.wrap3 = {|}
labelStdWrap.cObject.insertData = 1
}
...but it uses the GPvar for the currently displayed news, which of course is not present in list view.
So my question is: how do I get the ID of the currently iterated news entry, if possible at all?
I am open to other solutions as well.
You will need to use custom itemMarkerArrayFunc - fastest by copying the sample into your own extension: typo3conf/ext/tt_news/res/example_itemMarkerArrayFunc.php and adding custom marker to $markerArray.
The mentioned sample even demonstrates access to files so I assume that should not be a problem to modify it for your needs.
Note: if you haven't any own ext to copy the func into it, and you don't want to create such, try to copy it somewhere under fileadmin folder, modifying files in original destination is wrong idea, cause you'll lost all changes after next tt_news' update.
Easiest solution I found is using the labelStdWrap:
plugin.tt_news.newsFiles {
labelStdWrap = TEXT
labelStdWrap.field= title
}
More options can be found here: http://typo3.org/documentation/document-library/core-documentation/doc_core_tsref/4.0.0/view/5/13/

Showing an initially selected object in an ObjectAutoCompleteField on page load in Wicket

I've followed the Wicket by Example guide to get the ObjectAutoCompleteField working, and it does so quite nicely.
I have a huge problem, though, and that is to show an initially set object in the field when the page loads. The object is retrieved from a model I use for the form where the ObjectAutoCompleteField is used. Changing the ObjectAutoCompleteField changes the model attribute it is "connected" to, and any subsequent changes in the field shows the appropriate label in its place, just not the initial one when the page loads—the only thing that shows is the edit link (to get to the autocomplete functionality).
I've looked around in the documentation for the ObjectAutoCompleteBuilder but haven't found any corresponding method to even set the initial value explicitly on page load.
I finally managed to find a solution by looking through the classes relating to ObjectAutoCompleteField.
The ObjectAutoCompleteField is constructed by the build method in ObjectAutoCompleteBuilder. So, by calling the readOnlyRenderer method on the builder, creating a new ObjectReadOnlyRenderer creating a label inside its getObjectRenderer, I got the ObjectAutoCompleteField to render a preselected object on page load.
ObjectAutoCompleteBuilder<Author, Long> builder = new ObjectAutoCompleteBuilder<Author, Long>(provider);
builder.readOnlyRenderer(new ObjectReadOnlyRenderer<Long>() {
public Component getObjectRenderer(String id, IModel<Long> pModel, IModel<String> pSearchTextModel) {
return new Label(id, new PropertyModel<Author>(model, "author"));
}
});
One would think that this was the standard behaviour, but now I know for future reference.