[javascript] provide a simple function to limit textarea size (+minor cosmetic changes)
"""html calendar views:organization: Logilab:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), license is LGPL v2.:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr:license: GNU Lesser General Public License, v2.1 - http://www.gnu.org/licenses"""fromlogilab.mtconverterimporthtml_escapefromcubicweb.interfacesimportITimetableViewsfromcubicweb.selectorsimportimplementsfromcubicweb.utilsimportdate_rangefromcubicweb.viewimportAnyRsetViewclass_TaskEntry(object):def__init__(self,task,color,column):self.task=taskself.color=colorself.column=columnself.lines=1MIN_COLS=3# minimum number of task columns for a single userclassTimeTableView(AnyRsetView):id='timetable'title=_('timetable')__select__=implements(ITimetableViews)need_navigation=Falsedefcall(self,title=None):"""Dumps a timetable from a resultset composed of a note (anything with start/stop) and a user (anything)"""self.req.add_css('cubicweb.timetable.css')dates={}users=[]users_max={}# XXX: try refactoring with calendar.py:OneMonthCalforrowinxrange(self.rset.rowcount):task=self.rset.get_entity(row,0)iflen(self.rset[row])>1:user=self.rset.get_entity(row,1)else:user=u"*"the_dates=[]iftask.startandtask.stop:iftask.start.toordinal()==task.stop.toordinal():the_dates.append(task.start)else:the_dates+=date_range(task.start,task.stop)eliftask.start:the_dates.append(task.start)eliftask.stop:the_dates.append(task.stop)fordinthe_dates:d_users=dates.setdefault(d,{})u_tasks=d_users.setdefault(user,set())u_tasks.add(task)task_max=users_max.setdefault(user,0)iflen(u_tasks)>task_max:users_max[user]=len(u_tasks)ifusernotinusers:# keep original orderingusers.append(user)ifnotdates:returndate_min=min(dates)date_max=max(dates)#users = list(sorted(users, key=lambda u:u.login))rows=[]# colors here are class names defined in cubicweb.csscolors=["col%x"%iforiinxrange(12)]next_color_index=0visited_tasks={}# holds a description of a task for a usertask_colors={}# remember a color assigned to a taskfordateindate_range(date_min,date_max):columns=[date]d_users=dates.get(date,{})foruserinusers:# every user has its column "splitted" in at least MIN_COLS# sub-columns (for overlapping tasks)user_columns=[None]*max(MIN_COLS,users_max[user])# every task that is "visited" for the first time# require a special treatment, so we put them in# 'postpone'postpone=[]fortaskind_users.get(user,[]):key=(task,user)ifkeyinvisited_tasks:task_descr=visited_tasks[key]user_columns[task_descr.column]=task_descr,Falsetask_descr.lines+=1else:postpone.append(key)forkeyinpostpone:# to every 'new' task we must affect a color# (which must be the same for every user concerned# by the task)task,user=keyfori,tinenumerate(user_columns):iftisNone:iftaskintask_colors:color=task_colors[task]else:color=colors[next_color_index]next_color_index=(next_color_index+1)%len(colors)task_colors[task]=colortask_descr=_TaskEntry(task,color,i)user_columns[i]=task_descr,Truevisited_tasks[key]=task_descrbreakelse:raiseRuntimeError("is it possible we got it wrong?")columns.append(user_columns)rows.append(columns)widths=[len(col)forcolinrows[0][1:]]self.w(u'<div class="section">')iftitle:self.w(u'<h4>%s</h4>\n'%title)self.w(u'<table class="listing timetable">')self.render_col_headers(users,widths)self.render_rows(rows)self.w(u'</table>')self.w(u'</div>\n')defrender_col_headers(self,users,widths):""" render column headers """self.w(u'<tr class="header">\n')self.w(u'<th class="ttdate"> </th>\n')columns=[]foruser,widthinzip(users,widths):self.w(u'<th colspan="%s">'%max(MIN_COLS,width))ifuser!=u"*":user.view('secondary',w=self.w)else:self.w(user)self.w(u'</th>')self.w(u'</tr>\n')returncolumnsdefrender_rows(self,rows):""" render table content (row headers and central content) """odd=Falseprevious_is_empty=Falseforrowinrows:date=row[0]empty_line=Trueforgroupinrow[1:]:forvalueingroup:ifvalue:empty_line=Falsebreakelse:continuebreakifempty_lineandprevious_is_empty:continueprevious_is_empty=Falseklass="even"ifdate.weekday()in(5,6)andnotempty_line:klass="odd"self.w(u'<tr class="%s">'%klass)odd=notoddifnotempty_line:self.w(u'<th class="ttdate">%s</th>'%self.format_date(date))else:self.w(u'<th>...</th>')previous_is_empty=Trueempty_klasses=["ttle","ttme","ttre"]filled_klasses=["ttlf","ttmf","ttrf"]kj=0# 0: left, 1: mid, 2: rightforuid,groupinenumerate(row[1:]):fori,valueinenumerate(group):ifi==0:kj=0elifi==len(group):kj=2else:kj=1ifvalue:task_descr,first_row=valueiffirst_row:url=html_escape(task_descr.task.absolute_url(vid="edition"))self.w(u'<td rowspan="%d" class="%s%s" onclick="document.location=\'%s\'"> <div>'%(task_descr.lines,task_descr.color,filled_klasses[kj],url))task_descr.task.view('tooltip',w=self.w)self.w(u'</div></td>')else:ifempty_line:self.w(u'<td class="ttempty"> </td>')else:self.w(u'<td class="%s"> </td>'%empty_klasses[kj])self.w(u'</tr>\n')