[gen] More work on string multilingual fields.

This commit is contained in:
Gaetan Delannay 2014-08-15 10:46:28 +02:00
parent 7c2d4c1b7a
commit fb65cf82d8
3 changed files with 56 additions and 20 deletions

View file

@ -76,6 +76,26 @@ class Field:
tagName=field.master and 'slave' or ''; tagName=field.master and 'slave' or '';
layoutTarget=field">:tool.pxLayoutedObject</x>''') layoutTarget=field">:tool.pxLayoutedObject</x>''')
def doRender(self, layoutType, request, context=None, name=None):
'''Allows to call pxRender from code, to display the content of this
field in some specific context, for example in a Computed field.'''
if context == None: context = {}
context['layoutType'] = layoutType
context['field'] = self
context['name'] = name or self.name
# We may be executing a PX on a given object or on a given object tied
# through a Ref.
ctx = request.pxContext
if 'obj' not in context:
context['obj'] = ('tied' in ctx) and ctx['tied'] or ctx['obj']
context['zobj'] = context['obj'].o
# Copy some keys from the context of the currently executed PX.
for k in ('tool', 'ztool', 'req', '_', 'q', 'url', 'dright', 'dleft', \
'inPopup'):
if k in context: continue
context[k] = ctx[k]
return self.pxRender(context).encode('utf-8')
# Displays a field label. # Displays a field label.
pxLabel = Px('''<label if="field.hasLabel and field.renderLabel" pxLabel = Px('''<label if="field.hasLabel and field.renderLabel"
lfor=":field.name">::_('label', field=field)</label>''') lfor=":field.name">::_('label', field=field)</label>''')

View file

@ -113,9 +113,11 @@ class String(Field):
# pxView part for format String.XHTML. # pxView part for format String.XHTML.
pxViewRich = Px(''' pxViewRich = Px('''
<div if="not mayAjaxEdit" class="xhtml">::value or '-'</div> <div if="not mayAjaxEdit" class="xhtml">::value or '-'</div>
<div if="mayAjaxEdit" class="xhtml" contenteditable="true" <x if="mayAjaxEdit" var2="name=lg and ('%s_%s' % (name, lg)) or name">
<div class="xhtml" contenteditable="true"
id=":'%s_%s_ck' % (zobj.id, name)">::value or '-'</div> id=":'%s_%s_ck' % (zobj.id, name)">::value or '-'</div>
<script if="mayAjaxEdit">::field.getJsInlineInit(zobj,None)</script>''') <script if="mayAjaxEdit">::field.getJsInlineInit(zobj, name, lg)</script>
</x>''')
# PX displaying the language code and name besides the part of the # PX displaying the language code and name besides the part of the
# multilingual field storing content in this language. # multilingual field storing content in this language.
@ -618,7 +620,6 @@ class String(Field):
def getIndexValue(self, obj, forSearch=False): def getIndexValue(self, obj, forSearch=False):
'''Pure text must be extracted from rich content; multilingual content '''Pure text must be extracted from rich content; multilingual content
must be concatenated.''' must be concatenated.'''
print 'INDEX value computing...', self.name, obj.title
isXhtml = self.format == String.XHTML isXhtml = self.format == String.XHTML
if self.isMultilingual(): if self.isMultilingual():
res = self.getValue(obj) res = self.getValue(obj)
@ -639,7 +640,6 @@ class String(Field):
# Ugly catalog: if value is an empty string or None, it keeps the # Ugly catalog: if value is an empty string or None, it keeps the
# previous index value. # previous index value.
if res in self.emptyValuesCatalogIgnored: res = ' ' if res in self.emptyValuesCatalogIgnored: res = ' '
print 'INDEX value for', self.name, 'is', res
return res return res
def getPossibleValues(self, obj, withTranslations=False, def getPossibleValues(self, obj, withTranslations=False,
@ -815,8 +815,18 @@ class String(Field):
'''Stores the new field value from an Ajax request, or do nothing if '''Stores the new field value from an Ajax request, or do nothing if
the action was canceled.''' the action was canceled.'''
rq = obj.REQUEST rq = obj.REQUEST
if rq.get('cancel') != 'True': if rq.get('cancel') == 'True': return
self.store(obj, self.getStorableValue(rq['fieldContent'])) requestValue = rq['fieldContent']
if self.isMultilingual():
# We get a partial value, for one language only.
language = rq['languageOnly']
v = self.getUnilingualStorableValue(requestValue)
getattr(obj.aq_base, self.name)[language] = v
part = ' (%s)' % language
else:
self.store(obj, self.getStorableValue(requestValue))
part = ''
obj.log('Ajax-edited %s%s on %s.' % (self.name, part, obj.id))
def getIndexType(self): def getIndexType(self):
'''Index type varies depending on String parameters.''' '''Index type varies depending on String parameters.'''
@ -893,18 +903,20 @@ class String(Field):
return 'CKEDITOR.replace("%s", {%s})' % \ return 'CKEDITOR.replace("%s", {%s})' % \
(name, self.getCkParams(obj, language)) (name, self.getCkParams(obj, language))
def getJsInlineInit(self, obj, language): def getJsInlineInit(self, obj, name, language):
'''Gets the Javascript init code for enabling inline edition of this '''Gets the Javascript init code for enabling inline edition of this
field (rich text only). If the field is multilingual, the current field (rich text only). If the field is multilingual, the current
p_language is given. Else, p_language is None.''' p_language is given and p_name includes it. Else, p_language is
None.'''
uid = obj.id uid = obj.id
name = not language and self.name or ('%s_%s' % (self.name, language)) fieldName = language and name.rsplit('_',1)[0] or name
lg = language or ''
return "CKEDITOR.disableAutoInline = true;\n" \ return "CKEDITOR.disableAutoInline = true;\n" \
"CKEDITOR.inline('%s_%s_ck', {%s, on: {blur: " \ "CKEDITOR.inline('%s_%s_ck', {%s, on: {blur: " \
"function( event ) { var content = event.editor.getData(); " \ "function( event ) { var content = event.editor.getData(); " \
"doInlineSave('%s', '%s', '%s', content)}}})" % \ "doInlineSave('%s','%s','%s',content,'%s')}}})" % \
(uid, name, self.getCkParams(obj, language), uid, name, (uid, name, self.getCkParams(obj, language), uid, fieldName,
obj.absolute_url()) obj.absolute_url(), lg)
def isSelected(self, obj, fieldName, vocabValue, dbValue): def isSelected(self, obj, fieldName, vocabValue, dbValue):
'''When displaying a selection box (only for fields with a validator '''When displaying a selection box (only for fields with a validator

View file

@ -110,6 +110,7 @@ function getAjaxHook(hookId) {
for the result of an ajax request. If p_hookId starts with ':', we search for the result of an ajax request. If p_hookId starts with ':', we search
the element in the top browser window, not in the current one that can be the element in the top browser window, not in the current one that can be
an iframe.*/ an iframe.*/
if (!hookId) return;
var container = window.document; var container = window.document;
var startIndex = 0; var startIndex = 0;
if (hookId[0] == ':') { if (hookId[0] == ':') {
@ -126,7 +127,7 @@ function getAjaxChunk(pos) {
if ( (typeof(xhrObjects[pos]) != 'undefined') && if ( (typeof(xhrObjects[pos]) != 'undefined') &&
(xhrObjects[pos].freed == 0)) { (xhrObjects[pos].freed == 0)) {
var hook = xhrObjects[pos].hook; var hook = xhrObjects[pos].hook;
if (xhrObjects[pos].xhr.readyState == 1) { if (hook && (xhrObjects[pos].xhr.readyState == 1)) {
// The request has been initialized: display the waiting radar // The request has been initialized: display the waiting radar
var hookElem = getAjaxHook(hook); var hookElem = getAjaxHook(hook);
if (hookElem) if (hookElem)
@ -135,7 +136,8 @@ function getAjaxChunk(pos) {
if (xhrObjects[pos].xhr.readyState == 4) { if (xhrObjects[pos].xhr.readyState == 4) {
// We have received the HTML chunk // We have received the HTML chunk
var hookElem = getAjaxHook(hook); var hookElem = getAjaxHook(hook);
if (hookElem && (xhrObjects[pos].xhr.status == 200)) { var responseOk = (xhrObjects[pos].xhr.status == 200);
if (hookElem && responseOk) {
injectChunk(hookElem, xhrObjects[pos].xhr.responseText); injectChunk(hookElem, xhrObjects[pos].xhr.responseText);
// Call a custom Javascript function if required // Call a custom Javascript function if required
if (xhrObjects[pos].onGet) { if (xhrObjects[pos].onGet) {
@ -146,8 +148,8 @@ function getAjaxChunk(pos) {
for (var i=0; i<innerScripts.length; i++) { for (var i=0; i<innerScripts.length; i++) {
eval(innerScripts[i].innerHTML); eval(innerScripts[i].innerHTML);
} }
xhrObjects[pos].freed = 1;
} }
if (responseOk) xhrObjects[pos].freed = 1;
} }
} }
} }
@ -210,8 +212,8 @@ function askAjaxChunk(hook,mode,url,px,params,beforeSend,onGet) {
// Set the correct HTTP headers // Set the correct HTTP headers
rq.xhr.setRequestHeader( rq.xhr.setRequestHeader(
"Content-Type", "application/x-www-form-urlencoded"); "Content-Type", "application/x-www-form-urlencoded");
rq.xhr.setRequestHeader("Content-length", paramsFull.length); // rq.xhr.setRequestHeader("Content-length", paramsFull.length);
rq.xhr.setRequestHeader("Connection", "close"); // rq.xhr.setRequestHeader("Connection", "close");
rq.xhr.onreadystatechange = function(){ getAjaxChunk(pos); } rq.xhr.onreadystatechange = function(){ getAjaxChunk(pos); }
rq.xhr.send(paramsFull); rq.xhr.send(paramsFull);
} }
@ -294,12 +296,14 @@ function askField(hookId, objectUrl, layoutType, customParams, showChanges,
askAjaxChunk(hookId, 'GET', objectUrl, px, params, null, evalInnerScripts); askAjaxChunk(hookId, 'GET', objectUrl, px, params, null, evalInnerScripts);
} }
function doInlineSave(objectUid, name, objectUrl, content){ function doInlineSave(objectUid, name, objectUrl, content, language){
/* Ajax-saves p_content of field named p_name on object whose id is /* Ajax-saves p_content of field named p_name (or only on part corresponding
to p_language if the field is multilingual) on object whose id is
p_objectUid and whose URL is p_objectUrl. Asks a confirmation before p_objectUid and whose URL is p_objectUrl. Asks a confirmation before
doing it. */ doing it. */
var doIt = confirm(save_confirm); var doIt = confirm(save_confirm);
var params = {'action': 'storeFromAjax', 'layoutType': 'view'}; var params = {'action': 'storeFromAjax', 'layoutType': 'view'};
if (language) params['languageOnly'] = language;
var hook = null; var hook = null;
if (!doIt) { if (!doIt) {
params['cancel'] = 'True'; params['cancel'] = 'True';