Head <style> block with plone.app.z3cform - plone

I have a grok'ed plone.directives.form code below:
class EditForm(TreeFormMixin, form.SchemaForm):
"""
Edit form for our model.
We got one dummy button which allows us to manually inspect the data postback values.
"""
grok.context(ISiteRoot)
grok.name("dgftreeselect-test")
grok.require('zope2.View')
ignoreContext = True
schema = IFormSchema
label = u"Tree selection demo and manual testing"
#button.buttonAndHandler(u'Turbo boost')
def handleApply(self, action):
data, errors = self.extractData()
if errors:
self.status = self.formErrorsMessage
return
raise ActionExecutionError(Invalid(u"Please see that data stays intact over postback"))
it results to this form - which is not that good looking:
Since it is a demo form I'd like to keep all the related material in the same .py file. However, as the form is ugly looking, I'd like to inject a <style> CSS block on the page from a Python source code string to fix some of the most outstanding issues with the CSS styles.
What kind of hooks plone.app.forms / BrowserViews provide to inject your own <style> block in the <head> or in any part of the resulting HTML page? I prefer not to create any additional files and CSS registrations for this task.
Full source:
https://github.com/miohtama/collective.z3cform.dgftreeselect/blob/master/src/collective/z3cform/dgftreeselect/testform.py

plone.app.z3cform and Zope browser views don't provide any hooks to inject custom things into the head directly, but you can use a custom template by specifying the template attribute in the form class:
template = grok.Template('path/to/template.pt')
And then in template.pt, fill the style_slot to include your styles. The entire template could look like this:
<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"
xmlns:i18n="http://xml.zope.org/namespaces/i18n"
lang="en"
metal:use-macro="context/main_template/macros/master"
i18n:domain="plone">
<body>
<metal:block fill-slot="style_slot">
<style type="text/css">
/* insert styles here */
</style>
</metal:block>
<metal:content-core fill-slot="main">
<metal:content-core define-macro="content-core">
<tal:button metal:use-macro="context/##ploneform-macros/titlelessform" />
</metal:content-core>
</metal:content-core>
</body>
</html>
This is not a best practice since the styles must be served every time the widget is rendered. Instead it's usually better to register CSS in the portal_css tool.

Related

R/exams: How to change default "Exam 1" produced by exams2html

Is there a way to change the "Exam 1" to another word like "Homework 1" by passing arguments?
If not, is there a default template I can modify?
My last resort is to modify the built html files but it's not very convenient.
The exams2html() function takes an argument template which defaults to "plain.html". This template is shipped with the exams package and contains:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>Exam ##ID##</title>
<style type="text/css">
body{font-family: Arial, Helvetica, Sans;}
</style>
<meta charset="utf-8" />
</head>
<body>
<h2>Exam ##ID##</h2>
##\exinput{exercises}##
</body>
</html>
The ##ID## is replaced by the ID (from 1 to n) and the ##\exinput{exercises}## is replaced by an ordered list <ol> containing the questions and optionally also the solutions. You can modify this template in any way you need and call it, say, homework.html. Then you can call:
exams2html(..., template = "/path/to/homework.html",
question = "<h4>Exercise</h4>", solution = FALSE)
which sets the template and also modifies the way the question is displayed while suppressing the solution.
Remark: The placeholders ##ID## and ##\exinput{exercises}## are a bit awkward (analogous to the placeholders in LaTeX templates for exams2pdf()) and not very flexible. It has been on my wishlist to make this more flexible, e.g., using {{mustache}} templating via the whisker package, but so far I didn't get round to tackle that.

Is it legit to put the style declaration inside the body? [duplicate]

Is it correct to use the <style> tag outside of the <head> element ?
Like this:
<html>
<head>
<style> some style </style>
</head>
<body> some text </body>
<style> some more style </style>
<body> some more text </body>
</html>
I want to do this because: my cgi sources other files with their own style.
The cgi file contains:
#!/bin/bash
echo "content-type: text/html"
echo ""
echo "<html><head><style>"
echo "h1 {color: red;}"
echo "</style>"
echo "<body>"
echo "<h1> some text here </h1>"
echo "</body>"
source ./data.sh
echo "</html>"
And the source file contains:
echo "<style>"
echo "h2 {color: blue;}"
echo "</style>"
echo "<body>"
echo "<h2> and some other text here </h2>"
echo "</body>"
This seems to work fine. But is it correct ?
At w3schools it says:
Each HTML document can contain multiple <style> tags.
But is it done this way ?
style is supposed to be included only on the head of the document.
Besides the validation point, one caveat that might interest you when using style on the body is the flash of unstyled content. The browser would get elements that would be styled after they are displayed, making them shift on size/shape/font and/or flicker. It is generally a sign of bad craftsmanship. Generally you can get away with putting style anywhere you want, but try to avoid it whenever it is possible.
HTML 5 introduced a scoped attribute that allowed style tags to be included everywhere in the body, but then they removed it again.
According to the W3 specs, <link> tags are only supposed to go in the <head> section:
References
For HTML 4.01: http://www.w3.org/TR/html401/struct/links.html#edef-LINK
For HTML5: http://www.w3.org/TR/html5/document-metadata.html#the-link-element
Validation Issues
If you put a tag within the body of the HTML document, it will not validate using validate.w3.org
<style> tags can be anywhere in the HTML Document. However, it is best to have it inside the <head>.
From my personal experience, its best to just make a separate stylesheet to put all the CSS in.
According to https://developer.mozilla.org/en-US/docs/Web/HTML/Element/style :
"<style>-element can be included inside the <head> or <body> of the document, and the styles will still be applied, however it is recommended that you include your styles in the <head> for organizational purposes"
I think the key-phrase here is "for organizational purposes". So it's not a technical requirement but advise which purports to make your html-source more readable.
The above linked-to page is
"Last modified: Jun 4, 2019, by MDN contributors"
According to W3 standards, it is necessary to put style tag inside the head element of the document. If you put your style tag inside the body element then the style to your web page will be effected after whole DOM is loaded, due to which we can see blank page for some time before the CSS comes into effect and certainly that would cause impact on better UI experience. Mostly the recommended way to implement CSS in a document is to create a saperate stylesheet and providing link to the document wherever needed.
It really depends on the website and how it loads. CSS files which are loaded in the header block your website from rendering so you can inline CSS in the header or the body. This is because the CSS file must be fetched (through the network or locally) which can impact performance. In a perfect world you only have one css file but the world is not perfect.
A new feature available on most major browsers..
Stylesheets activated after the body is started do not block paint
[https://www.chromestatus.com/feature/5696805480169472][1]
<body class="gorgias-loaded">
<p>This page includes an image, followed by an external css file that is appended to the document by js (async) followed by another image.
The css file changes the page background color black when it has been applied.</p>
<p>Optimally what you will see would be:</p>
<ol>
<li>A blank white page with this text and the title for both images.</li>
<li>Immediately after, the second image.</li>
<li>One second later the first image.</li>
<li>Four seconds later the background color should change to black.</li>
</ol>
<h2>First Image (1 second delay)</h2>
<img width="300" height="365" src="slowimage.php">
<h2>External CSS injected by JS (5 second delay)</h2>
<script>
var attach = document.getElementsByTagName('script')[0];
var link = document.createElement('link');
link.rel = 'stylesheet';
link.type = 'text/css';
link.href = 'slowcss.php';
link.media = 'all';
attach.appendChild(link);
<link rel="stylesheet" type="text/css" href="slowcss.php" media="all"></script>
<h2>Second Image (no delay)</h2>
<img width="300" height="365" src="slowimage.php?delay=0">
</div></body>

All urls in css files are mistranslated for some reason

I got a very strange problem with my website. It happens randomly Let me take an example of the main CSS file from my website
http://www.xxxxx.net/oxwall/ow_static/plugins/base/css/ow.css
which defines background image for alot of widget, for example
ow_console_lang_ai{background:url(images/flags/AI.png)
this one is correctly located at
http://www.xxxxxx.net/oxwall/ow_static/plugins/base/css/images/flags/AI.png
At runtime, ow.css is included by every single pages. And most of the time, things go smoothly, but sometime, (just sometime!!) all urls messed up. All images (by all, it is around 200-400 images) is appended to the resquesting url.
For examples: this one /oxwall/photo/useralbum/EltonJohn/109 may trigger 200+ requests of of wrong urls from ow.css:
/oxwall/photo/useralbum/EltonJohn/images/flags/GT.png
The number of images is huge that occupies all available process of my preforked Apache..
I have been googling for days. I thought it was mod_deflate but no... Any idea?
Try to add a slash:
Old code:
ow_console_lang_ai{background:url(images/flags/AI.png)
New code:
ow_console_lang_ai{background:url(/images/flags/AI.png)
Some you're sayin' when you write this /oxwall/photo/useralbum/EltonJohn/109 it's searching /oxwall/photo/useralbum/EltonJohn/images/flags/GT.png ? I'm not sure to understand
EDIT :
So i was thinking, if you call your css as before , but before your file you can externalize your specific class and put your relative url in javascript
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<style>
.box {
height:100px;
width:100px;
}
</style>
<script>
var url = location.href;
</script>
</head>
<body>
<div class="test-image box"></div>
<script>
document.write('<style> \
.test-image { \
background-image:url('+url+'); \
} \
</style>');
</script>
</body>
</html>
This is not a best idea , but hope this help
Allan
Perhaps the problem is not the code but the picture.
Once I had a image that has a ".PNG"-ending and not ".png"-ending and my website doesn't load it.

Adding widget (dynamic) CSS in Genshi (TurboGears 2)

I'm trying to figure out how to add CSS in Genshi to some markup which is dynamically generated. I'm trying to avoid inline CSS, and ideally the rules would appear in the <head/> tag of the parent document.
I'm working with existing code that looks like this (I rewrote this from the original, to simplify, so I might have some syntax mistakes; but the original works, so I think you can ignore syntax mistakes if any):
templates/widgets/file_widget.html
<html xmlns:py="http://genshi.edgewall.org/"
xmlns:xi="http://www.w3.org/2001/XInclude"
py:strip="">
<head>
<style type="text/css">
.file-widget {
background-color:#eee; display:inline-block; padding:4px;
}
</style>
</head>
<py:def function="file_widget(file_name)">
<div class=".file-widget">
...
</div>
</py:def>
</html>
widgets.py
class FileWidget:
...
def html():
markup_template = genshi.template.MarkupTemplate('''
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:py="http://genshi.edgewall.org/" xmlns:xi="http://www.w3.org/2001/XInclude">
<xi:include href="my_project/widgets/file_widget.html" />
${description}
${file_widget(file_name)}
</html>''')
markup = markup_template.generate(file_name = self.file_name, description = genshi.core.Markup(self.description))
return markup.render('html', doctype = 'html')
templates/main_page.html
<div py:for='widget in app.widgets'>
${ genshi.core.Markup( widget.html() ) }
</div>
Unfortunately, the <style/> tag gets rendered twice: once, as I want it to be, inside the original document <head/>, and then the widget <head/> gets rendered again.
How can I change the code to properly include the CSS in the right place? Since this is collaborative code, little changes and clearer code are appreciated!
Thanks for reading and for your help.
You might want to use a widget library like ToscaWidget2 which is meant to actually manage widgets with resources.
Otherwise you might want to use a static files framework like fanstatic which provides support for resources inclusion: http://www.fanstatic.org/en/1.0a5/quickstart.html#including-resources-with-fanstatic
If you want to roll your own custom solution you should register the resources somewhere whenever the widget is rendered (like in request) and then add them to the head tag when template is rendered. This is actually what tw2.core.resources does: https://github.com/toscawidgets/tw2.core/blob/develop/tw2/core/resources.py

Apply styles to only to one element

I am including styles in normal way like this:
<link rel="stylesheet" href="/css/boostrap.css" type="text/css" />
this styles has a lot of styles which destroy my main view, it applies to body element, is it possible to applay the style only to one particular div?
Put that <div> into a separate page and include bootstrap CSS only in that page.
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="/css/boostrap.css" type="text/css" />
</head>
<body>
<div>This is your DIV</div>
</body>
</html>
Your main page won't be touched by that and you'll be able to display that div inside your main page simply using an iframe, change (for example) this:
<div>This is your DIV</div>
To this:
<iframe src="url of the other page"></iframe>
Of course you may need to change little bit the logic of your page to accommodate this (primary I guess because of server side C# code, for client side JavaScript code it should be easier because the come from the same domain).
Yes, you can do that by ID:
<div id="myDiv"></div>
and then the CSS would be:
#myDiv { ... }
and that will apply that style to anything named myDiv. You could also use classes:
<div class="someClass"></div>
and then the CSS would be:
.someClass { ... }
and that will apply that style to anything with that class attached.
Based on what you're describing, surrounding the generality of the CSS that's breaking the already defined CSS, you're going to want to get rid of those general element styles and use ID's because it sounds like you're trying to merge some CSS.
You try to remove all styles of body with javascript code, and after that, after you add a name/id to the body style in your correct css, set this as class attribute of your body. (js code too after the document is completely loaded)
Another (stupid) solution depends on what do you have in the css file. Do you can edit the /css/boostrap.css, simply replace all body word with ".body1" (fe => make a class from it)?

Resources