I'm trying to figure out exactly what css is included by the standard call to currentDesign.writeCssIncludes(pagecontext); found in headlibs.jsp. The documentation states simply that it is
Convenience method that writes the CSS include strings to the response.
Looking at what it seems to do, it will include /etc/designs/currentdesign.css which is built off the design components css, and /etc/designs/currentdesign/static.css, which is just a static file. But is this all that is will include?
In particular, what I'd like to do is include a clientLib-processed css file as part of my design. One way to do this is to manually build out the css include:
<link rel="stylesheet" href="<%= currentDesign.getPath() %>/myclientlib.css" />
But I'd prefer to let that get generated automatically, so that my designers have flexibility to structure the css files differently for different designs (i.e., for the "base" design they are fine with just a static.css file, but for the "fancy" design they want to use LESS css and break up the files more granularly). And it would be helpful to put design-specific css info with the components they affect, rather then needing to separate those.
You can use the <cq:includeClientLib> tag, combined with themes and/or categories, to mix and match bits of CSS.
But you may find it somewhat limiting; for instance, you can't specify a media attribute. If you need to do this, or your designers don't structure their CSS in a way that fits the themes/categories model, your fallback is the technique you've identified in your question, using <link> directly.
Update
An excellent question about themes! I have only seen them used in passing.
You can define a theme by just adding a new folder/node under /etc/designs/yourproject/clientlibs/themes, as a sibling to default.
You can pull in the clientlibs for a theme with the <cq:includeClientLibs> tag, perhaps under the control of some conditional logic. For instance, in one of my projects I have a theme called authoring which I only want to apply to the author instance; I pull it in with this code in headlibs.jsp:
<c:if test="${ (global['wcmmode'] eq 'EDIT') || (global['wcmmode'] eq 'PREVIEW') }">
<cq:includeClientLib theme="apps.myproject.authoring" />
</c:if>
I have not seen any documentation that would apply theme automatically to a particular subtree of the content tree, or based on the presence of a tag.
There is that cryptic statement "The theme name is extracted from the request." in the Adobe docs, which is backed up by this statement in the Sling docs, "ThemeResolverFilter Provides the Theme for the request. The theme is provided as a request attribute." So perhaps tacking &theme=apps.yourproject.foo onto a query string would apply that theme.
The list of CSS files is based on the property 'cq:designPath' of the page.
Related
I have a GWT 2.7 application where a lot of the styling is done in a CSS file referenced in the module XML file. I'd like to migrate this file to GSS so I can use some of the new functionality like variables and functions.
The GSS Migration Guide has instructions on migrating to GSS, but it appears to apply only to styles used through CSSResource objects. My understanding is that the only class selectors that can be accessed through CSSResources are those for which one declares accessors, and that all these class selectors will be obfuscated. This won't work for me because the selectors I want to use are unobfuscated ones that have mainly been added through UIObject.addStyleName and addStyleDependentName. I also don't want to have to add an accessor to an interface every time I want to add a new style.
As for the other three ways of using CSS files in a GWT project:
Using a <link> tag in the host HTML page.
Using the <stylesheet> element in the module XML file.
Using an inline <ui:style> element in a UiBinder template.
The first two don't seem to support GSS: even if I specify a GSS file it simply gets served directly to the browser without processing.
Is my only choice, then, to migrate to UIBinder? And if so, what's the minimal way to do this? (My current HTML host page is just the default host page with some additional stuff in the <head> element, so I feel like this ought to be straightforward).
Using a <ui:style> is the same as using CssResource. The .ui.xml file will generate the required ClientBundle and CssResource files, and those in turn will convert the GSS to css.
When you refer to <ui:style> content in a .ui.xml file, you do so as if you were caling an accessor on the interface, as {style.myStyleName} - because you are calling the accessor, but it is generated automatically. This may limit what you can do in your <ui:style> tag slightly. On the other hand, once you write CSS, your IDE can almost certainly add the accessors for you automatically, and if it doesn't, the failed recompile will list them so you can add them.
If instead you simply put a string literal "my-class-name" in your Java or HTML, the compiler has no way of knowing that "my-class-name" is the same or different everywhere in your app, and when to use one CssResource versus another. It also cannot rewrite those strings, so your CSS would remain unoptimized. Plus, now you can check for usages of a given css class name accessor - if no one uses it, delete it, then delete the CSS that uses it, to keep your .gss files smaller, and your application smaller.
You are correct in that <link> tags in the html, and <stylesheet> tags in the .gwt.xml do not result in running GSS. You do not need to use UiBinder (and I'm not a fan personally, but some people like it), but you do need to use the accessors, or there is no point to GSS as it stands.
If you want to avoid obfuscation and renaming, consider just running the closure-stylesheets directly, or something like LESS or SASS on your plain CSS file, which have no GWT integration, and so will work just fine with your string literals already in use. This will result in bigger compiled outputs, and remove your ability to find and remove unused CSS in an easy way.
As I discovered later on, it turns out that you can inject a GSS (or CSS) stylesheet as a CSSResource without the selectors being obfuscated. Simply add the following annotation to the stylesheet:
#external '*';
This will mark all selectors in the file as external, which means 1) that the CSSResource subinterface used as the type for the stylesheet resource will no longer be required to implement accessor methods corresponding corresponding to the class selectors in the stylesheet and 2) that the selectors in the stylesheet will be unobfuscated, so for example if you have a class .foo in the stylesheet you'll be able to apply it to entities using UIObject.addStyleName("foo").
This way you can easily get some of the major benefits of GSS (variables, functions, etc.) and CSSResource (injection into the page rather than serving another file) without having to make any changes to your workflow.
I have a requirement where I have 2 clientlibs having different CSS files for my website. The business author should be capable of switching the website look and feel by just changing the path of the design under page properties. While I am able to achieve that requirement by changing the clientlib categories name referred in my JSP of base template of my site, can the same thing be achieved by the business author without actually performing a code level change? Basically, he should be able to select the design path present under the page properties section, and selecting a different design should change the look and feel of the website. Please let me know how this can be achieved.
Note: I have placed my clientlibs under /etc/design/proj-name/ path
The foundation page component is designed to include css link in the head if a file called static.css is present under the design. It's done through the design object.
If you have different css in the static.css file under different designs then the look and feel will change with the design. However you will be stuck with one file and cannot leverage the utility of client libs.
This adobe doc suggest's doing something like this for css and related images
<%= currentDesign.getPath() + "/static/img/icon.gif %>
Data from design dialogs is stored under the design , swapping designs to change look and feel will cause data inconsistencies too.
Why not add a selection widget to the page and use it's value to selectively include different client lib categories instead of relying on the design.
I would like to implement an extensible templating mechanism in AEM, so as to permit component users to control markup for individual projects (designs) without modifying the components' pre-defined JSPs.
I have extended the <cq:include> tag to permit this, by passing a template name, which is then retrieved from the current design, falling back to the default markup when an override does not exist in the design:
<ct:template name="listNav/prev" />
This should load the jsp script from [1], unless the location does not exist, defaulting to [2]:
/etc/designs/projectName/component_templates/listNav/prev.jsp
/etc/designs/component_templates/listNav/prev.jsp
When using the extended tag, I'm receiving the exception (yes, the file exists):
Caused by: org.apache.sling.api.SlingException: javax.servlet.ServletException: javax.servlet.jsp.JspException: Could not find script /etc/designs/component_templates/listNav/prev.jsp
This all works when the component_templates is under /apps. Is there any way to make this work? Is there a better approach? I'd prefer to keep the component_templates with the designs, if possible.
I don't think it is a good idea to put application script to etc. They should be under /apps.
But I think it could work, if you add /etc path to the "Resource Search Path" of this service:
system/console/configMgr/org.apache.sling.jcr.resource.internal.JcrResourceResolverFactoryImpl
you can choose between different "designs" within the advanced page properties tab! afaik you should use this mechanism to declare different designts i.e. stylesheets etc. to your pages and of cause you don't need to modify anything at the jsp's to switch between different styles if implemented properly.
Have a look at this:
Adobe AEM Designs
The Client Library (ClientLib) feature in Adobe AEM (formerly Adobe CQ) makes it easy to include client libraries by category and each library can pull in other libraries through dependencies. However the documentation around "Themes" is a little thin.
This link is about all I can find on the subject. Here is an excerpt of the sample code:
<%-- theme only (theme-js + css) --%>
<cq:includeClientLib theme="cq.collab.calendar, cq.security" />
If this tag were to be used how would CQ determine what Client Libs to pull in? Does it look for a theme property of type String[]?
Or does it look for a certain directory structure in the /etc/designs section?
Or does it take the passed in categories and add theme-js to the end like so?
cq.collab.calendar.theme-js
Or is the theme invoked through the URL? In other words, the word "theme", in this case, is a token that is replaced with a selector from a URL applied theme?
Client Libraries reside in a cq:ClientLibraryFolder folder. This folder has a property called category. In the following example, cq.collab.calendar and cq.security are categories:
<cq:includeClientLib theme="cq.collab.calendar, cq.security" />
When this include is called, it is looking for any cq:ClientLibraryFolder with the category cq.collab.calendar or cq.security assigned to it. Using the theme property adds both the css and javascript of clientLibs residing in the themes folder of the parent ClientLibraryFolder. If you were to view your page source, these would be added to their own css and js files. For example, I created the following structure under the geometrixx clientLibary:
geometrixx
clientlibs
themes
myTheme (clientLibray)
css.txt
myCSS.css
js.txt
myJS.js
If, you use the theme property with this clientlib you would get a myTheme.css and myTheme.js file showing in your source/network tab.
The themed flag is a way to shut theme inclusion on and off. The following cq:include will include all the css in the clientLibrary, including stuff in the themes directory.
<cq:includeClientLib css="apps.geometrixx-main" />
However, if I add the themed flag and set it to false, anything under the theme directory is excluded:
<cq:includeClientLib css="apps.geometrixx-main" themed="false" />
So in that case, myTheme.css would not show up. One thing to note, is that the themed flag, only works on "pure css and js includes" Categories and theme properties would not work with this.
The answer to this question goes over this a bit: What exactly does currentDesign.writeCssincludes include?
It has been mentioned that theme is fetched from the request did a little digging an finally found out it tries to fetch it from request parameter named "forceTheme"
private String getDefaultThemeName(SlingHttpServletRequest request)
{
String theme = request.getParameter("forceTheme");
if (theme == null) {
theme = this.defaultUserThemeName;
}
return theme;
}
But needed request.getAttribute because using query parameters will send all requests to pub.
So guess this theme option is of no use at all.
Depends on what you mean by "theme". If you are used to wordpress, drupal, etc, what is called a theme in those systems is called a "design" in CQ5/AEM.
To set a design, you choose a "designpath" in the page properties. This will affect where information about components for each template is stored (all changes made in design mode about what components are allowed where are stored under this path) and is the convention for where CSS, JS, and non-DAM image resources are stored. It takes planning, but you can re-use code and markup in AEM/CQ5 but totally change the look by changing the design.
I working on a web app. Is it good to use own html tags than divs? I mean using own tags instead of classes. This will make it easier to bind up dynamic content by splitting up common classes with id.
Example
<div id="message">
My Message
</div>
Replace with this
<message>
My message
</message>
I don't understand why you want this, because now HTML5 supports a lot of semantic tags like <audio>, <address>, etc. Usually, you can achive block-effect (i.e. combining or grouping related content in a block) by <div class="myblock"></div> for special purposes. Anyway, as you've asked, then for your information—you can use custom tags in HTML. Also you can style those using CSS and can use selectors to perform operation on those using JavaScript.
Note: Prior IE9 versions don't support custom tags. Hence you should create your tags like this using JavaScript:
<script type="text/javascript">
document.createElement('mytag');
</script>
The main practical reason for not doing this is that IE 8 and older do not let you style your custom tags. As Vishal mentions, there’s a workaround to this, but it does not work when JavaScript is disabled. And as he points out, you can use the class attribute—you should use id only for uniquely identifying a single element.
You can also use class attributes for elements other than div. You can first select an element so that its default (non-CSS) rendering is the best possible (among available alternatives), then add a class attribute.
In CSS, you would then normally use a class selector without tag name, e.g. .message (if you use class=message).