What is the proper way to include images in Hybris using siteResourcePath or <theme:image>
In what cases should we use in each of them?
If we are using <theme:image> should we mention the property in theme-alpha-deskptop_en.properties?
What is the proper way to include images in Hybris using
siteResourcePath or <theme:image>?
Both are used to display the static image or a content. siteResourcePath, themeResourcePath, and other ResourcePath are used to get the static contents like CSS, image, font, js etc.
In what cases should we use in each of them?
Let say you want to show the static image on some page with regardless of your theme, site, lang. which means it's common for all, so you can simply use siteResourcePath or commonResourcePath(based on your folder-structure).
<img src="${commonResourcePath}/images/my_image_300x300.jpg" alt="My Image" title="My Image" />
Now, in another scenario where you have to display different static image based on your theme/site/lang, so here you can declare a respective value in each properties files and pass the code to <theme:image>. value of respective file has peeked. Like missingProductImage.
<theme:image code="img.missingProductImage.responsive.product" alt="${fn:escapeXml(product.name)}" title="${fn:escapeXml(product.name)}"/>
theme-alpha-desktop_de.properties
img.missingProductImage.responsive.product=/_ui/responsive/theme-alpha/images/missing_product_DE_300x300.jpg
theme-black-desktop_en.properties
img.missingProductImage.responsive.product=/_ui/responsive/theme-black/images/missing_product_EN_300x300.jpg
If we are using should we mention the property in
theme-alpha-deskptop_en.properties?
As I mentioned in above example, if you are using <theme:image> then you have to mention a respective value in all respective properties files (not only in theme-alpha-deskptop_en.properties). Which are based on your theme, UI experience, and supportive language.
final String siteRootUrl = contextPath + "/_ui/" + uiExperienceCodeLower;
final String sharedResourcePath = contextPath + "/_ui/" + SHARED;
final String siteResourcePath = siteRootUrl + "/site-" + siteName;
final String themeResourcePath = siteRootUrl + "/theme-" + themeName;
final String commonResourcePath = siteRootUrl + "/" + COMMON;
Related
We have developed a site with typo3 v8.7.11. We want to display the search box in the sidebar section, for this we installed the indexed_search extension. B
How to display a search box in all the frontend page sidebar section?
Edit:
The search and form action of the SearchController are both non-cacheable. This means that you would place a non-cacheable plugin on each of your pages, if you used my old answer. This harms performance and could have other side-effects.
Nowadays I usually simply include a search form on each of my pages by including this in my Fluid Template:
<form action="{f:uri.action(controller: 'Search', action: 'search', extensionName: 'indexedsearch', pluginName: 'Pi2', pageUid: searchPid)}" method="POST" role="search">
<input type="text" name="tx_indexedsearch_pi2[search][sword]" spellcheck="false" autocomplete="off" />
<button type="submit">Search</button>
</form>
I hand over the searchPid variable via TypoScript like this:
page.10.variables.searchPid = TEXT
page.10.variables.searchPid.value = <Pid where search results should be displayed>
Old answer:
My tip would be to create a TypoScript object that actually includes the plugin, like this:
lib.headerSearch = USER
lib.headerSearch {
userFunc = TYPO3\CMS\Extbase\Core\Bootstrap->run
extensionName = IndexedSearch
pluginName = Pi2
vendorName = TYPO3\CMS
switchableControllerActions {
Search {
1 = form
2 = search
}
}
features {
requireCHashArgumentForActionArguments = 0
}
view < plugin.tx_indexedsearch.view
view.partialRootPaths.10 = Path/To/Partial/
view.templateRootPaths.10 = Path/To/Template/
settings =< plugin.tx_indexedsearch.settings
}
Then, in your template, include it like this
<f:cObject typoscriptObjectPath="lib.headerSearch" />
Note that you should create a new "Search.html" Template in Path/To/Template/Search/ for this TS-Plugin, so that it does not interfere with the regular plugin. Also, be careful if you include the search slot on the same page as the search Plugin itself.
you have multiple options:
copy the HTML of the form from the search plugin in the normal content and insert it in your page-(html-)template.
create a special BE-column, insert the search-plugin into this column and render this column inherited in all pages
make a special page not visible in FE, where you insert the search-plugin and include this special CE in the rendering of every page (use a CONTENT object in typoscript to select that special CE)
include and configure the plugin in typoscript. (see answer of Thomas Löffler)
I prefer option 2 as it is most flexible and does not need any special page or content IDs, which might change with time (option 3). It also can handle any kind of CE.
Option 1 needs manual fixing if there are changes in the plugin rendering after an update for example.
Option 4 is not possible for each plugin or CEs at all to inherit. If you can configure the plugin with typoscript it is a fine option because you do not need any record (from tt_content)
for option 2:
temp.inheritedContent = CONTENT
temp.inheritedContent {
table = tt_content
select.orderBy = sorting
// -- use your own column id: --
select.where = colPos = 100
select.languageField = sys_language_uid
slide = -1
}
Use a TYPO3 extension, which can be a copy (fork) of the newly developed version of macina_searchbox
Template Module: Add "Macina Searchbox" under "include static from extensions" .
Use this or a similar TypoScript to include it, where '6' in this example is the search page. Use your own page id instead.
Constants:
lib.macina_searchbox {
pidSearchpage = 6
}
Setup:
10 = TEMPLATE
10.template = FILE
10.template.file = fileadmin/template/template.html
10.workOnSubpart = DOKUMENT
10.marks {
SUCHE < lib.macina_searchbox
LOGO = TEXT
LOGO.value = <img src="fileadmin/template/img/logo.png">
NAVI= HMENU
NAVI {
Then you can edit the Fluid template files in the folders below macina_searchbox/Resources/Private/ to modify the output of the searchbox. This method is necessary in order that the search result list will not be shown on the page. You must instead insert an Indexed Search plugin on your search page, which has id=6 in this example. SUCHE is the marker in the main template of the website. Use your own marker.
The easiest way is to copy the given plugin from indexed_search to a variable you use in your template.
When you e.g. use FLUIDTEMPLATE:
page.10 = FLUIDTEMPLATE
page.10.variable.searchBox < plugin.tx_indexedsearch
After that you can assign a separate template and make other modifications by changing page.10.variable.searchBox with the possible configuration here: https://docs.typo3.org/typo3cms/extensions/indexed_search/8.7/Configuration/Index.html
When trying to retrieve DocumentPageTitle and DocumentPageDescription using GetStringValue() on a custom page type TreeNode, the result is always coming back as the default value (in this case an empty string) passed into the method.
I'm able to successfully retrieve other column values as well as standard document properties such as DocumentName, DocumentID and AbsoluteURL, but not the document meta properties.
The respective fields in the Meta tab of document/page do have values and are being successfully rendered in the by default such as <meta name="description" content=".." />
// returns empty string
string documentPageDescription = DocumentContext.CurrentDocument.GetString("DocumentPageDescription", string.Empty);
// returns empty string
TreeNode document = parameters[0] as TreeNode;
string documentPageDescription = document.GetStringValue("DocumentPageDescription", string.Empty);
I've tried setting option Inherits fields from page type to "Page (menu item)", but that did not help.
Does the custom page type need to inherit from something specifically or have a specific setting activated to access these values? Or if what I think is a TreeNode in fact isn't, how could I get the TreeNode from this object that has the properties listed before available?
Thank you for any help you can provide.
ValidationHelper.GetString(CMS.DocumentEngine.DocumentContext.CurrentDocument.GetValue("DocumentPageDescription"), string.Empty)
Two things to check, one, are you sure the meta data is available on the page you are pulling? Two, is your API actually pulling all the data for that page?
I've used these in my test and both returned the metadata.
var page = DocumentHelper.GetDocuments().Path("/Articles/Coffee-Beverages-Explained").FirstObject;
Response.Write(page.GetStringValue("DocumentPageDescription", string.Empty));
TreeProvider tree = new TreeProvider(MembershipContext.AuthenticatedUser);
TreeNode tn = tree.SelectNodes().OnCurrentSite().Path("/Articles/Coffee-Beverages-Explained").FirstObject;
Response.Write(tn.GetStringValue("DocumentPageDescription", string.Empty));
The DocumentPageTitle and DocumentPageDescription were coming back as null when the custom page type document/page was inheriting from parent/global values.
I was able to use the following to get the properties when not inheriting, while falling back to the parent value when inheriting was taking place:
string documentPageTitle = document.GetStringValue("DocumentPageTitle", DocumentContext.CurrentTitle);
This approach came from the following issue on Kentico DevNet.
Thank you for your help and suggestions, it's appreciated.
I understood how we parse the url parameters in express routes, as in the example
How to get GET (query string) variables in Express.js on Node.js?
But where do the url parameters come from in the first place?
EDIT:
Apparently, I can build such a query with jquery (i.e $.get). I can append params to this query object. It s cool, but still i m trying to understand how we achieve this in the query that renders the page as a whole.
An example : when i choose the oldest tab below, how does SO add ?answertab=oldest to the url so it becomes :
https://stackoverflow.com/questions/30516497/how-do-we-add-url-parameters-ejs-node-express?answertab=oldest#tab-top
The string you're looking at is a serialization of the values of a form, or some other such method of inputing data. To get a sense of this, have a look at jQuery's built in .serialize() method.
You can construct that string manually as well, and that's pretty straight forward as well. The format is just ?var1=data1&var2=data2 etc. If you have a JSON object {"name": "Tim", "age": 22} then you could write a very simple function to serialize this object:
function serializeObject(obj) {
var str = "?";
for(var i = 0; i < Object.keys(obj).length; i++) {
key = Object.keys(obj)[i];
if (i === Object.keys(obj).length - 1)
str += encodeURIComponent(key) + "=" + encodeURIComponent(obj[key]);
else
str += encodeURIComponent(key) + "=" + encodeURIComponent(obj[key]) + "&";
}
return str;
}
Running seralizeObject({"name": "Tim", "age": 22}) will output '?name=Tim&age=22'. This could be used to generate a link or whatnot.
The page author writes them so. This is how they "come in the first place". The authors of an HTML page decide (or are told by website designers) where to take the user when he clicks on a particular anchor element on it. If they want users to GET a page with some query parameters (which their server handles), they simply add query string of their choice to the link's href attribute.
Take a look at the href attribute of the oldest tab you clicked:
<a
class="youarehere"
href="/questions/30516497/how-do-we-add-url-parameters-ejs-node-express?answertab=oldest#tab-top"
title="Answers in the order they were provided"
>
oldest
</a>
When you clicked it, the browser simply took you to path indicated in href attribute /questions/30516497/how-do-we-add-url-parameters-ejs-node-express?answertab=oldest#tab-top relative to the base URL http://stackoverflow.com. So the address bar changed.
stackoverflow.com may have its own system of generating dynamic HTML pages. Their administrators and page authors have configured their server to handle particular query parameters and have put in place their own methods to make sure that links on their pages point to the URL(including query string) they wish.
You need to provide URIs with query strings of your choice (you can build them using url.format and querystring.stringify) to your template system to render. Then make your express routes process them and generate pages depending on their value.
In my xpage which is bound to a domDoc datasource I want to build a preview mechanism for images stored in the datasource's richtext field. Designer and server are V 9.0.1.
The names of the attached images are stored as an array in a viewScope var and fed as source to a repeat control. The image control sits inside the repeat. I also put a link control alongside the image offering a means to download the file. The calculated url looks like this:
/dbpath/dbfile.nsf/xsp/.ibmmodres/domino/OpenAttachment/dbpath/dbfile.nsf/docunid/rtBodyField/filename.gif
Calculation of the link works perfect, but the images are never displayed. Instead Firebug tells me that the image's source url could not be resolved. And indeed I see that the db path part has been rendered twice before the /xsp/.ibmmodres/domino/OpenAttachment/ portion of the url (but only once after it!):
/dbpath/dbfile.nsf/dbpath/dbfile.nsf/xsp/.ibmmodres/domino/OpenAttachment/dbpath/dbfile.nsf/docunid/rtBodyField/filename.gif
Here's the code I'm using to calculate the source urls for both the link (using its value property) and the image (using its url property):
var unid=context.getUrlParameter('documentId');
var p=facesContext.getExternalContext().getRequestContextPath();
return p+'/xsp/.ibmmodres/domino/OpenAttachment'+p+'/'+unid + '/rtBodyFld/'+imgEntry;
Here's what I tried so far to solve that miracle:
a) calculate the db path (facesContext...) beforePageLoad, store it in a viewScope, then reference the viewScope when build the image's source ==> same result as above
b) used the image's value property instead of url ==> same result as above
c) use a standard html <img /> tag where the src argument is built using "#{javascript:...}" with the identical code as above ==> this works fine!
So I do have a workaround with solution c), but still I'd like to learn why the path element is doubled only in the first portion of the url, and only for image resources.
EDIT:
tried two more things:
d) pulled the image control outside my repeat then added a fixed (and valid) filename to the calculated url ==> same (bad) result as above
e) calculated the entire url portion only except the image file name beforePageLoad and stored that in a viewScope var ==> this is the weirdest result: outside the image viewscope contains the correct path info, but inside I see the same bad result as above. So it appears that inside the image the viewScope variable is altered in parts???
This is so weird that I feel I must have made a very simple and stupid error here, but what could that be?
Are you looking for how to calculate attachment URLs? Try this:
function getAttachmentURL(docID:java.lang.String, attachmentName:java.lang.String) {
var base = getBaseURL();
var middle = "/xsp/.ibmmodres/domino/OpenAttachment";
if (base.substr(0,4) == "/xsp") {
middle += base.substr(4);
} else {
middle += base;
}
var result = base + middle + "/" + docID + "/$File/" + attachmentName + "?Open";
return result;
}
function getBaseURL() {
var curURL = context.getUrl();
var curAdr = curURL.getAddress();
var rel = curURL.getSiteRelativeAddress(context);
var step1 = curAdr.substr(0,curAdr.indexOf(rel));
// Now cut off the http
var step2 = step1.substr(step1.indexOf("//")+2);
var result = step2.substr(step2.indexOf("/"));
return result;
}
Hope that helps!
Alright, it is as I feared: I had not taken into account that a relative url defined for an image control is automatically prefixed with /dbpath/dbfile.nsf/.
That's why that part always appeared twice no matter how I calculated my own url. It would have worked if I had used absolute urls (http://server/path/dbfile.nsf/...)
So instead the calculated url has to be built like that:
var unid=context.getUrlParameter('documentId');
var p=facesContext.getExternalContext().getRequestContextPath();
return '/xsp/.ibmmodres/domino/OpenAttachment' + p + '/' +
unid + '/rtBodyFld/' + imgEntry;
We have a compound CT, which outputs the code field of one of the component.
The dream-weaver part of CT is as follows:
<!-- TemplateBeginRepeat name="Component.HTMLCode" -->
##Component.HTMLCode##
<!-- TemplateEndRepeat -->
However this CT displays the code field on the page, instead of converting into HTML.
For eg: If the code field has a value as ->
<div align="center" id="loginapp"></div>
Then this same value is displayed on page instead of parsing.
In the page source, we get output as "< ;div align=" ;center" id=" ;loginapp" ;> ;< ;/div> ;"
I know this can be resolved if we use C#.
But is there any way using dreamweaver to stop the conversion of special characters?
You should use dwt to publish the code to server, I mean create new dwt for every code and just paste the code in the dwt. you can use this dwt with emply component or resource type component.
or if you want to use text field, try following tbb code. add this tbb at the end of the template.
public override void Transform(Engine engine, Package package)
{
Regex objExp = new Regex(#"&#\d+;", RegexOptions.IgnoreCase);
Regex objDecExp = new Regex(#"[^0-9]", RegexOptions.IgnoreCase);
this.Initialize(engine, package);
string strPackage = package.GetValue("Output");
strPackage = unescapeHTML(strPackage);
strPackage = objExp.Replace(strPackage, delegate (Match match)
{
string strInput = match.ToString();
strInput = objDecExp.Replace(strInput, "");
int intValue = Convert.ToInt32(strInput);
char strChar = (char)intValue;
return strChar.ToString();
});
strPackage = strPackage.Trim();
Item objOutput = package.CreateStringItem(ContentType.Html, strPackage);
package.PushItem("Output", objOutput);
}
private string unescapeHTML(string strInput)
{
StringBuilder strOutput = new StringBuilder(strInput);
strOutput.Replace(""", """);
strOutput.Replace(" ", " ");
strOutput.Replace("&", "&");
strOutput.Replace("'", "'");
strOutput.Replace("<", "<");
strOutput.Replace(">", ">");
strOutput.Replace("¡", "¡");
strOutput.Replace("¢", "¢");
strOutput.Replace("£", "£");
strOutput.Replace("¤", "¤");
strOutput.Replace("¥", "¥");
strOutput.Replace("¦", "¦");
strOutput.Replace("§", "§");
strOutput.Replace("¨", "¨");
strOutput.Replace("©", "©");
strOutput.Replace("ª", "ª");
strOutput.Replace("¬", "¬");
strOutput.Replace("", "­");
strOutput.Replace("®", "®");
strOutput.Replace("¯", "¯");
strOutput.Replace("°", "°");
return strOutput.ToString();
}
}
If I recall correctly it is depending on your fieldtype, if in your Schema you use a normal text field, then HTML is escaped, if you use a rich text field, it will be resolved.
An option would perhaps be to write a Dreamweaver Custom function which allows you to unescape the field (represent it as an HTML field rather than a text field). As you mentioned you could also do it in a TBB, but the Dreamweaver Custom Functions are directly callable from the DWT Template. Either way I think you indeed need to do some coding yourself.
RenderComponentField has two parameters: bool htmlEncodeResult, and bool resolveHtmlAsRTFContent. Are you using this built in function?
Thanks for your help. After lots of trials with dreamweaver code, we decided to use C# TBB instead which solved the purpose.
Also reading the multiline field as a textfield was one of the mistake we committed. This caused the field value to be displayed on page instead of rendering as a code behind.
We finally solved the issue using "MultilineTextField".