XPage with computed CSS file - xpages

I am trying to implement an option for the user to set his own CSS in the front end.
I created an XPage like this:
<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core" rendered="false">
<xp:this.afterRenderResponse><![CDATA[#{javascript:
var externalContext = facesContext.getExternalContext();
var writer = facesContext.getResponseWriter();
var response = externalContext.getResponse();
response.setContentType("text/css");
response.setHeader("Cache-Control", "no-cache");
var param = context.getUrlParameter("myParam");
//HERE I WILL READ THE USER FIELD
writer.write("body{font-size:100pt;}");
writer.endDocument();
}]]>
</xp:this.afterRenderResponse>
</xp:view>
If I try to implement the CSS (XPage) like this
<xp:styleSheet href="/myCssXPages.xsp"></xp:styleSheet>
everything works fine until I set the property xsp.resources.aggregate to true. If I try to implement the file like this:
<xp:linkResource type="text/css" loaded="true" href="./myCssXPages.xsp">
<xp:this.attrs>
<xp:attr name="rel" value="stylesheet" loaded="true"></xp:attr>
</xp:this.attrs>
</xp:linkResource>
It could work, because now every CSS file will be aggregate except this file, but the order is wrong. This file is always loaded before the aggregated files are loaded but I need this file at the last position.
Is there any solution to set the order of the resources or why I can't use a XPage as CSS resource with aggregate true? Or is there another solution to implement a functionality like this?
UPDATE
The user created an settings document where he got a textfield. So he will save his css as string in an document.
I created also some default css file resources. But when the user sets his own css config, this shut override the content from the default files resources.
I can't use themes because themes are also implemented befor the aggregated css files a implemented.

You could load your CSS with a CSJS script and append it to the HTML head:
<xp:scriptBlock id="scriptBlockCss">
<xp:this.value><![CDATA[
function loadCss(url) {
var link = document.createElement("link");
link.type = "text/css";
link.rel = "stylesheet";
link.href = url;
document.getElementsByTagName("head")[0].appendChild(link);
}
loadCss( '/yourDB.nsf/myCssXPages.xsp' );
]]></xp:this.value>
</xp:scriptBlock>
Code shamelessly copied from http://requirejs.org/docs/faq-advanced.html#css

I'm not quite sure whether I really understand your use case. But my first thought is using an Xpages theme where you load a specific css file in a resource node, probably with the rendered attribute set appropriately.
For reference have a look at how the standard discussion template is using various themes, each of them using their own set of style sheet resources.
If that's not what you have in mind you'd have to tell us more about hwo and when your users should be able to select their own css, and where those specific css files shall be created and stored

Related

Add alternate tag to individual pages in liferay

I want to add a meta tag in my each individual page of life ray. I am could only find meta tag with description which is in the SEO of the pages in Control panel.
<link rel="alternate" href="http://example.com/xyz/abc" hreflang="en-au" />
Please help me out with this. I am unable to find an answer to this.
The best and permanent way is to create custom theme (or modify default one) and add general meta-tags, javascript / css files (which you want to appear on each page of portal) through head section of theme's portal_normal.vm file. However, if you want to restrict these tags for specific page(s) you can still do it through Velocity Objects like public / private layout, admin / user difference, current page name / URL, there are numerous options available.
If you are new to theme design, you can start with: Creating Liferay Themes
The other possible and quick way is to add js / css dynamically using javascript / jQuery as following:
if you are using pure javascript:
window.onload = function(){
loadjscssfile("myscript.js", "js");
loadjscssfile("javascript.php", "js");
loadjscssfile("mystyle.css", "css");
}
Or you can use jQuery:
jQuery(function(){
loadjscssfile("myscript.js", "js");
loadjscssfile("javascript.php", "js");
loadjscssfile("mystyle.css", "css");
});
general method:
function loadjscssfile(filename, filetype){
if (filetype=="js"){
var fileref=document.createElement('script')
fileref.setAttribute("type","text/javascript")
fileref.setAttribute("src", filename)
}
else if (filetype=="css"){
var fileref=document.createElement("link")
fileref.setAttribute("rel", "stylesheet")
fileref.setAttribute("type", "text/css")
fileref.setAttribute("href", filename)
}
if (typeof fileref!="undefined")
document.getElementsByTagName("head")[0].appendChild(fileref);
}
Reference: http://www.javascriptkit.com/javatutors/loadjavascriptcss.shtml
Add above code to the javascript section of the root of your pages.

JSF 1.2 response capture including resources

I am using JSF 1.2 with RichFaces. Is it possible to mimic the "Save as" of a web browser client? To be more precise, I want to add a "Download zip" on a page. The purpose is to generate a zip archive containing the HTML generated page with all necessary files to open that page with a correct layout.
I succeeded in the past to capture the HTML page by means of a HttpResponseWrapper.
But as soon as the page contains RichFaces components, some JS and images are required for a correct display. How could I get those resources to add them in the zip?
Use a HTML parser like Jsoup. It can easily find CSS/JS/image elements by jQuery-like CSS selectors and give you the resource URLs back so that you can download them individually.
InputStream input = new URL(url).openStream();
// ... Save webpage itself.
Document document = Jsoup.parse(savedWebPage, "UTF-8", url);
for (Element stylesheet : document.select("link[rel=stylesheet]")) {
InputStream input = new URL(stylesheet.absUrl("href")).openStream();
// ... Save individual stylesheet file.
}
for (Element script : document.select("script[src]")) {
InputStream input = new URL(script.absUrl("src")).openStream();
// ... Save individual script file.
}
for (Element img : document.select("img[src]")) {
InputStream input = new URL(img.absUrl("src")).openStream();
// ... Save individual image file.
}
CSS background images are not taken into account. You could consider a CSS parser like SAC on every individual CSS file.

Add the Umbraco "siteName" textstring to my .net usercontrol

I have a text string property type that I use to display the "siteName" in the page title:
<title><umbraco:Item runat="server" field="siteName" recursive="true" /></title>
What code do I need in my .net usercontrol to add the "siteName"?
<asp:Label ID="siteName" runat="server" Text="siteName should go here!"></asp:Label>
Can anyone help?
I've added this to the Umbraco forum and was suggested the following, but not sure how to included it in my .ascx file:
dynamic node = new umbraco.MacroEngines.DynamicNode(umbraco.NodeFactory.Node.GetCurrent()); siteName.Text = node._siteName;
You can use this in a usercontrol
//var node = new Node(123); // Get node by Id, good if you have information on a certain page
var node = Node.GetCurrent(); // Get the current node
var nodeProperty = node.GetProperty("siteName").Value;
siteName.Text = nodeProperty;
You want to have a public property in your usercontrol, and then when you expose the usercontrol to umbraco via a macro, that property will become a parameter of the macro as well.
When you reference the macro in your template, you can pas through the page property.
You might want to check out Umbraco tv:
http://umbraco.com/help-and-support/video-tutorials/introduction-to-umbraco/developer-introduction/macro-parameters.aspx
And an old (but mostly accurate) pdf:
http://umbraco.com/media/42a0202c-b0ba-4f84-bcf1-64dfd5230322-usingcontrolswithumbraco.pdf

What is an API object for the GE method FlyToObject?

In the GE Plugin API GEHelper.cs there is a function FlyToObject. Since I've been unable to get the kml to fly me to a placemark I thought I would use the API call.
The required arguments for FlyToObject are:
"dynamic ge,"
"dynamic feature,"
I'm stuck on what the 'feature' argument is. The description says "the api object". I'm not sure which api object that is referring to or how to create it.
What I'm trying to do is automatically (upon loading the file) "fly to" a placemark in my kml file.
If anyone knows how to do what I'm asking with KML that would be great. Here is the KML file I'm loading that does NOT work. This is one of Google's example files.
<kml xmlns="http://www.opengis.net/kml/2.2">
<Placemark>
<name>300m straight down</name>
<Camera>
<longitude>-122.4783</longitude>
<latitude>37.812</latitude>
<altitude>300</altitude>
<heading>0</heading>
<tilt>0</tilt>
<roll>0</roll>
<altitudeMode>absolute</altitudeMode>
</Camera>
</Placemark>
</kml>
THANKS!
If you are loading Google Earth into your own webpage, you have access to the GE API via javascript. Therefore if you want to set a certain view, use the following code
// Create a new LookAt.
var lookAt = ge.createLookAt('');
// Set the position values.
lookAt.setLatitude(36.584207);
lookAt.setLongitude(-121.754322);
lookAt.setRange(5000.0); //default is 0.0
// Update the view in Google Earth.
ge.getView().setAbstractView(lookAt);
More advanced: If you are loading a custom kml file, with your own Placemarks. Assign them as id as such in your kml file
<Placemark id="uniqueId">
Then, once loaded, use this code
placemark = ge.getElementById(uniqueId);
if (placemark == null) {
return false;
} else if (placemark.getAbstractView()) {
ge.getView().setAbstractView(lastViewLoaded);
}

Is it possible to add my custom JS file so page DOM could access it?

The problem now is that if I add some DOM elements I must put all JS inside tags creating huge mess in code for example:
<div onclick='//js monstrous oneliner with function declarations and so on..
//that must be repeated many times multipcating the whole mess..
'>
Here some pure html thing.
</div>
So can I add my custom JS file into rendered document in the same way as I'm able to add DOM elements ?
You can inject a JavaScript file from your extension into the page. Then, the onclick handler can refer to that directly.
Assume you have a script in your extension:
// myfile.js
function hello() {
alert('hello world');
}
In your content script, make the script tag:
var script = document.createElement('script');
script.src = chrome.extension.getURL('/myfile.js');
Now, you can write your HTML like this:
<div onclick="hello">…</div>
Note that because the content script doesn't run in the same JavaScript context as the page, doing this won't work from your content extension.
var div = document.createElement('div');
div.onclick = someFuncInMyExtension;
Yes, it's quite simple: see this document just to have an idea http://blog.jeffhaynie.us/cross-browser-way-to-dynamically-load-javascript.html

Resources