appy.gen: added params String.allowImageUpload and String.styles for tuning the in-line editor corresponding to a String instance with format=XHTML; managed borders images uploaded in such a field; bugfix for https://bugs.launchpad.net/appy/+bug/913171 (appy.shared.dav).

This commit is contained in:
Gaetan Delannay 2012-01-09 17:00:47 +01:00
parent 2bd3fe1eeb
commit 30a51b7c1d
8 changed files with 47 additions and 32 deletions

View file

@ -1113,8 +1113,16 @@ class String(Type):
specificWritePermission=False, width=None, height=None, specificWritePermission=False, width=None, height=None,
maxChars=None, colspan=1, master=None, masterValue=None, maxChars=None, colspan=1, master=None, masterValue=None,
focus=False, historized=False, mapping=None, label=None, focus=False, historized=False, mapping=None, label=None,
transform='none'): transform='none', styles=('p','h1','h2','h3','h4'),
allowImageUpload=True):
# According to format, the widget will be different: input field,
# textarea, inline editor...
self.format = format self.format = format
# When format is XHTML, the list of styles that the user will be able to
# select in the styles dropdown is defined hereafter.
self.styles = styles
# When format is XHTML, do we allow the user to upload images in it ?
self.allowImageUpload = allowImageUpload
# The following field has a direct impact on the text entered by the # The following field has a direct impact on the text entered by the
# user. It applies a transformation on it, exactly as does the CSS # user. It applies a transformation on it, exactly as does the CSS
# "text-transform" property. Allowed values are those allowed for the # "text-transform" property. Allowed values are those allowed for the

View file

@ -1450,8 +1450,18 @@ class BaseMixin:
def getEditorInit(self, name): def getEditorInit(self, name):
'''Gets the Javascript init code for displaying a rich editor for '''Gets the Javascript init code for displaying a rich editor for
field named p_name.''' field named p_name.'''
return "CKEDITOR.replace('%s', {toolbar: 'Appy', filebrowserUploadUrl:"\ # Define the attributes that will initialize the ckeditor instance for
"'%s/upload'})" % (name, self.absolute_url()) # this field.
field = self.getAppyType(name)
ckAttrs = {'toolbar': 'Appy',
'format_tags': '%s' % ';'.join(field.styles)}
if field.allowImageUpload:
ckAttrs['filebrowserUploadUrl'] = '%s/upload' % self.absolute_url()
ck = ''
for k, v in ckAttrs.iteritems():
ck += "%s: '%s'," % (k, v)
res = "CKEDITOR.replace('%s', {%s})" % (name, ck)
return res
def getCalendarInit(self, name, years): def getCalendarInit(self, name, years):
'''Gets the Javascript init code for displaying a calendar popup for '''Gets the Javascript init code for displaying a calendar popup for

View file

@ -1,4 +1,4 @@
body { font: 70% Lucida,Helvetica,Arial,sans-serif; background-color: #EAEAEA; } body { font: 75% Lucida,Helvetica,Arial,sans-serif; background-color: #EAEAEA; }
pre { font: 100% Lucida,Helvetica,Arial,sans-serif; margin: 0} pre { font: 100% Lucida,Helvetica,Arial,sans-serif; margin: 0}
h1 { font-size: 11pt; margin:0;} h1 { font-size: 11pt; margin:0;}
h2 { font-size: 10pt; margin:0; font-style: italic; font-weight: normal;} h2 { font-size: 10pt; margin:0; font-style: italic; font-weight: normal;}
@ -32,7 +32,8 @@ ul { line-height: 1.2em; margin: 0 0 0.2em 0.6em; padding: 0;
list-style: none outside none;} list-style: none outside none;}
li { margin: 0; background-image: url("ui/li.gif"); padding-left: 10px; li { margin: 0; background-image: url("ui/li.gif"); padding-left: 10px;
background-repeat: no-repeat; background-position: 0 4px;} background-repeat: no-repeat; background-position: 0 4px;}
img {border: 0;} img {border: 0}
.xhtml img { margin-right: 5px }
.main { width: 900px; background-color: white; box-shadow: 3px 3px 3px #A9A9A9; .main { width: 900px; background-color: white; box-shadow: 3px 3px 3px #A9A9A9;
border-style: solid; border-width: 1px; border-color: grey; } border-style: solid; border-width: 1px; border-color: grey; }

View file

@ -23,4 +23,9 @@ CKEDITOR.editorConfig = function( config )
'SpecialChar', 'PageBreak', 'Link', 'Unlink', 'SpecialChar', 'PageBreak', 'Link', 'Unlink',
'-', 'Maximize']}, '-', 'Maximize']},
]; ];
config.format_p = { element:'p', attributes:{'style':'margin:0;padding:0'}};
config.format_h1 = { element:'h1', attributes:{'style':'margin:0;padding:0'}};
config.format_h2 = { element:'h2', attributes:{'style':'margin:0;padding:0'}};
config.format_h3 = { element:'h3', attributes:{'style':'margin:0;padding:0'}};
config.format_h4 = { element:'h4', attributes:{'style':'margin:0;padding:0'}};
}; };

View file

@ -3,23 +3,12 @@ Copyright (c) 2003-2011, CKSource - Frederico Knabben. All rights reserved.
For licensing, see LICENSE.html or http://ckeditor.com/license For licensing, see LICENSE.html or http://ckeditor.com/license
*/ */
body body { font: 75% Lucida,Helvetica,Arial,sans-serif; background-color: white; }
{
/* Font */
font-family: Arial, Verdana, sans-serif;
font-size: 12px;
/* Text color */ ol,ul,dl {
color: #222; /* IE7: reset rtl list margin. (#7334) */
*margin-right:0px;
/* Remove the background color to make it transparent */ /* preserved spaces for list items with text direction other than the list. (#6249,#8049)*/
background-color: #fff; padding:0 40px;
}
ol,ul,dl
{
/* IE7: reset rtl list margin. (#7334) */
*margin-right:0px;
/* preserved spaces for list items with text direction other than the list. (#6249,#8049)*/
padding:0 40px;
} }
img { margin-right: 5px}

View file

@ -10,11 +10,13 @@
<span tal:condition="python: fmt == 3">********</span> <span tal:condition="python: fmt == 3">********</span>
</tal:singleValue> </tal:singleValue>
</span> </span>
<tal:formattedString condition="python: fmt not in (0, 3)"> <tal:comment replace="nothing">Text</tal:comment>
<span tal:condition="python: value and (fmt == 1)" <span tal:condition="python: value and (fmt == 1)"
tal:replace="structure python: contextObj.formatText(value, format='html')"/> tal:replace="structure python: contextObj.formatText(value, format='html')"/>
<span tal:condition="python: value and (fmt == 2)" tal:replace="structure value"/> <tal:comment replace="nothing">XHTML text</tal:comment>
</tal:formattedString> <div tal:condition="python: value and (fmt == 2)" class="xhtml">
<span tal:replace="structure value"/>
</div>
<input type="hidden" tal:condition="masterCss" <input type="hidden" tal:condition="masterCss"
tal:attributes="class masterCss; value rawValue; name name; id name"/> tal:attributes="class masterCss; value rawValue; name name; id name"/>
</metal:view> </metal:view>

View file

@ -114,8 +114,8 @@
</@text@:list-level-style-number> </@text@:list-level-style-number>
</@text@:list-style> </@text@:list-style>
<@style@:style @style@:name="podImageLeft" @style@:family="graphic" @style@:parent-style-name="Graphics"> <@style@:style @style@:name="podImageLeft" @style@:family="graphic" @style@:parent-style-name="Graphics">
<@style@:graphic-properties @style@:run-through="foreground" @style@:wrap="parallel" @style@:number-wrapped-paragraphs="no-limit" @style@:wrap-contour="false" @style@:vertical-pos="top" @style@:vertical-rel="paragraph" @style@:horizontal-pos="left" @style@:horizontal-rel="paragraph" @style@:mirror="none" @fo@:clip="rect(0cm, 0.3cm, 0cm, 0cm)"/> <@style@:graphic-properties @style@:run-through="foreground" @style@:wrap="parallel" @style@:number-wrapped-paragraphs="no-limit" @style@:wrap-contour="false" @style@:vertical-pos="top" @style@:vertical-rel="paragraph" @style@:horizontal-pos="left" @style@:horizontal-rel="paragraph" @style@:mirror="none" @fo@:clip="rect(0cm, 0cm, 0cm, 0cm)" @fo@:margin-right="0.3cm" @fo@:margin-bottom="0.2cm"/>
</@style@:style> </@style@:style>
<@style@:style @style@:name="podImageRight" @style@:family="graphic" @style@:parent-style-name="Graphics"> <@style@:style @style@:name="podImageRight" @style@:family="graphic" @style@:parent-style-name="Graphics">
<@style@:graphic-properties @style@:run-through="foreground" @style@:wrap="parallel" @style@:number-wrapped-paragraphs="no-limit" @style@:wrap-contour="false" @style@:vertical-pos="top" @style@:vertical-rel="paragraph" @style@:horizontal-pos="right" @style@:horizontal-rel="paragraph" @style@:mirror="none" @fo@:clip="rect(0cm, 0.3cm, 0cm, 0cm)"/> <@style@:graphic-properties @style@:run-through="foreground" @style@:wrap="parallel" @style@:number-wrapped-paragraphs="no-limit" @style@:wrap-contour="false" @style@:vertical-pos="top" @style@:vertical-rel="paragraph" @style@:horizontal-pos="right" @style@:horizontal-rel="paragraph" @style@:mirror="none" @fo@:clip="rect(0cm, 0cm, 0cm, 0cm)" @fo@:margin-left="0.3cm" @fo@:margin-bottom="0.2cm"/>
</@style@:style> </@style@:style>

View file

@ -114,7 +114,7 @@ class HttpResponse:
raise ResourceError('Invalid XML response (%s)'%str(se)) raise ResourceError('Invalid XML response (%s)'%str(se))
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
urlRex = re.compile(r'http://([^:/]+)(:[0-9]+)?(/.+)?', re.I) urlRex = re.compile(r'http[s]?://([^:/]+)(:[0-9]+)?(/.+)?', re.I)
binaryRex = re.compile(r'[\000-\006\177-\277]') binaryRex = re.compile(r'[\000-\006\177-\277]')
class Resource: class Resource:
@ -139,7 +139,7 @@ class Resource:
self.host = host self.host = host
self.port = port and int(port[1:]) or 80 self.port = port and int(port[1:]) or 80
self.uri = uri or '/' self.uri = uri or '/'
else: raise 'Wrong URL: %s' % str(url) else: raise Exception('Wrong URL: %s' % str(url))
# If some headers must be sent with any request sent through this # If some headers must be sent with any request sent through this
# resource (like a cookie), you can store them in the following dict. # resource (like a cookie), you can store them in the following dict.
self.headers = {'Host': self.host} self.headers = {'Host': self.host}