I'm a Plone user and I've been using tal macros from Products.Five.browser.pagetemplatefile.ViewPageTemplateFile for quite a while and created a library of existing macros and templates.
I started using chameleon page templates through grokcore.chameleon 1.0.3, and would like to keep using them within the existing framework. I.E. I want to be able to import tal macros and then fill out macro slots using chameleon.
So far I tried several ways of importing existing macro but none of them worked. 'Load' keyword isn't enabled even though Chameleon 2.14 is installed[1].
I've been looking for a compatibility layer, but all I've found so far is z3c.pt, which purpose is to speed up .pt page rendering and not provide compatibility layer.[2]
Are there any packages that activate tal macro and then insert information from a Chameleon page template?
As a workaround I can render tal template, render chameleon template and then do string substitution, but there's got to be someone who solved this problem in a more elegant way.
[1] how to use macros with pyramid / ZPT (Chameleon)
[2] https://pypi.python.org/pypi/z3c.pt
Update
As a workaround I create a function that generates an intermediate page, which accepts html generated by chameleon page template.
common.py
from zope.publisher.browser import BrowserView
from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile
def insert_into_master(html, view):
class View(BrowserView):
def __call__(self):
self.data = html
return ViewPageTemplateFile('pt/master_holder.pt')(self)
rendered = View(view.context, view.request)
return rendered()
pt/master_holder.pt
<html
xmlns="http://www.w3.org/1999/xhtml"
xmlns:tal="http://xml.zope.org/namespaces/tal"
xmlns:metal="http://xml.zope.org/namespaces/metal"
xmlns:i18n="http://xml.zope.org/namespaces/i18n"
metal:use-macro="here/main_template/macros/master"
i18n:domain="Plone"
xml:lang="en"
lang="en">
<div
metal:fill-slot="main"
tal:content="structure:view/data"
/>
</html>
any client view that uses chameleon
from five import grok
from zope.interface import Interface
from grokcore.chameleon.components import ChameleonPageTemplate
from common import insert_into_master
class MyView(grok.View):
grok.context(Interface)
grok.require('zope2.View')
grok.name('myview')
def render(self):
view = ChameleonPageTemplate('<div>Hello, world!</div>')
return insert_into_master(view.render(self), self)
Chameleon's represents macros internally in a different form than Zope's standard page template implementation, and the two are not compatible. So you can only use Chameleon macros from other Chameleon templates.
You can try installing five.pt, which monkeypatches Zope to use Chameleon for all page templates.
Related
Having read about HTML5 support in JSF 2.2, I was surprised to find the same XHTML doctype as in previous Facelets versions in the template file created with a new web application in Netbeans. The only difference is that the HTML tag reads in JSF 2.2:
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html">
, rather than as follows in older JSF versions:
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html">
It seems a bit wrong to keep using XHTML with the promise of HTML5 in mind. I only have the option to use 2.2 if I choose it from "registered libraries" instead of "server library". Does this affect the way the framework version is applied to the project?
Is Facelets too much dependent on XHTML to support HTML5?
It seems that you misunderstood the purpose of XHTML like as many people during the XHTML overhype a couple of years ago. Long story short: check our XHTML wiki page. Carefully read it. In a nutshell, Facelets absolutely doesn't care about the doctype being used in the generated HTML output. You can perfectly fine declare a HTML5 doctype in a Facelets template.
It's indeed unfortunate that Netbeans by default prepares the document with XHTML doctype while HTML5 is these days the recommended doctype. I don't do Netbeans, but in Eclipse you can easily edit those templates and even create your own. You can just replace the whole XHTML doctype by a HTML5 one. You can find/create those templates via Web » HTML Files » Editor » Templates in IDE prefs.
Please note that the HTML5 support in JSF 2.2 has got nothing to do with being able to support specifically the HTML5 doctype. On the contrary, this is supported on all JSF versions, even when legacy JSP is being used. JSP and Facelets are view technologies which allows you to generate HTML output, which can perfectly fine be HTML5 as good. This is also elaborated in the following closely related answer: Is it possible to use JSF+Facelets with HTML 4/5?
Instead, the HTML5 support in JSF 2.2 covers the possibility to define custom JSF component attributes and turning custom HTML elements into JSF components. This was not possible in JSF 2.1 and before. Any custom JSF component attributes (including the HTML5-recommended data-xxx attributes) were simply ignored by the default JSF renderers. See also the following related answer: Custom HTML tag attributes are not rendered by JSF. In JSF 2.2 you can easily specify custom attributes by the new http://xmlns.jcp.org/jsf/passthrough namespace as follows:
<html ... xmlns:a="http://xmlns.jcp.org/jsf/passthrough">
...
<h:inputText ... a:autocorrect="off" />
This will end up in the by <h:inputText> unsupported attribute autocorrect to actually be included in the generated HTML output. Note that I use a XML namespace prefix of a ("attribute") instead of p as shown in the Java EE tutorial, as it would otherwise clash with default XML namespace prefix p of PrimeFaces.
Turning custom HTML elements (including HTML5 elements) into JSF components is a matter of specifying a jsf attribute such as jsf:id.
<html ... xmlns:jsf="http://xmlns.jcp.org/jsf">
...
<header jsf:id="header">...</header>
<main jsf:id="main">...</main>
<footer jsf:id="footer">...</footer>
Those will under the covers be turned into UIPanel (like as <h:panelGroup>). And yes, they are referencable in e.g. <f:ajax render>.
In other words, "HTML5 support" is just again another buzzword for "Custom attribute support".
Running: Plone 5.0.0 with Diazo.
How does one permanently bypass the diazo theme applying in BrowserView templates? (Not with the diazo.off=1)
Example:
I have a diazo theme. I have a template that I'm returning via a BrowserView's ViewPageTemplateFile:
class ExhibitView(BrowserView):
template = ViewPageTemplateFile("exhibit.pt")
def __call__(self):
return self.template()
The exhibit.pt file is as follows:
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"
xmlns:tal="http://xml.zope.org/namespaces/tal"
xmlns:metal="http://xml.zope.org/namespaces/metal"
i18n:domain="plone"
lang="en">
<body>
Is it just this text?
</body>
</html>
I removed the plone master template, it is still applying the diazo rules. I just want it to return a barebone template, unthemed by diazo. We used to be able to do that before Diazo as I shown above.
Also making a Diazo rule to skip this is out of the question because it has to be installed in many places, I don't want to apply rules to everyone's site themes to make this work. That is hacky.
Thanks in advance!
According to this line:
https://github.com/plone/plone.app.theming/blob/5ba9447150776f7edbfd73b528b9b62f31dd14b5/src/plone/app/theming/policy.py#L79
If you have an header called 'X-Theme-Disabled' the transform is not applied. Two lines later you see the condition that is checking for "diazo.off".
So you should modify your __call__ method in a way that it sets the header before returning the template.
Something line this:
def __call__(self):
self.request.response.setHeader('X-Theme-Disabled', '1')
return self.template()
The control panel is doing the same:
https://github.com/plone/plone.app.theming/blob/fbbdc3bfdbccf2315cef069fe827fea863feb1c8/src/plone/app/theming/browser/controlpanel.py#L72
Caveat: I did not tested this :)
I am implementing a custom theming issue for a Rails 3.2 app, with a very small number of CSS overrides for each theme.
While I have so far implemented the theme variations by inlining some CSS (including occasional Erb parameters) within the layout file, I'd really like to tidy this up by delivering the customisation CSS via a GET request, e.g.: (assume current_theme is defined)
<%= stylesheet_link_tag theme_path(current_theme, format: :css) %>
In my themes_controller.rb:
class ThemesController < ApplicationController
respond_to :css
...
def show
#theme = Theme.find(params[:id])
respond_with #theme
end
end
I have the requisite show.css.erb file in views/themes.
My main issue is that /themes/1?format=css loads and renders the CSS file correctly. However, /themes/1.css – the form of URL generated by the theme_path helper – is producing a 404.
I'm probably overlooking something very simple here – hopefully a fellow SO user can point out the bloomin' obvious to prevent my head and brick walls becoming better acquainted...
UPDATE: Doing a bot of Rails route recognition debugging:
r = Rails.application.routes
#=> #<ActionDispatch::Routing::RouteSet:0x007fc385016170>
r.recognize_path '/themes/1.css'
#=> {:action=>"show", :controller=>"themes", :id=>"1", :format=>"css"}
r.recognize_path '/themes/1?format=css'
#=> {:action=>"show", :controller=>"themes", :id=>"1"}
So the fact that ?format=css seems to be working is actually because, at least when CURLing from the command line, /themes/1 is returning the requisite CSS. As far as I'm concerned, that's a red herring...
Incidentally, adding this line to routes.rb works:
get '/themestyle/:id' => 'themes#show', as: 'themestyle', format: 'css'
(using a slightly different route so as not to conflict with the resources :themes in routes.rb). themestyle_path(current_theme) generates a workable route of – /themestyle/1 – I can add the 'text/css' type header at render stage no problem. I'll have to hand-code a <link rel="stylesheet"> element though, as stylesheet_link_tag adds the css suffix.
I don't know if this is correct, but I see your error is that you're trying to use a controller action to do the job of a helper
Controller actions are only called on HTTP requests, and it's my experience that you cannot just call an action by linking to it from your view / layout -- you have to explicitly call the action, either through the backend, or through ajax or something
Change Your Action To A Helper
<%= stylesheet_link_tag theme(current_theme) %>
#app/controllers/application_controller.rb
def theme
return theme_path(params[:id])
end
helper_method :theme
I don't know if this will generate the route correctly, but it's certainly the method I would use
I found the source of the problem: the rack-zippy gem, middleware designed to help deliver GZIPped production assets on heroku.
Disabling that middleware enables the routes to all work perfectly fine and be passed to the correct controller method with all formats, etc. retained.
Thanks to all who helped.
I am working on a Plone add-on that requires a re-skinned alternate edit form for Dexterity content. I need to be able to display only part of the edit form in an AJAX overlay (using JQuery UI, not JQuery tools, so it seems more reasonable to do this server-side than to filter in JavaScript)**.
Documentation from Dexterity Developer's Guide seems to indicate I can have a custom template using macros. Something is missing from this section though -- maybe some critical context for folks not using grok to bind views, but perhaps something else. Creating a template-only view fails (cannot find names from view class, obviously), and attempting to bind a custom template in ZCML to either the stock view class or to a subclass of it both fail (the template is ignored in favor of the stock template).
My goals:
Have an edit for that is wrapped in a bare template that essentially just includes the content inside the #content div.
I do not want merely an unwrapped z3c.form rendering, I need a minimal template to wrap it too -- just not the stock Plone viewlet managers and furntiture.
What does not work:
from plone.dexterity.browser.edit import DefaultEditForm
from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile
class MyEditForm(DefaultEditForm):
index = ViewPageTemplateFile('my_edit_template.pt')
The ZCML equivalent (defining the index with runtime magic) also does not work here.
How can I inject a custom template into an edit form?
** I am working on Solgema.fullcalendar compatibility with plone.app.event's Dexterity-based type. Solgema.fullcalendar uses jQuery UI for popups, not plone.app.jquerytools overlay helpers; for consistency, it makes sense to have this minimal view and not attempt to mimic the filter mechanism in JavaScript of normal Plone overlays.
z3c.form looks for the template as the template attribute, so you need to assign your custom template to the template attribute of your edit form subclass, rather than index (which is where the template ZCML attribute puts it).
from plone.dexterity.browser.edit import DefaultEditForm
from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile
class MyEditForm(DefaultEditForm):
template = ViewPageTemplateFile('my_edit_template.pt')
While working on a dexterity based project I needed one of my content types to support collective.quickupload by marking it with the IQuickUploadCapable interface.
What I'm currently doing is adding an 'implements' to my configure.zcml file:
`<class class="plone.dexterity.content.Container">
<implements interface="collective.quickupload.browser.interfaces.IQuickUploadCapable" />
</class>`
Since my content type is a Container this works however my first inclination was to use a grok style approach instead of declaring it in ZCML. What's the grok/dexterity way to tell my dexterity content type that it implements an additional interface, or should I stick to the current approach?
Also I tried adding the interface as a behaviour in my profiles/default/types/my.dexterity.content.xml file but this didn't work (I didn't really expect it to as behaviours serve a different purpose).
Sean's answer is good. The other way is to create a behaviour and apply that. You need to register the behaviour with:
<plone:behavior
title="Quickupload"
provides="collective.quickupload.browser.interfaces.IQuickUploadCapable"
/>
You can then add 'collective.quickupload.browser.interfaces.IQuickUploadCapable' to your list of behaviours in the FTI.
Your approach using is not good because it means all Container-based Dexterity types get the marker interface, not just your type.
Why not just subclass IQuickUploadCapable as a mixin after form.Schema in your type interface?
You can not use it as a behaviour because it doesn't claim to be used in that way.
As I read from pypi, is intended to be used in a portlet or in a viewlet.
To add it in a grok style you should:
from collective.quickupload.browser.interfaces import IQuickUploadCapable
from plone.directives import form
class IMyContent(form.schema):
grok.implements(IQuickUploadCapable)
And that's it!
Be sure that your content type allows files to be added inside it, so is both folderish and it allows files to be added (or it just doesn't restrict to any specific content type).