[px] Managed special HTML attributes like 'checked' and 'selected'.
This commit is contained in:
parent
5ece5c9831
commit
e4b84be05e
|
@ -24,7 +24,7 @@ class ToolWrapper(AbstractWrapper):
|
|||
pxHome = Px('''
|
||||
<table width="300px" height="240px" align="center">
|
||||
<tr valign="middle">
|
||||
<td align="center">:_('front_page_text')</td>
|
||||
<td align="center">::_('front_page_text')</td>
|
||||
</tr>
|
||||
</table>
|
||||
''', template=AbstractWrapper.pxTemplate, hook='content')
|
||||
|
|
|
@ -77,9 +77,9 @@ class AbstractWrapper(object):
|
|||
<br/>
|
||||
</div>
|
||||
<br/>
|
||||
<input type="button" onclick="doConfirm()" value="_('yes')"/>
|
||||
<input type="button" onclick="doConfirm()" value=":_('yes')"/>
|
||||
<input type="button" onclick="closePopup('confirmActionPopup')"
|
||||
value="_('no')"/>
|
||||
value=":_('no')"/>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
@ -101,44 +101,44 @@ class AbstractWrapper(object):
|
|||
</form>
|
||||
</div>
|
||||
|
||||
<!--
|
||||
<table class="main" align="center" cellpadding="0">
|
||||
<tal:comment replace="nothing">Top banner</tal:comment>
|
||||
<tr class="top" metal:define-slot="top">
|
||||
<td tal:define="bannerName python: (dir == 'ltr') and 'banner' or 'bannerrtl'"
|
||||
tal:attributes="style python: 'background-image: url(%s/ui/%s.jpg)' % (appUrl, bannerName)">
|
||||
<tal:comment replace="nothing">Top links</tal:comment>
|
||||
<div style="margin-top: 4px"
|
||||
tal:define="pages tool/getMainPages" tal:attributes="align dright">
|
||||
<tal:comment replace="nothing">Icon "home"</tal:comment>
|
||||
<a class="pageLink" tal:attributes="href appUrl; title python: _('app_home')">
|
||||
<img tal:attributes="src string: $appUrl/ui/home.gif" style="margin-right: 3px"/>
|
||||
</a>
|
||||
<tal:comment replace="nothing">Additional links (or icons) from icons.pt</tal:comment>
|
||||
<metal:call use-macro="app/ui/icons/macros/links"/>
|
||||
<tal:comment replace="nothing">Top-level pages</tal:comment>
|
||||
<a tal:repeat="page pages" class="pageLink"
|
||||
tal:content="page/title" tal:attributes="href page/absolute_url"></a>
|
||||
<tal:comment replace="nothing">Connect link if discreet login</tal:comment>
|
||||
<a id="loginLink" name="loginLink" onclick="showLoginForm()" class="pageLink" style="cursor:pointer"
|
||||
tal:condition="python: isAnon and discreetLogin" tal:content="python: _('app_connect')">
|
||||
</a>
|
||||
<tal:comment replace="nothing">Language selector</tal:comment>
|
||||
<tal:lg condition="tool/showLanguageSelector">
|
||||
<select class="pageLink"
|
||||
tal:define="languages tool/getLanguages;
|
||||
defaultLanguage python: languages[0]"
|
||||
tal:attributes="onchange string:window.location='$appUrl/config/changeLanguage?language=' + this.options[this.selectedIndex].value">
|
||||
<option tal:repeat="lg languages"
|
||||
tal:content="python: tool.getLanguageName(lg)"
|
||||
tal:attributes="selected python:lang == lg; value lg">
|
||||
</option>
|
||||
</select>
|
||||
</tal:lg>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tal:comment replace="nothing">The message strip</tal:comment>
|
||||
<tr class="top">
|
||||
<!-- Top banner -->
|
||||
<td var="bannerName=(dir == 'ltr') and 'banner' or 'bannerrtl'"
|
||||
style=":'background-image: url(%s/ui/%s.jpg)'% (appUrl,bannerName)">
|
||||
|
||||
<!-- Top links -->
|
||||
<div style="margin-top: 4px" align=":dright">
|
||||
<!-- Icon "home" -->
|
||||
<a class="pageLink" href=":appUrl" title=": _('app_home')">
|
||||
<img src=":'%s/ui/home.gif' % appUrl" style="margin-right: 3px"/>
|
||||
</a>
|
||||
<!-- Additional links (or icons) from icons.pt -->
|
||||
<!--metal:call use-macro="app/ui/icons/macros/links"/-->
|
||||
|
||||
<!-- Top-level pages -->
|
||||
<a for="page in tool.pages" class="pageLink"
|
||||
href=":page.url">:page.title</a>
|
||||
|
||||
<!-- Connect link if discreet login -->
|
||||
<a if="isAnon and discreetLogin" id="loginLink" name="loginLink"
|
||||
onclick="showLoginForm()" class="pageLink"
|
||||
style="cursor:pointer">:_('app_connect')</a>
|
||||
|
||||
<!-- Language selector -->
|
||||
<x if="ztool.showLanguageSelector()">
|
||||
<select class="pageLink"
|
||||
var="languages=ztool.getLanguages();
|
||||
defaultLanguage=languages[0]"
|
||||
onchange=":'window.location="%s/config/changeLanguage?language=" + this.options[this.selectedIndex].value' % appUrl">
|
||||
<option for="lg in languages" value=":lg"
|
||||
selected=":lang == lg">:ztool.getLanguageName(lg)</option>
|
||||
</select>
|
||||
</x>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<!--tal:comment replace="nothing">The message strip</tal:comment>
|
||||
<tr valign="top">
|
||||
<td>
|
||||
<div style="position: relative">
|
||||
|
@ -230,9 +230,8 @@ class AbstractWrapper(object):
|
|||
</tr>
|
||||
<tr><tal:comment replace="nothing">Footer</tal:comment>
|
||||
<td><metal:call use-macro="app/ui/footer/macros/footer"/></td>
|
||||
</tr>
|
||||
</tr-->
|
||||
</table>
|
||||
-->
|
||||
<x>:content</x>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -138,14 +138,20 @@ class Buffer:
|
|||
|
||||
def getLength(self): pass # To be overridden
|
||||
|
||||
def dumpStartElement(self, elem, attrs={}, ignoreAttrs=(),
|
||||
insertAttributesHook=False, noEndTag=False):
|
||||
def dumpStartElement(self, elem, attrs={}, ignoreAttrs=(), hook=False,
|
||||
noEndTag=False):
|
||||
'''Inserts into this buffer the start tag p_elem, with its p_attrs,
|
||||
excepted those listed in p_ignoreAttrs. If p_insertAttributesHook
|
||||
is True (works only for MemoryBuffers), we will insert an Attributes
|
||||
instance at the end of the list of dumped attributes, in order to be
|
||||
able, when evaluating the buffer, to dump additional attributes, not
|
||||
known at this dump time.'''
|
||||
excepted those listed in p_ignoreAttrs. If p_hook is not None
|
||||
(works only for MemoryBuffers), we will insert, at the end of the
|
||||
list of dumped attributes:
|
||||
* [pod] an Attributes instance, in order to be able, when evaluating
|
||||
the buffer, to dump additional attributes, not known at this
|
||||
dump time;
|
||||
* [px] an Attribute instance, representing a special HTML attribute
|
||||
like "checked" or "selected", that, if the tied expression
|
||||
returns False, must not be dumped at all. In this case,
|
||||
p_hook must be a tuple (s_attrName, s_expr).
|
||||
'''
|
||||
self.write('<%s' % elem)
|
||||
for name, value in attrs.items():
|
||||
if ignoreAttrs and (name in ignoreAttrs): continue
|
||||
|
@ -157,16 +163,14 @@ class Buffer:
|
|||
self.write(' %s="' % name)
|
||||
self.addExpression(value[1:])
|
||||
self.write('"')
|
||||
if insertAttributesHook:
|
||||
res = self.addAttributes()
|
||||
else:
|
||||
res = None
|
||||
res = None
|
||||
if hook:
|
||||
if self.pod:
|
||||
res = self.addAttributes()
|
||||
else:
|
||||
self.addAttribute(*hook)
|
||||
# Close the tag
|
||||
if noEndTag:
|
||||
suffix = '/>'
|
||||
else:
|
||||
suffix = '>'
|
||||
self.write(suffix)
|
||||
self.write(noEndTag and '/>' or '>')
|
||||
return res
|
||||
|
||||
def dumpEndElement(self, elem):
|
||||
|
@ -212,6 +216,7 @@ class FileBuffer(Buffer):
|
|||
# At 2013-02-06, this method was not called within the whole test suite.
|
||||
try:
|
||||
expr = Expression(expression, self.pod)
|
||||
if tiedHook: tiedHook.tiedExpression = expr
|
||||
res, escape = expr.evaluate(self.env.context)
|
||||
if escape: self.dumpContent(res)
|
||||
else: self.write(res)
|
||||
|
@ -366,12 +371,19 @@ class MemoryBuffer(Buffer):
|
|||
self.content += u' '
|
||||
|
||||
def addAttributes(self):
|
||||
# Create the Attributes instance
|
||||
'''pod-only: adds an Attributes instance into this buffer.'''
|
||||
attrs = Attributes(self.env)
|
||||
self.elements[self.getLength()] = attrs
|
||||
self.content += u' '
|
||||
return attrs
|
||||
|
||||
def addAttribute(self, name, expr):
|
||||
'''px-only: adds an Attribute instance into this buffer.'''
|
||||
attr = Attribute(name, expr)
|
||||
self.elements[self.getLength()] = attr
|
||||
self.content += u' '
|
||||
return attr
|
||||
|
||||
def _getVariables(self, expr):
|
||||
'''Returns variable definitions in p_expr as a list
|
||||
~[(s_varName, s_expr)]~.'''
|
||||
|
@ -656,7 +668,8 @@ class MemoryBuffer(Buffer):
|
|||
evalEntry.expr, e), dumpTb=False)
|
||||
else: # px
|
||||
raise Exception(EVAL_EXPR_ERROR %(evalEntry.expr,e))
|
||||
elif isinstance(evalEntry, Attributes):
|
||||
elif isinstance(evalEntry, Attributes) or \
|
||||
isinstance(evalEntry, Attribute):
|
||||
result.write(evalEntry.evaluate(context))
|
||||
else: # It is a subBuffer
|
||||
if evalEntry.action:
|
||||
|
|
|
@ -185,4 +185,20 @@ class Attributes(PodElement):
|
|||
for name, value in self.attrs.iteritems():
|
||||
res += ' %s=%s' % (name, quoteattr(value))
|
||||
return res
|
||||
|
||||
class Attribute(PodElement):
|
||||
'''Represents an HTML special attribute like "selected" or "checked".
|
||||
px-only.'''
|
||||
OD = None
|
||||
|
||||
def __init__(self, name, expr):
|
||||
# The name of the attribute
|
||||
self.name = name
|
||||
# The expression that will compute the attribute value
|
||||
self.expr = expr.strip()
|
||||
|
||||
def evaluate(self, context):
|
||||
# If the expr evaluates to False, we do not dump the attribute at all.
|
||||
if eval(self.expr, context): return ' %s="%s"' % (self.name, self.name)
|
||||
return ''
|
||||
# ------------------------------------------------------------------------------
|
||||
|
|
|
@ -259,7 +259,7 @@ class PodParser(OdfParser):
|
|||
hook = e.currentBuffer.dumpStartElement(elem, attrs,
|
||||
ignoreAttrs=(e.tags['formula'], e.tags['string-value'],
|
||||
e.tags['value-type']),
|
||||
insertAttributesHook=True)
|
||||
hook=True)
|
||||
# We already have the POD expression: remember it on the env.
|
||||
e.currentOdsExpression = attrs[e.tags['string-value']]
|
||||
e.currentOdsHook = hook
|
||||
|
|
|
@ -47,6 +47,7 @@ class PxParser(XmlParser):
|
|||
pxAttributes = ('var', 'for', 'if')
|
||||
# No-end tags
|
||||
noEndTags = ('br', 'img', 'link', 'input')
|
||||
noDumpTags = ('selected', 'checked')
|
||||
|
||||
def __init__(self, env, caller=None):
|
||||
XmlParser.__init__(self, env, caller)
|
||||
|
@ -73,8 +74,19 @@ class PxParser(XmlParser):
|
|||
# the main element or to a sub-element.
|
||||
e.currentBuffer.addElement(elem, elemType='px')
|
||||
if elem != 'x':
|
||||
# Dump the start elements and its attributes. But as a preamble,
|
||||
# manage special attributes that could not be dumped at all, like
|
||||
# "selected" or "checked".
|
||||
hook = None
|
||||
ignorableAttrs = self.pxAttributes
|
||||
for name in self.noDumpTags:
|
||||
if attrs.has_key(name) and attrs[name].startswith(':'):
|
||||
hook = (name, attrs[name][1:])
|
||||
ignorableAttrs += (name,)
|
||||
break
|
||||
e.currentBuffer.dumpStartElement(elem, attrs,
|
||||
ignoreAttrs=self.pxAttributes, noEndTag=elem in self.noEndTags)
|
||||
ignoreAttrs=ignorableAttrs, noEndTag=elem in self.noEndTags,
|
||||
hook=hook)
|
||||
|
||||
def endElement(self, elem):
|
||||
e = self.env
|
||||
|
|
|
@ -37,7 +37,7 @@ CUSTOM_CONVERSION_ERROR = 'Custom converter for "%s" values produced an ' \
|
|||
'error while converting value "%s". %s'
|
||||
XML_SPECIAL_CHARS = {'<': '<', '>': '>', '&': '&', '"': '"',
|
||||
"'": '''}
|
||||
XML_ENTITIES = {'lt': '<', 'gt': '>', 'amp': '&', 'quot': "'", 'apos': "'"}
|
||||
XML_ENTITIES = {'lt': '<', 'gt': '>', 'amp': '&', 'quot': '"', 'apos': "'"}
|
||||
HTML_ENTITIES = {
|
||||
'iexcl': '¡', 'cent': '¢', 'pound': '£', 'curren': '€', 'yen': '¥',
|
||||
'brvbar': 'Š', 'sect': '§', 'uml': '¨', 'copy':'©', 'ordf':'ª',
|
||||
|
|
Loading…
Reference in a new issue