Can I make the Doctype on a master page (Kentico 11 Portal Engine) dynamic based on a macro? - kentico

I've inherited a Kentico 11 site that uses a doctype of
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
The client wants to create AMP variants of their pages using Kentico's AMP module, which uses a subdomain for any AMP content.
The module also includes a boolean macro {% AmpFilter.IsAmpPage() %} that tests if you're currently serving AMP content.
https://github.com/Kentico/kentico-amp
The issue I'm running into is that AMP seems to want a doctype of
<!doctype html>
. I don't want to change the doctype of the existing site, but it also doesn't look like I can evaluate macros within the master page template's doctype field.
Wondering if anyone has come up against an issue like this; if there's a way to allow macros to be evaluated in the doctype field, or some other approach I haven't thought of.

There's a similar issue when adding the HTML lang attribute to support WCAG 2.0 guidelines. However, the HTML attribute is controlled by a system file PortalTemplate.aspx, which uses the Kentico page's XmlNamespace property. To solve this, we added server-side code in to the master page's layout properties. However, this could also be done in a web part that you add to the master page. Then, instead of changing the page's XmlNamespace property, you would change the page's DocType property, based on whatever conditions you choose. Would this meet your needs?
<script runat="server">
/// Add Page_Load just to insert the "lang" attribute required by WCAG 2.0 Level A guidelines
protected void Page_Load(object sender, EventArgs e)
{
if (CurrentDocument != null)
{
CMS.UIControls.ContentPage page= this.Page as CMS.UIControls.ContentPage;
if (page != null)
{
System.Globalization.CultureInfo c= new System.Globalization.CultureInfo(CMS.Localization.LocalizationContext.CurrentCulture.CultureCode);
string lang= c.TwoLetterISOLanguageName;
page.XmlNamespace += " lang=\"" + lang + "\"";
page.XmlNamespace += " xml:lang=\"" + lang + "\"";
}
}
}
</script>
Mike

Related

Sublime Text adding additional opening tag at the beginning?

So every time I use html snippet or boiler plate with <ht + tab or enter
I get this extra opening tag? What gives?
<<!doctype html> <---- whats that additional tag at the beginning?
<html>
......
....
I got emmet installed by the way. Thanks
It's a snippet. You type html (or less), and press tab, it'll inserts all this content:
<!DOCTYPE html>
<html>
<head>
<title>$1</title>
</head>
<body>
$0
</body>
</html>
Note that if you repress tab again, it'll go to $1, and the last one is $0 (by default it's the end of the content).
So, don't type <ht, just ht, tab, and it'll insert everything for you. I really recommend you find yourself a course about Sublime Text, you're going to miss so much otherwise
That is the doctype decleration this is straight out of hte W3School docs:
The declaration must be the very first thing in your HTML
document, before the tag.
The declaration is not an HTML tag; it is an instruction to
the web browser about what version of HTML the page is written in.
In HTML 4.01, the declaration refers to a DTD, because HTML
4.01 was based on SGML. The DTD specifies the rules for the markup language, so that the browsers render the content correctly.
HTML5 is not based on SGML, and therefore does not require a reference
to a DTD.
Tip: Always add the declaration to your HTML documents, so
that the browser knows what type of document to expect.
You can read more about it here: http://www.w3schools.com/tags/tag_doctype.asp

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.

Migrate custom admin pages with dialogs from 4.5.12 to 5.3.4

We have code to open dialogs for links on admin pages by calling the javascript function mgnlOpenDialog(), like this,
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
[#assign cms=JspTaglibs["cms-taglib"]]
<html>
<head>
<title>UCP Books</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<link href="${this.request.contextPath}/.resources/admin-css/admin-all.css" type="text/css" rel="stylesheet" />
<script type="text/javascript" src="${this.request.contextPath}/.magnolia/pages/javascript.js"><!-- --></script>
<script type="text/javascript">
function displayDialog()
{
if ( ! window.focus ) return true;
var path = "${this.path}";
var nodeCollection = null;
var node = "${this.nodeName}";
var paragraph = null;
var repository = "${this.repository}";
var dialogPage = ".magnolia/dialogs/author.html";
mgnlOpenDialog( path, nodeCollection, node, paragraph, repository, dialogPage );
return false;
}
</script>
</head>
<body id="mgnl" class="mgnlBgLight mgnlImportExport">
<h2>
${this.messages.get("module.books.pages.AuthorDetailPage.header")}
<span class="mgnlControlButton" onclick="displayDialog();">
${this.messages.get("module.books.pages.edit")}
</span>
</h2>
<div class="pageFrame">${this.content}</div>
</body>
</html>
Now we are migrating our site from 4.5.12 to 5.3.4, and I noticed that the dialog definitions got updated. Now when I click on the link, there is still the dialog popup, but the popup is blank with the old style "Save" and "Cancel" buttons displaying at the bottom. It seems we need to convert our admin pages to content apps. But to do it that way will require a lot of changes in our code. So I'd like to know if there is an alternative way to replace mgnlOpenDialog() function to invoke the dialogs when I click on the links on the admin pages.
Thanks very much!
Aiping
Yeah this doesn't work any longer. Assuming you needed to open the dialogs explicitly because you had content you were editing in other workspaces then website. Correct?
When migrating custom data to M5, if you had that content in data workspace, you can use migration task to move it from the shared workspace into separate workspace and to also migrate your dialog. Not sure at the moment if it generates also app for you, but if not you can use this script to create one.
Once you have dialog migrated (or created from scratch) and your app created (either via script above or manually) you can just simply open any content in that app for editing and copy url from there. That would be the url you need to call to open dialog for editing from anywhere. It will be something like http://<your host>:<your port>/<contextPath>/.magnolia/admincentral#app:<yourAppName>:detail;/path/to/edited/content:edit
of course, assuming your subapp is called "detail" and your edit action "edit" as suggested in the tutorial or generated by the script.
Good luck,
Jan
Thanks Jan!
This seems a right direction to go by calling the url,
http://<your host>:<your port>/<contextPath>/.magnolia/admincentral#app:<yourAppName>:detail;/path/to/edited/content:edit.
I've configured the detail subapp and added this line to my code,
title
and it works. I'll post more in details later.
Thanks,
Aiping
Jan, I tried your solution as I commented here and it works well, except for one issue. Here I'm pointing to several screenshots to better explain it.
https://plus.google.com/u/0/photos/103180294078685589341/albums/6081701864232931905
On the app_faqSearch_1.png, there is a search form only.
The app_faqSearch_2.png is the page with the search results.
When I click on the "faq0004" link on app_faqSearch_2.png, the app_faqSearch_3.png appears. The code behind the scenes is,
faq0004
The problem is when I close the dialog tab "/FAQ/TOPICS/COMMAS/...", on the app_faqSearch_4.png, the search results are not there anymore since the view got reloaded.
Is there a way to configure to prevent the view from being reloaded if it's already opened, like for this URL in my case, /magnoliaAuthor/.magnolia/admincentral#app:faqSearch:main;
Or is there a way to explicitly open a dialog, instead of an editor, by passing the node path and workspace when click on the link like "faq0004"? Similar way to open the "editMessage" dialog in "contacts" app.
Thanks very much,
Aiping

OpenRasta Framework for component (or composite) based web application

we are trying to build a more loosely coupled composite based web application, and looking at various options and frameworks.
The idea is like when the user browse to a page, the uri will be resolved on the server for a resource and a list of actions to take based on the configuration.
The view will be composed by some html markups and some components that are based on other URIs for their contents. The components are reusable and should not have any ideas about each other (maybe the context).
this is just an idea, and wanna see how the OpenRasta framework would help on this. I might be completely wrong with the approach; maybe this can be easily done with current asp.net webform and mvc framework, but i would like to see your opinion.
I have just completed an OpenRasta site that relies on standard webcontrols that I inject into my views, passing on the strongly typed Resource (supplied by OR via the handler) to enable the control to surface resource properties etc in the usual way.
The resource instance carries the path to the control to be loaded and injected (Resource.ControlPath). This is set in the handler by concatenating aspects of the URI to find the control. This allows different URIs to request different versions of the same control that live at different locations in the site file hierarchy.
So, for example, ClientA requires an intro view with lots of client-specific text and features. ClientB also requires an intro page with different content and features.
This give two URIs
/myapp/clienta/intro
/myapp/clientb/intro
Configuration
ResourceSpace.Has.ResourcesOfType<IntroResource>()
.AtUri("/myapp/{client}/intro")
.HandledBy<IntroHandler>()
.RenderedByAspx("~/Views/IntroView.aspx");
IntroHandler.cs
public class IntroHandler
{
public OperationResult Get(string client)
{
var controlPath = ClientService.GetIntroControlPath(client);
if (controlPath.IsEmpty()) return new OperationResult.NotFound();
return new OperationResult.OK{
ResponseResource = new IntroResource{
ControlPath = controlPath,
Client=client
}
};
}
}
}
Intro.aspx
<%# Page Language="C#" Inherits="OpenRasta.Codecs.WebForms.ResourceView<xx.IntroResource>" MasterPageFile="~/Views/View.Master" %>
<asp:Content ContentPlaceHolderID="head" ID="head" runat="server">
<link href="/assets/CSS/intro.css" rel="stylesheet" type="text/css" />
<%
var userControl = Page.LoadControl(Resource.ControlPath) as UserControl;
if (userControl == null) return;
var property = userControl.GetType().GetProperty("Resource");
if (property == null) return;
property.SetValue(userControl, Resource, null);
IntroContentControlHolder.Controls.Add(userControl);
%>
</asp:Content>
<asp:Content ContentPlaceHolderID="body" ID="content" runat="server">
<asp:placeholder runat="server" id="IntroContentControlHolder"></asp:placeholder>
</asp:Content>
Intro.ascx
<%# Control CodeBehind="intro.ascx.cs" Language="C#" Inherits="xxxx.intro"%>
<h1>Welcome <%=Resource.Client%></h1>
...Lots more UI stuff
Intro.ascx.cs
public class intro : UserControl
{
public IntroResource Resource { get; set; }
}
Therefore each version of the intro control extends the View with client specific features.

Meta keywords before doctype declaration?

I recently was browsing a local web design firm's portfolio and found all their sites' code begins as such:
<meta name="keywords" content="a whole bunch of keywords for their site">
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
...
I was able to determine that the pages were generated by dreamweaver (at least in part).
Did dreamweaver do this, or did their "developer" just paste the code at the top of the document.
It is my impulse that this is bad practice and it might work incorrectly on some platforms but it got me wondering as to whether or not their may be a reason for this?
That is a terrible practice and invalid HTML. I bet that this would throw IE directly into quirks mode.
But as for your question, either the developer is a script kiddie and shoved the <meta> tag in there with little knowledge of the outcomes, or Dreamweaver did it. I hope it was Dreamweaver...
FYI - just had this issue and Dreamweaver does not put the meta tags in the correct position automatically. Cursor must be placed beforehand into an editable region.

Resources