--- a/common/migration.py Mon Jun 22 11:15:17 2009 +0200
+++ b/common/migration.py Tue Jun 23 08:44:42 2009 +0200
@@ -17,6 +17,8 @@
from logilab.common.decorators import cached
from logilab.common.configuration import REQUIRED, read_old_config
+from cubicweb import ConfigurationError
+
def migration_files(config, toupgrade):
"""return an orderer list of path of scripts to execute to upgrade
@@ -328,18 +330,18 @@
self.config.add_cubes(newcubes)
return newcubes
- def cmd_remove_cube(self, cube):
+ def cmd_remove_cube(self, cube, removedeps=False):
+ if removedeps:
+ toremove = self.config.expand_cubes([cube])
+ else:
+ toremove = (cube,)
origcubes = self.config._cubes
- basecubes = list(origcubes)
- for pkg in self.config.expand_cubes([cube]):
- try:
- basecubes.remove(pkg)
- except ValueError:
- continue
+ basecubes = [c for c in origcubes if not c in toremove]
self.config._cubes = tuple(self.config.expand_cubes(basecubes))
removed = [p for p in origcubes if not p in self.config._cubes]
- assert cube in removed, \
- "can't remove cube %s, used as a dependancy" % cube
+ if not cube in removed:
+ raise ConfigurationError("can't remove cube %s, "
+ "used as a dependency" % cube)
return removed
def rewrite_configuration(self):
--- a/common/mixins.py Mon Jun 22 11:15:17 2009 +0200
+++ b/common/mixins.py Tue Jun 23 08:44:42 2009 +0200
@@ -191,11 +191,18 @@
return rset.get_entity(0, 0)
return None
- def change_state(self, stateeid, trcomment=None, trcommentformat=None):
+ def change_state(self, state, trcomment=None, trcommentformat=None):
"""change the entity's state according to a state defined in given
parameters
"""
- assert not isinstance(stateeid, basestring), 'change_state wants a state eid'
+ if isinstance(state, basestring):
+ state = self.wf_state(state)
+ assert state is not None, 'not a %s state: %s' % (self.id, state)
+ if hasattr(state, 'eid'):
+ stateeid = state.eid
+ else:
+ stateeid = state
+ stateeid = typed_eid(stateeid)
if trcomment:
self.req.set_shared_data('trcomment', trcomment)
if trcommentformat:
--- a/devtools/fill.py Mon Jun 22 11:15:17 2009 +0200
+++ b/devtools/fill.py Tue Jun 23 08:44:42 2009 +0200
@@ -10,7 +10,7 @@
from random import randint, choice
from copy import deepcopy
-from datetime import datetime, date, timedelta
+from datetime import datetime, date, time#timedelta
from decimal import Decimal
from yams.constraints import (SizeConstraint, StaticVocabularyConstraint,
@@ -163,7 +163,7 @@
def generate_time(self, attrname, index):
"""generates a random time (format is ' HH:MM')"""
- return timedelta(0, 11, index%60) #'11:%02d' % (index % 60)
+ return time(11, index%60) #'11:%02d' % (index % 60)
def generate_datetime(self, attrname, index):
"""generates a random date (format is 'yyyy-mm-dd HH:MM')"""
--- a/entity.py Mon Jun 22 11:15:17 2009 +0200
+++ b/entity.py Tue Jun 23 08:44:42 2009 +0200
@@ -398,7 +398,7 @@
path = etype.lower()
if mainattr != 'eid':
value = getattr(self, mainattr)
- if value is None:
+ if value is None or unicode(value) == u'':
mainattr = 'eid'
path += '/eid'
elif needcheck:
--- a/server/migractions.py Mon Jun 22 11:15:17 2009 +0200
+++ b/server/migractions.py Tue Jun 23 08:44:42 2009 +0200
@@ -523,8 +523,9 @@
self.exec_event_script('postcreate', self.config.cube_dir(pack))
self.commit()
- def cmd_remove_cube(self, cube):
- removedcubes = super(ServerMigrationHelper, self).cmd_remove_cube(cube)
+ def cmd_remove_cube(self, cube, removedeps=False):
+ removedcubes = super(ServerMigrationHelper, self).cmd_remove_cube(
+ cube, removedeps)
if not removedcubes:
return
fsschema = self.fs_schema
--- a/server/msplanner.py Mon Jun 22 11:15:17 2009 +0200
+++ b/server/msplanner.py Tue Jun 23 08:44:42 2009 +0200
@@ -361,7 +361,7 @@
self._set_source_for_term(source, const)
# if system source is used, add every rewritten constant
# to its supported terms even when associated entity
- # doesn't actually comes from it so we get a changes
+ # doesn't actually come from it so we get a changes
# that allequals will return True as expected when
# computing needsplit
# check const is used in a relation restriction
@@ -555,7 +555,12 @@
self.needsplit = False
elif not self.needsplit:
if not allequals(self._sourcesterms.itervalues()):
- self.needsplit = True
+ for terms in self._sourcesterms.itervalues():
+ if any(x for x in terms if not isinstance(x, Constant)):
+ self.needsplit = True
+ return
+ self._sourcesterms = {self.system_source: {}}
+ self.needsplit = False
else:
sample = self._sourcesterms.itervalues().next()
if len(sample) > 1:
--- a/server/schemaserial.py Mon Jun 22 11:15:17 2009 +0200
+++ b/server/schemaserial.py Tue Jun 23 08:44:42 2009 +0200
@@ -109,7 +109,7 @@
ETYPE_NAME_MAP[etype])
print sql
sqlcu.execute(sql)
- # other table renaming done once schema has been readen
+ # other table renaming done once schema has been read
# print 'reading schema from the database...'
index = {}
permsdict = deserialize_ertype_permissions(session)
--- a/server/test/unittest_migractions.py Mon Jun 22 11:15:17 2009 +0200
+++ b/server/test/unittest_migractions.py Tue Jun 23 08:44:42 2009 +0200
@@ -7,6 +7,7 @@
from logilab.common.testlib import TestCase, unittest_main
from cubicweb.devtools.apptest import RepositoryBasedTC, get_versions
+from cubicweb import ConfigurationError
from cubicweb.schema import CubicWebSchemaLoader
from cubicweb.server.sqlutils import SQL_PREFIX
from cubicweb.server.repository import Repository
@@ -365,7 +366,7 @@
finally:
self.mh.cmd_set_size_constraint('CWEType', 'description', None)
- def test_add_remove_cube(self):
+ def test_add_remove_cube_and_deps(self):
cubes = set(self.config.cubes())
schema = self.repo.schema
self.assertEquals(sorted(schema['see_also']._rproperties.keys()),
@@ -374,11 +375,10 @@
('Note', 'Note'), ('Note', 'Bookmark')]))
try:
try:
- self.mh.cmd_remove_cube('email')
+ self.mh.cmd_remove_cube('email', removedeps=True)
# file was there because it's an email dependancy, should have been removed
- cubes.remove('email')
- cubes.remove('file')
- self.assertEquals(set(self.config.cubes()), cubes)
+ self.failIf('email' in self.config.cubes())
+ self.failIf('file' in self.config.cubes())
for ertype in ('Email', 'EmailThread', 'EmailPart', 'File', 'Image',
'sender', 'in_thread', 'reply_to', 'data_format'):
self.failIf(ertype in schema, ertype)
@@ -392,17 +392,14 @@
self.assertEquals(sorted(schema['see_also'].objects()), ['Bookmark', 'Folder', 'Note'])
self.assertEquals(self.execute('Any X WHERE X pkey "system.version.email"').rowcount, 0)
self.assertEquals(self.execute('Any X WHERE X pkey "system.version.file"').rowcount, 0)
- self.failIf('email' in self.config.cubes())
- self.failIf('file' in self.config.cubes())
except :
import traceback
traceback.print_exc()
raise
finally:
self.mh.cmd_add_cube('email')
- cubes.add('email')
- cubes.add('file')
- self.assertEquals(set(self.config.cubes()), cubes)
+ self.failUnless('email' in self.config.cubes())
+ self.failUnless('file' in self.config.cubes())
for ertype in ('Email', 'EmailThread', 'EmailPart', 'File', 'Image',
'sender', 'in_thread', 'reply_to', 'data_format'):
self.failUnless(ertype in schema, ertype)
@@ -420,8 +417,6 @@
email_version)
self.assertEquals(self.execute('Any V WHERE X value V, X pkey "system.version.file"')[0][0],
file_version)
- self.failUnless('email' in self.config.cubes())
- self.failUnless('file' in self.config.cubes())
# trick: overwrite self.maxeid to avoid deletion of just reintroduced
# types (and their associated tables!)
self.maxeid = self.execute('Any MAX(X)')[0][0]
@@ -429,6 +424,38 @@
# next test may fail complaining of missing tables
self.commit()
+
+ def test_add_remove_cube_no_deps(self):
+ cubes = set(self.config.cubes())
+ schema = self.repo.schema
+ try:
+ try:
+ self.mh.cmd_remove_cube('email')
+ cubes.remove('email')
+ self.failIf('email' in self.config.cubes())
+ self.failUnless('file' in self.config.cubes())
+ for ertype in ('Email', 'EmailThread', 'EmailPart',
+ 'sender', 'in_thread', 'reply_to'):
+ self.failIf(ertype in schema, ertype)
+ except :
+ import traceback
+ traceback.print_exc()
+ raise
+ finally:
+ self.mh.cmd_add_cube('email')
+ self.failUnless('email' in self.config.cubes())
+ # trick: overwrite self.maxeid to avoid deletion of just reintroduced
+ # types (and their associated tables!)
+ self.maxeid = self.execute('Any MAX(X)')[0][0]
+ # why this commit is necessary is unclear to me (though without it
+ # next test may fail complaining of missing tables
+ self.commit()
+
+ def test_remove_dep_cube(self):
+ ex = self.assertRaises(ConfigurationError, self.mh.cmd_remove_cube, 'file')
+ self.assertEquals(str(ex), "can't remove cube file, used as a dependency")
+
+
def test_set_state(self):
user = self.session.user
self.mh.set_state(user.eid, 'deactivated')
--- a/server/test/unittest_msplanner.py Mon Jun 22 11:15:17 2009 +0200
+++ b/server/test/unittest_msplanner.py Tue Jun 23 08:44:42 2009 +0200
@@ -2118,6 +2118,15 @@
None, None, [self.vcs], {}, [])
])
+ def test_nonregr_fully_simplified_extsource(self):
+ self.repo._type_source_cache[999998] = ('Note', 'vcs', 999998)
+ self.repo._type_source_cache[999999] = ('Note', 'vcs', 999999)
+ self.repo._type_source_cache[1000000] = ('Note', 'system', 1000000)
+ self._test('DISTINCT Any T,FALSE,L,M WHERE L eid 1000000, M eid 999999, T eid 999998',
+ [('OneFetchStep', [('DISTINCT Any 999998,FALSE,1000000,999999', [{}])],
+ None, None, [self.system], {}, [])
+ ])
+
if __name__ == '__main__':
from logilab.common.testlib import unittest_main
--- a/test/unittest_entity.py Mon Jun 22 11:15:17 2009 +0200
+++ b/test/unittest_entity.py Tue Jun 23 08:44:42 2009 +0200
@@ -390,6 +390,11 @@
metainf['extid'] = 1234
self.assertEquals(note.absolute_url(), 'http://cubicweb2.com/note/1234')
+ def test_absolute_url_empty_field(self):
+ card = self.add_entity('Card', wikiid=u'', title=u'test')
+ self.assertEquals(card.absolute_url(),
+ 'http://testing.fr/cubicweb/card/eid/%s' % card.eid)
+
if __name__ == '__main__':
from logilab.common.testlib import unittest_main
unittest_main()
--- a/web/data/cubicweb.css Mon Jun 22 11:15:17 2009 +0200
+++ b/web/data/cubicweb.css Tue Jun 23 08:44:42 2009 +0200
@@ -1,6 +1,6 @@
/*
* :organization: Logilab
- * :copyright: 2003-2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+ * :copyright: 2003-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
* :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
*/
/***************************************/
@@ -12,7 +12,7 @@
padding :0px;
}
-html, body {
+html, body {
background: #e2e2e2;
}
@@ -277,8 +277,8 @@
position: relative;
min-height: 800px;
}
-
-table#mainLayout{
+
+table#mainLayout{
margin:0px 3px;
}
@@ -321,7 +321,7 @@
/* boxes */
div.navboxes {
- margin-top: 8px;
+ margin-top: 8px;
}
div.boxFrame {
@@ -459,9 +459,9 @@
max-width: 50em;
}
-ul.sideBox li{
+ul.sideBox li{
list-style: none;
- background: none;
+ background: none;
padding: 0px 0px 1px 1px;
}
@@ -576,7 +576,7 @@
div.primaryRight{
float:right;
-
+
}
div.metadata {
@@ -603,7 +603,7 @@
padding-bottom:0.4px
}
-div.row span.label{
+div.row span.label{
padding-right:1em
}
@@ -772,20 +772,20 @@
/* addcombobox */
/***************************************/
-input#newopt{
- width:120px ;
+input#newopt{
+ width:120px ;
display:block;
float:left;
}
-div#newvalue{
+div#newvalue{
margin-top:2px;
}
#add_newopt{
background: #fffff8 url("go.png") 50% 50% no-repeat;
width: 20px;
- line-height: 20px;
+ line-height: 20px;
display:block;
float:left;
}
@@ -794,7 +794,7 @@
/* buttons */
/***************************************/
-input.button{
+input.button{
margin: 1em 1em 0px 0px;
border: 1px solid #edecd2;
border-color:#edecd2 #cfceb7 #cfceb7 #edecd2;
@@ -838,7 +838,7 @@
font-weight: bold;
}
-input.validateButton {
+input.validateButton {
margin: 1em 1em 0px 0px;
border: 1px solid #edecd2;
border-color:#edecd2 #cfceb7 #cfceb7 #edecd2;
--- a/web/data/cubicweb.facets.css Mon Jun 22 11:15:17 2009 +0200
+++ b/web/data/cubicweb.facets.css Tue Jun 23 08:44:42 2009 +0200
@@ -1,7 +1,7 @@
#filterbox fieldset{
margin: 0px;
padding: 0px;
-}
+}
div.facet {
margin-bottom: 8px;
@@ -14,11 +14,11 @@
font-size: 80%;
color: #000;
margin-bottom: 2px;
- cursor: pointer;
+ cursor: pointer;
font: bold 100% Georgia;
}
-div.facetTitle a {
+div.facetTitle a {
padding-left: 10px;
background: transparent url("puce.png") 0% 50% no-repeat;
}
@@ -26,12 +26,12 @@
div.facetBody {
}
-.opened{
- color: #000 !important;
+.opened{
+ color: #000 !important;
}
div.overflowed{
- height: 12em;
+ height: 12em;
overflow-y: auto;
}
@@ -50,12 +50,12 @@
}
div.facetValue img{
- float: left;
+ float: left;
background: #fff;
}
div.facetValue a {
- margin-left: 20px;
+ margin-left: 20px;
display: block;
margin-top: -6px; /* FIXME why do we need this ? */
}
@@ -78,11 +78,11 @@
}
-div.facetCheckBox{
+div.facetCheckBox{
line-height:0.8em;
}
-.facet input{
+.facet input{
margin-top:3px;
border:1px solid #ccc;
font-size:11px;
--- a/web/data/cubicweb.htmlhelpers.js Mon Jun 22 11:15:17 2009 +0200
+++ b/web/data/cubicweb.htmlhelpers.js Tue Jun 23 08:44:42 2009 +0200
@@ -247,6 +247,11 @@
}
}
+function limitTextAreaSize(textarea, size) {
+ var $area = jQuery(textarea);
+ $area.val($area.val().slice(0, size));
+}
+
//============= page loading events ==========================================//
function roundedCornersOnLoad() {
jQuery('div.sideBox').corner('bottom 6px');
--- a/web/data/cubicweb.login.css Mon Jun 22 11:15:17 2009 +0200
+++ b/web/data/cubicweb.login.css Tue Jun 23 08:44:42 2009 +0200
@@ -1,7 +1,7 @@
/* styles for the login popup and login form
*
* :organization: Logilab
- * :copyright: 2003-2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+ * :copyright: 2003-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
* :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
*/
@@ -12,7 +12,7 @@
width: 26em;
padding: 0px 1px 1px;
font-weight: bold;
- background: #E4EAD8;
+ background: #E4EAD8;
}
div#popupLoginBox div#loginContent {
@@ -20,7 +20,7 @@
padding: 5px 3px 4px;
}
-div#loginBox {
+div#loginBox {
position : absolute;
top: 15%;
left : 50%;
@@ -32,12 +32,12 @@
text-align: center;
}
-div#loginBox h1 {
+div#loginBox h1 {
color: #FF7700;
font-size: 140%;
}
-div#loginTitle {
+div#loginTitle {
color: #fff;
font-weight: bold;
font-size: 140%;
@@ -46,32 +46,32 @@
background: #ff7700 url("banner.png") left top repeat-x;
}
-div#loginBox div#loginContent form {
+div#loginBox div#loginContent form {
padding-top: 1em;
- width: 90%;
- margin: auto;
+ width: 90%;
+ margin: auto;
}
-#popupLoginBox table td {
- padding: 0px 3px;
+#popupLoginBox table td {
+ padding: 0px 3px;
white-space: nowrap;
}
-#loginContent table {
+#loginContent table {
padding: 0px 0.5em;
margin: auto;
}
-#loginBox table td {
- padding: 0px 3px 0.6em;
+#loginBox table td {
+ padding: 0px 3px 0.6em;
white-space: nowrap;
}
-#loginBox .loginButton {
+#loginBox .loginButton {
margin-top: 0.6em;
}
-#loginContent input.data {
+#loginContent input.data {
width:12em;
}
@@ -79,5 +79,5 @@
border: 1px solid #edecd2;
border-color:#edecd2 #cfceb7 #cfceb7 #edecd2;
margin: 2px 0px 0px;
- background: #f0eff0 url("gradient-grey-up.png") left top repeat-x;
+ background: #f0eff0 url("gradient-grey-up.png") left top repeat-x;
}
--- a/web/facet.py Mon Jun 22 11:15:17 2009 +0200
+++ b/web/facet.py Tue Jun 23 08:44:42 2009 +0200
@@ -744,7 +744,7 @@
% (cssclass, html_escape(unicode(self.value))))
self.w(u'<div class="facetCheckBoxWidget">')
self.w(u'<img src="%s" alt="%s" cubicweb:unselimg="true" /> ' % (imgsrc, imgalt))
- self.w(u'<label class="facetTitle" cubicweb:facetName="%s"><a href="javascript: {}">%s</a></label>' % (facetid,title))
+ self.w(u'<label class="facetTitle" cubicweb:facetName="%s"><a href="javascript: {}">%s</a></label>' % (facetid, title))
self.w(u'</div>\n')
self.w(u'</div>\n')
self.w(u'</div>\n')
--- a/web/formwidgets.py Mon Jun 22 11:15:17 2009 +0200
+++ b/web/formwidgets.py Tue Jun 23 08:44:42 2009 +0200
@@ -148,7 +148,7 @@
"""<textarea>"""
def render(self, form, field):
name, values, attrs = self._render_attrs(form, field)
- attrs.setdefault('onkeypress', 'autogrow(this)')
+ attrs.setdefault('onkeyup', 'autogrow(this)')
attrs.setdefault('cols', 80)
attrs.setdefault('rows', 20)
if not values:
--- a/web/test/unittest_form.py Mon Jun 22 11:15:17 2009 +0200
+++ b/web/test/unittest_form.py Tue Jun 23 08:44:42 2009 +0200
@@ -145,12 +145,12 @@
<option value="text/html">text/html</option>
<option value="text/plain">text/plain</option>
<option selected="selected" value="text/rest">text/rest</option>
-</select><textarea cols="60" id="description:%(eid)s" name="description:%(eid)s" onkeypress="autogrow(this)" rows="5" tabindex="1"/>''')
+</select><textarea cols="60" id="description:%(eid)s" name="description:%(eid)s" onkeyup="autogrow(this)" rows="5" tabindex="1"/>''')
def test_richtextfield_2(self):
self.req.use_fckeditor = lambda: True
- self._test_richtextfield('<input name="description_format:%(eid)s" style="display: block" type="hidden" value="text/rest"/><textarea cols="80" cubicweb:type="wysiwyg" id="description:%(eid)s" name="description:%(eid)s" onkeypress="autogrow(this)" rows="20" tabindex="0"/>')
+ self._test_richtextfield('<input name="description_format:%(eid)s" style="display: block" type="hidden" value="text/rest"/><textarea cols="80" cubicweb:type="wysiwyg" id="description:%(eid)s" name="description:%(eid)s" onkeyup="autogrow(this)" rows="20" tabindex="0"/>')
def test_filefield(self):
@@ -195,7 +195,7 @@
<input name="data:%(eid)s__detach" type="checkbox"/>
detach attached file
<p><b>You can either submit a new file using the browse button above, or choose to remove already uploaded file by checking the "detach attached file" check-box, or edit file content online with the widget below.</b></p>
-<textarea cols="80" name="data:%(eid)s" onkeypress="autogrow(this)" rows="20" tabindex="3">new widgets system</textarea>''' % {'eid': file.eid})
+<textarea cols="80" name="data:%(eid)s" onkeyup="autogrow(this)" rows="20" tabindex="3">new widgets system</textarea>''' % {'eid': file.eid})
def test_passwordfield(self):
--- a/web/views/actions.py Mon Jun 22 11:15:17 2009 +0200
+++ b/web/views/actions.py Tue Jun 23 08:44:42 2009 +0200
@@ -6,6 +6,7 @@
:license: GNU Lesser General Public License, v2.1 - http://www.gnu.org/licenses
"""
__docformat__ = "restructuredtext en"
+_ = unicode
from cubicweb.vregistry import objectify_selector
from cubicweb.selectors import (EntitySelector,
@@ -18,8 +19,6 @@
from cubicweb.web.views import linksearch_select_url, vid_from_rset
from cubicweb.web.views.autoform import AutomaticEntityForm
-_ = unicode
-
class has_editable_relation(EntitySelector):
"""accept if some relations for an entity found in the result set is
--- a/web/views/basecomponents.py Mon Jun 22 11:15:17 2009 +0200
+++ b/web/views/basecomponents.py Tue Jun 23 08:44:42 2009 +0200
@@ -29,7 +29,8 @@
"""build the rql input form, usually displayed in the header"""
id = 'rqlinput'
property_defs = VISIBLE_PROP_DEF
-
+ visible = False
+
def call(self, view=None):
if hasattr(view, 'filter_box_context_info'):
rset = view.filter_box_context_info()[0]
@@ -148,8 +149,10 @@
site_wide = True
def call(self):
- self.w(u'<span id="appliName"><a href="%s">%s</a></span>' % (
- self.req.base_url(), self.req.property_value('ui.site-title')))
+ title = self.req.property_value('ui.site-title')
+ if title:
+ self.w(u'<span id="appliName"><a href="%s">%s</a></span>' % (
+ self.req.base_url(), title))
class SeeAlsoVComponent(component.RelatedObjectsVComponent):
--- a/web/views/basetemplates.py Mon Jun 22 11:15:17 2009 +0200
+++ b/web/views/basetemplates.py Tue Jun 23 08:44:42 2009 +0200
@@ -431,7 +431,7 @@
self.w(u'<div id="%s" class="%s">' % (id, klass))
if title:
self.w(u'<div id="loginTitle">%s</div>'
- % self.req.property_value('ui.site-title'))
+ % (self.req.property_value('ui.site-title') or u' '))
self.w(u'<div id="loginContent">\n')
if message:
--- a/web/views/tableview.py Mon Jun 22 11:15:17 2009 +0200
+++ b/web/views/tableview.py Tue Jun 23 08:44:42 2009 +0200
@@ -140,6 +140,7 @@
actions += self.form_filter(divid, displaycols, displayfilter,
displayactions)
elif displayfilter:
+ req.add_css('cubicweb.facets.css')
actions += self.show_hide_actions(divid, True)
self.w(u'<div id="%s"' % divid)
if displayactions:
--- a/web/widgets.py Mon Jun 22 11:15:17 2009 +0200
+++ b/web/widgets.py Tue Jun 23 08:44:42 2009 +0200
@@ -418,7 +418,7 @@
hidden = u'<input type="hidden" name="edits-%s" value="%s"/>\n'\
'<input type="hidden" name="%s" value="text/html"/>\n' % (
frname, format, frname)
- return u'%s<textarea cubicweb:type="wysiwyg" onkeypress="autogrow(this)" name="%s" %s>%s</textarea>' % (
+ return u'%s<textarea cubicweb:type="wysiwyg" onkeyup="autogrow(this)" name="%s" %s>%s</textarea>' % (
hidden, self.rname, self.format_attrs(), dvalue)
if with_format and entity.e_schema.has_metadata(self.name, 'format'):
fmtwdg = entity.get_widget(self.name + '_format')
@@ -426,7 +426,7 @@
self.attrs['tabindex'] = entity.req.next_tabindex()
else:
fmtwdgstr = ''
- return u'%s<br/><textarea onkeypress="autogrow(this)" name="%s" %s>%s</textarea>' % (
+ return u'%s<br/><textarea onkeyup="autogrow(this)" name="%s" %s>%s</textarea>' % (
fmtwdgstr, self.rname, self.format_attrs(), dvalue)