def collapsed(id_, content, button_content=None): return HTML.div( HTML.p( HTML.a( button_content or icon('plus-sign'), **{ 'class': 'btn', 'data-toggle': 'collapse', 'data-target': '#%s' % id_ })), HTML.div(content, id=id_, class_='collapse'))
def collapsed(id_, content, button_content=None): return HTML.div( HTML.p( HTML.a( button_content or icon("plus-sign"), **{"class": "btn", "data-toggle": "collapse", "data-target": "#%s" % id_} ) ), HTML.div(content, id=id_, class_="collapse"), )
def alt_representations(req, rsc, doc_position='right', exclude=None): exclude = exclude or [] exclude.extend(['html', 'snippet.html']) adapters = [ a for n, a in req.registry.getAdapters([rsc], interfaces.IRepresentation) if a.extension not in set(exclude) ] doc = [] for adapter in adapters: if adapter.__doc__: doc.append(HTML.dt(adapter.name or adapter.extension)) doc.append(HTML.dd(adapter.__doc__)) doc = HTML.div( HTML.p( """You may download alternative representations of the data on "%s" by clicking the button """ % rsc.name, icon('download-alt')), HTML.dl(*doc)) return HTML.div( HTML.div( button( icon('info-sign', inverted=True), **{ 'class': ['btn-info'], 'id': 'rsc-dl', 'data-content': unicode(doc) }), HTML.a( icon('download-alt'), HTML.span(class_="caret"), **{ 'class_': "btn dropdown-toggle", 'data-toggle': "dropdown", 'href': "#", 'id': "dt-dl-opener", }), HTML.ul( *[ HTML.li( HTML. a(a.name or a.extension, href="#", onclick="document.location.href = '%s'; return false;" % req.resource_url(rsc, ext=a.extension), id='dt-dl-%s' % a.extension)) for a in adapters ], **dict(class_="dropdown-menu")), class_='btn-group'), HTML.script( literal("""\ $(document).ready(function() { $('#rsc-dl').clickover({ html: true, title: 'Alternative representations', placement: '%s', trigger: 'click' }); });""" % doc_position)))
def alt_representations(req, rsc, doc_position='right', exclude=None): exclude = exclude or [] exclude.extend(['html', 'snippet.html']) adapters = [a for n, a in req.registry.getAdapters([rsc], interfaces.IRepresentation) if a.extension not in set(exclude)] doc = [] for adapter in adapters: if adapter.__doc__: doc.append(HTML.dt(adapter.name or adapter.extension)) doc.append(HTML.dd(adapter.__doc__)) doc = HTML.div( HTML.p( """You may download alternative representations of the data on "%s" by clicking the button """ % rsc.name, icon('download-alt')), HTML.dl(*doc)) return HTML.div(HTML.div( button( icon('info-sign', inverted=True), **{'class': ['btn-info'], 'id': 'rsc-dl', 'data-content': unicode(doc)}), HTML.a( icon('download-alt'), HTML.span(class_="caret"), **{ 'class_': "btn dropdown-toggle", 'data-toggle': "dropdown", 'href': "#", 'id': "dt-dl-opener", } ), HTML.ul( *[HTML.li(HTML.a( a.name or a.extension, href="#", onclick="document.location.href = '%s'; return false;" % req.resource_url(rsc, ext=a.extension), id='dt-dl-%s' % a.extension)) for a in adapters], **dict(class_="dropdown-menu")), class_='btn-group'), HTML.script(literal("""\ $(document).ready(function() { $('#rsc-dl').clickover({ html: true, title: 'Alternative representations', placement: '%s', trigger: 'click' }); });""" % doc_position)))
def text2html(text, mode='br', sep='\n\n'): """ >>> assert 'div' in unicode(text2html('chunk', mode='p')) """ if mode == 'p': return HTML.div(*[HTML.p(literal(newline2br(line))) for line in text.split(sep)]) return HTML.p(literal(newline2br(text)))
def format(self, item): item = self.get_obj(item) if item.family: label = link(self.dt.req, item.family) if self._link else item.family.name else: label = 'isolate' return HTML.div(map_marker_img(self.dt.req, item), ' ', label)
def toolbar(self): """ """ return HTML.div( button(icon('info-sign', inverted=True), class_='btn-info %s-cdOpener' % self.eid), HTML.a( icon('download-alt'), HTML.span(class_="caret"), **{ 'class_': "btn dropdown-toggle", 'data-toggle': "dropdown", 'href': "#", 'id': "dt-dl-opener", }), HTML.ul( #HTML.li(HTML.a('csv', href="#")), *[ HTML.li( HTML. a(fmt, href="#", onclick= "document.location.href = CLLD.DataTable.current_url" "('%s', '%s'); return false;" % (self.eid, fmt), id='dt-dl-%s' % fmt)) for fmt in [ a.extension for n, a in self.req.registry.getAdapters( [self.model()], IIndex) ] if fmt != 'html' ], **dict(class_="dropdown-menu")), class_='btn-group right')
def image_detail_html(context=None, request=None, **kw): referents = get_sticks(context) if context.mime_type == 'application/pdf': return { 'referents': referents, 'image': HTML.div( HTML.iframe( class_='pdf_iframe', src='%sbitstreams/%s/%s' % (cdstar.SERVICE_URL, context.jsondata.get('refobjid'), context.jsondata.get('original')), frameborder='0', ), class_='div_pdf_iframe', ) } else: return { 'referents': referents, 'image': HTML.img( class_='image_single', src=cdstar.bitstream_url(context), ), }
def format(self, item): obj = self.get_obj(item) if obj: return HTML.div(link(self.dt.req, obj), style="background-color: #%s;" % obj.color, class_='dt-full-cell') return '' # pragma: no cover
def toolbar(self): """ """ return HTML.div( button( icon('info-sign', inverted=True), class_='btn-info %s-cdOpener' % self.eid), HTML.a( icon('download-alt'), HTML.span(class_="caret"), **{ 'class_': "btn dropdown-toggle", 'data-toggle': "dropdown", 'href': "#", 'id': "dt-dl-opener", } ), HTML.ul( #HTML.li(HTML.a('csv', href="#")), *[HTML.li(HTML.a( fmt, href="#", onclick="document.location.href = CLLD.DataTable.current_url" "('%s', '%s'); return false;" % (self.eid, fmt), id='dt-dl-%s' % fmt)) for fmt in [a.extension for n, a in self.req.registry.getAdapters([self.model()], IIndex)] if fmt != 'html'], **dict(class_="dropdown-menu")), class_='btn-group right')
def format_iso_retirement(req, lang): ir = lang.jsondata['iso_retirement'] _md, comment = [], '' if ir['comment']: comment = HTML.div( HTML.p(HTML.strong("Excerpt from change request document:")), HTML.blockquote(md(req, ir['comment'], small=True))) if ir['change_request']: _md.append(('Change request:', link(req, Refprovider.get('iso6393:{0}'.format( ir['change_request'])).ref, label=ir['change_request']))) _md.append(('ISO 639-3:', ir['code'])) _md.append(('Name:', ir['name'])) if ir['reason']: _md.append(('Reason:', ir['reason'])) _md.append(('Effective:', ir['effective'])) return infobox( HTML.p(HTML.strong("Retired in ISO 639-3: "), linkify_iso_codes(req, ir['remedy'], class_='iso639-3')), HTML.ul( *[ HTML.li(HTML.strong(dt), Markup(' '), dd) for dt, dd in _md ], **{'class': 'inline'}), comment)
def format_iso_retirement(req, lang): ir = lang.iso_retirement _md, comment = [], '' if ir.description: comment = HTML.div( HTML.p(HTML.strong("Excerpt from change request document:")), HTML.blockquote(md(req, ir.description, small=True))) if ir.change_request: _md.append(( 'Change request:', link( req, Refprovider.get('iso6393:{0}'.format(ir.change_request)).ref, label=ir.change_request))) _md.append(('ISO 639-3:', ir.id)) _md.append(('Name:', ir.name)) if ir.reason: _md.append(('Reason:', ir.reason)) _md.append(('Effective:', ir.effective)) return infobox( HTML.p( HTML.strong("Retired in ISO 639-3: "), linkify_iso_codes(req, ir.remedy, class_='iso639-3')), HTML.ul(*[HTML.li(HTML.strong(dt), Markup(' '), dd) for dt, dd in _md], **{'class': 'inline'}), comment)
def text2html(text, mode="br", sep="\n\n"): """Turn plain text into simple HTML. >>> assert 'div' in text_type(text2html('chunk', mode='p')) """ if mode == "p": return HTML.div(*[HTML.p(literal(newline2br(line))) for line in text.split(sep)]) return HTML.p(literal(newline2br(text)))
def format(self, item): item = self.get_obj(item) if item.family: label = link(self.dt.req, item.family) if self._link else item.family.name else: label = 'isolate' return HTML.div(map_marker_img(self.dt.req, item), ' ', label)
def text2html(text, mode='br', sep='\n\n'): """ >>> assert 'div' in unicode(text2html('chunk', mode='p')) """ if mode == 'p': return HTML.div( *[HTML.p(literal(newline2br(line))) for line in text.split(sep)]) return HTML.p(literal(newline2br(text)))
def infobox(*content): return HTML.div( HTML.button( '\xd7', **{ 'type': "button", 'class': "close", 'data-dismiss': "alert" }), *content, **{'class': "alert alert-success"})
def format(self, item): obj = self.get_obj(item) if obj: return HTML.div( link(self.dt.req, obj), style="background-color: #%s;" % obj.color, class_='dt-full-cell') return '' # pragma: no cover
def alt_translation(sentence): res = '' if sentence.jsondata.get('alt_translation'): text = sentence.jsondata['alt_translation'] name = '' if ALT_TRANSLATION_LANGUAGE_PATTERN.match(text): name, text = [t.strip() for t in text.split(':', 1)] name = HTML.span(name + ': ') res = HTML.div(name, HTML.span(text, class_='translation')) return res
def hb_score(name, description, domain): return HTML.div( HTML.p("""This gives the average {name} of all words corresponding to this meaning. The following {name}s are assigned to words depending on {description}:""".format(**locals())), HTML.table( HTML.thead(HTML.tr( HTML.th(' '), HTML.th('score'))), HTML.tbody( *[HTML.tr(HTML.td(label), HTML.td(score)) for label, score in domain])))
def alt_translation(sentence): res = "" if sentence.jsondata.get("alt_translation"): text = sentence.jsondata["alt_translation"] name = "" if ALT_TRANSLATION_LANGUAGE_PATTERN.match(text): name, text = [t.strip() for t in text.split(":", 1)] name = HTML.span(name + ": ") res = HTML.div(name, HTML.span(text, class_="translation")) return res
def hb_score(name, description, domain): return HTML.div( HTML.p("""This gives the average {name} of all words corresponding to this meaning. The following {name}s are assigned to words depending on {description}:""".format(**locals())), HTML.table( HTML.thead(HTML.tr( HTML.th(' '), HTML.th('score'))), HTML.tbody( *[HTML.tr(HTML.td(label), HTML.td(score)) for label, score in domain])))
def alt_translation(sentence): res = '' if sentence.jsondatadict.get('alt_translation'): text = sentence.jsondatadict['alt_translation'] name = '' if ALT_TRANSLATION_LANGUAGE_PATTERN.match(text): name, text = [t.strip() for t in text.split(':', 1)] name = HTML.span(name + ': ') res = HTML.div(name, HTML.span(text, class_='translation')) return res
def parameter_chapter_html(context=None, request=None, **kw): if context.feature_type != 'primary': raise HTTPNotFound() try: _html = get_text('Atlas', request.matchdict['id'], 'html') return { 'md': get_text('Atlas', request.matchdict['id'], 'json'), 'html': lambda vt: _html.replace('<p>value-table</p>', HTML.div(vt)), 'css': get_text('Atlas', request.matchdict['id'], 'css'), } except ValueError: return {'md': {}, 'html': lambda s: '', 'css': ''}
def parameter_chapter_html(context=None, request=None, **kw): if context.feature_type != 'primary': raise HTTPNotFound() try: _html = get_text('Atlas', request.matchdict['id'], 'html') return { 'md': get_text('Atlas', request.matchdict['id'], 'json'), 'html': lambda vt: _html.replace('<p>value-table</p>', HTML.div(vt)), 'css': get_text('Atlas', request.matchdict['id'], 'css'), } except ValueError: return {'md': {}, 'html': lambda s: '', 'css': ''}
def render(self, no_js=False): adapters = [ a for n, a in self.req.registry.getAdapters([self.obj], self.interface) if a.extension not in set(self.options['exclude']) ] adoc = [] for adapter in adapters: if adapter.__doc__: adoc.append(HTML.dt(adapter.name or adapter.extension)) adoc.append(HTML.dd(adapter.__doc__)) doc = HTML.div( HTML.p( """You may download alternative representations of the data on "%s" by clicking the button """ % self.ctx, HTML.i(class_='icon-download-alt')), self.doc(), HTML.dl(*adoc)) res = HTML.div( HTML.button(HTML.i(class_='icon-info-sign icon-white'), class_='btn btn-info %s' % self._opener_class, **{ 'data-content': text_type(doc), 'type': 'button' }), HTML.a( HTML.i(class_='icon-download-alt'), HTML.span(class_="caret"), **{ 'class_': "btn dropdown-toggle", 'data-toggle': "dropdown", 'href': "#", 'id': self._id_prefix + "opener" }), HTML.ul(*[HTML.li(self.dl_link(adapter)) for adapter in adapters], **dict(class_="dropdown-menu")), class_='btn-group right') if no_js: return res return HTML.div(res, self.js())
def format(self, item): return HTML.div(HTML.div( HTML.div(HTML.a( '{0} Languages'.format(len(item.contribution_assocs)), **{ 'class': 'accordion-toggle', 'data-toggle': 'collapse', 'data-parent': '#acc-{0}'.format(item.pk), 'href': '#coll-{0}'.format(item.pk) }), class_='accordion-heading'), HTML.div( HTML.div(HTML.ul(*[ HTML.li(link(self.dt.req, c.contribution)) for c in item.contribution_assocs ]), class_='accordion-inner'), **{ 'class': 'accordion-body collapse', 'id': 'coll-{0}'.format(item.pk) }), class_='accordion-group', ), class_='accordion', id='acc-{0}'.format(item.pk))
def render(self, no_js=False): adapters = [a for n, a in self.req.registry.getAdapters([self.obj], self.interface) if a.extension not in set(self.options['exclude'])] adapters = sorted(adapters, key=lambda x: x.extension) adoc = [] for adapter in adapters: if adapter.__doc__: adoc.append(HTML.dt(adapter.name or adapter.extension)) adoc.append(HTML.dd(adapter.__doc__)) doc = HTML.div( HTML.p( """You may download alternative representations of the data on "%s" by clicking the button """ % self.ctx, HTML.i(class_='icon-download-alt')), self.doc(), HTML.dl(*adoc)) res = HTML.div( HTML.button( HTML.i(class_='icon-info-sign icon-white'), class_='btn btn-info %s' % self._opener_class, **{'data-content': text_type(doc), 'type': 'button'}), HTML.a( HTML.i(class_='icon-download-alt'), HTML.span(class_="caret"), **{ 'class_': "btn dropdown-toggle", 'data-toggle': "dropdown", 'href': "#", 'id': self._id_prefix + "opener"}), HTML.ul( *[HTML.li(self.dl_link(adapter)) for adapter in adapters], **dict(class_="dropdown-menu")), class_='btn-group right') if no_js: return res return HTML.div(res, self.js())
def format_coordinates(obj, no_seconds=True, wgs_link=True): """ WGS84 53° 33' 2" N, 9° 59' 36" E 53.550556°, 9.993333° .. seealso:: http://en.wikipedia.org/wiki/ISO_6709#Order.2C_sign.2C_and_units """ def degminsec(dec, hemispheres): _dec = abs(dec) degrees = int(floor(_dec)) _dec = (_dec - int(floor(_dec))) * 60 minutes = int(floor(_dec)) _dec = (_dec - int(floor(_dec))) * 60 seconds = _dec if no_seconds: if seconds > 30: if minutes < 59: minutes += 1 else: minutes = 0 degrees += 1 fmt = "{0}\xb0" if minutes: fmt += "{1:0>2d}'" if not no_seconds and seconds: fmt += '{2:0>2f}"' fmt += hemispheres[0] if dec > 0 else hemispheres[1] return unicode(fmt).format(degrees, minutes, seconds) if not isinstance(obj.latitude, float) or not isinstance(obj.longitude, float): return '' return HTML.div( HTML.table( HTML.tr( HTML.td( 'Coordinates ', external_link( 'http://en.wikipedia.org/wiki/World_Geodetic_System_1984', label="WGS84") if wgs_link else ''), HTML.td( HTML.span('%s, %s' % ( degminsec(obj.latitude, 'NS'), degminsec(obj.longitude, 'EW'))), HTML.br(), HTML.span( '{0.latitude:.2f}, {0.longitude:.2f}'.format(obj), class_='geo'))), class_="table table-condensed"))
def format_coordinates(obj, no_seconds=True, wgs_link=True): """Format WGS84 coordinates as HTML. .. seealso:: http://en.wikipedia.org/wiki/ISO_6709#Order.2C_sign.2C_and_units """ def degminsec(dec, hemispheres): _dec = abs(dec) degrees = int(floor(_dec)) _dec = (_dec - int(floor(_dec))) * 60 minutes = int(floor(_dec)) _dec = (_dec - int(floor(_dec))) * 60 seconds = _dec if no_seconds: if seconds > 30: if minutes < 59: minutes += 1 else: minutes = 0 degrees += 1 fmt = "{0}\xb0" if minutes: fmt += "{1:0>2d}'" if not no_seconds and seconds: fmt += '{2:0>2f}"' fmt += hemispheres[0] if dec > 0 else hemispheres[1] return text_type(fmt).format(degrees, minutes, seconds) if not isinstance(obj.latitude, float) or not isinstance(obj.longitude, float): return "" return HTML.div( HTML.table( HTML.tr( HTML.td( "Coordinates ", external_link("http://en.wikipedia.org/wiki/World_Geodetic_System_1984", label="WGS84") if wgs_link else "", ), HTML.td( HTML.span("%s, %s" % (degminsec(obj.latitude, "NS"), degminsec(obj.longitude, "EW"))), HTML.br(), HTML.span("{0.latitude:.2f}, {0.longitude:.2f}".format(obj), class_="geo"), ), ), class_="table table-condensed", ) )
def _media(maintype_, obj, **kw): label = kw.pop('label', None) assert maintype_ in ['audio', 'video'] if maintype(obj) != maintype_: raise ValueError('type mismatch: {0} and {1}'.format(maintype(obj), maintype_)) kw.setdefault('controls', 'controls') media_element = getattr(HTML, maintype_)( literal('Your browser does not support the <code>{0}</code> element.'.format( maintype_)), HTML.source(src=bitstream_url(obj, type_='web'), type=mimetype(obj)), **kw) return HTML.div( media_element, HTML.br(), link(obj, label=label), class_='cdstar_{0}_link'.format(maintype_), style='margin-top: 10px')
def _media(maintype_, obj, **kw): label = kw.pop('label', None) assert maintype_ in ['audio', 'video'] if maintype(obj) != maintype_: raise ValueError('type mismatch: {0} and {1}'.format(maintype(obj), maintype_)) kw.setdefault('controls', 'controls') media_element = getattr(HTML, maintype_)( literal('Your browser does not support the <code>{0}</code> element.'.format( maintype_)), HTML.source(src=bitstream_url(obj, type_='web'), type=mimetype(obj)), **kw) return HTML.div( media_element, HTML.br(), link(obj, label=label), class_='cdstar_{0}_link'.format(maintype_), style='margin-top: 10px')
def icons(req, param): """Create an HTML snippet listing available icons. :param req: current request :param param: parameter name :return: HTML element """ iconlist = req.registry.queryUtility(interfaces.IIconList) td = lambda icon: HTML.td(marker_img(icon.url(req)), onclick='CLLD.reload({"%s": "%s"})' % (param, icon.name)) rows = [ HTML.tr(*map(td, icons)) for c, icons in groupby(sorted(iconlist, key=lambda i: i.name[1:]), lambda i: i.name[1:]) ] return HTML.div( HTML.table(HTML.tbody(*rows), class_="table table-condensed"), button("Close", **{"data-dismiss": "clickover"}) )
def format_coordinates(obj, no_seconds=True, wgs_link=True): """ WGS84 53° 33' 2" N, 9° 59' 36" E 53.550556°, 9.993333° .. seealso:: http://en.wikipedia.org/wiki/ISO_6709#Order.2C_sign.2C_and_units """ def degminsec(dec, hemispheres): _dec = abs(dec) degrees = int(floor(_dec)) _dec = (_dec - int(floor(_dec))) * 60 minutes = int(floor(_dec)) _dec = (_dec - int(floor(_dec))) * 60 seconds = _dec if no_seconds: if seconds > 30: if minutes < 59: minutes += 1 else: minutes = 0 degrees += 1 fmt = "{0}\xb0" if minutes: fmt += "{1:0>2d}'" if not no_seconds and seconds: fmt += '{2:0>2f}"' fmt += hemispheres[0] if dec > 0 else hemispheres[1] return unicode(fmt).format(degrees, minutes, seconds) if not isinstance(obj.latitude, float) or not isinstance( obj.longitude, float): return '' return HTML.div( HTML.table(HTML.tr( HTML.td( 'Coordinates ', external_link( 'http://en.wikipedia.org/wiki/World_Geodetic_System_1984', label="WGS84") if wgs_link else ''), HTML.td( HTML.span('%s, %s' % (degminsec( obj.latitude, 'NS'), degminsec(obj.longitude, 'EW'))), HTML.br(), HTML.span('{0.latitude:.2f}, {0.longitude:.2f}'.format(obj), class_='geo'))), class_="table table-condensed"))
def icons(req, param): """Create an HTML snippet listing available icons. :param req: current request :param param: parameter name :return: HTML element """ iconlist = req.registry.queryUtility(interfaces.IIconList) td = lambda icon: HTML.td(marker_img(icon.url(req)), onclick='CLLD.reload({"%s": "%s"})' % (param, icon.name)) rows = [ HTML.tr(*map(td, icons)) for c, icons in groupby( sorted(iconlist, key=lambda i: i.name[1:]), lambda i: i.name[1:]) ] return HTML.div( HTML.table(HTML.tbody(*rows), class_="table table-condensed"), button('Close', **{'data-dismiss': 'clickover'}))
def icons(req, param): icon_map = req.registry.settings['icons'] print "yes" print icon_map td = lambda spec: HTML.td( HTML.img( src=req.static_url('clld:web/static/icons/' + icon_map[spec] + '.png'), ##src=req.static_url('lsi:static/icons/' + icon_map[spec] + '.png'), height='20', width='20'), onclick='LSI.reload({"%s": "%s"})' % (param, spec)) rows = [ HTML.tr(*map(td, icons)) for c, icons in groupby(sorted(icon_map.keys()), lambda spec: spec[0]) ] return HTML.div( HTML.table(HTML.tbody(*rows), class_="table table-condensed"), button('Close', **{'data-dismiss': 'clickover'}))
def video_detail(*objs, **kw): def video(mp4): return cdstar.video(mp4, width='100%', preload='none', **kw) mp4s, name, dl = [], None, [] if isinstance(objs[0], Movie): dl.extend([HTML.dt('Description'), HTML.dd(objs[0].name)]) dl.extend([HTML.dt('Duration'), HTML.dd(format_duration(objs[0]))]) if objs[0].get_file('mp4'): mp4s = [objs[0].get_file('mp4')] files = objs[0].files else: for obj in objs: if obj.mime_type == 'video/mp4': mp4s.append(obj) files = objs dl.extend([HTML.dt('Formats'), HTML.dd(format_videos(files))]) return HTML.div( HTML.ul(*[HTML.li(video(mp4)) for mp4 in mp4s], **dict(class_='unstyled')), HTML.dl(*dl))
def rendered_sentence(sentence, req, form=None): units = [] for i, (f, concept) in enumerate(sentence.iter_form_and_concept()): units.append(HTML.div( HTML.div( link(req, f, label=f.description) if f != form else f.description, class_='original-script'), HTML.div(f.name, class_='object-language'), HTML.div( link(req, concept, label=concept.french_gloss) if f != form else concept.french_gloss, ), class_='gloss-unit', )) return HTML.div( HTML.div( HTML.div( HTML.div(*units, **{'class': 'gloss-box'}) if units else '', class_='body', ), class_="sentence", ), class_="sentence-wrapper", )
def format(self, doculect): return HTML.div(map_marker_img(self.dt.req, doculect), ' ', doculect.subfamily)
def infobox(*content): return HTML.div( HTML.button( '\xd7', **{'type': "button", 'class': "close", 'data-dismiss': "alert"}), *content, **{'class': "alert alert-success"})
def format(self, item): return HTML.div( HTML.strong(LEGEND[item.color][0]), style="background-color: {}; text-align: center;".format( item.color))
def rendered_sentence(sentence, abbrs=None, fmt="long"): """Format a sentence as HTML.""" if sentence.xhtml: return HTML.div(HTML.div(Markup(sentence.xhtml), class_="body"), class_="sentence") if abbrs is None: q = DBSession.query(models.GlossAbbreviation).filter( or_( models.GlossAbbreviation.language_pk == sentence.language_pk, models.GlossAbbreviation.language_pk == None, ) ) abbrs = dict((g.id, g.name) for g in q) def gloss_with_tooltip(gloss): person_map = {"1": "first person", "2": "second person", "3": "third person"} res = [] end = 0 for match in GLOSS_ABBR_PATTERN.finditer(gloss): if match.start() > end: res.append(gloss[end : match.start()]) abbr = match.group("abbr") if abbr in abbrs: explanation = abbrs[abbr] if match.group("personprefix"): explanation = "%s %s" % (person_map[match.group("personprefix")], explanation) if match.group("personsuffix"): explanation = "%s %s" % (explanation, person_map[match.group("personsuffix")]) res.append( HTML.span( HTML.span(gloss[match.start() : match.end()].lower(), class_="sc"), **{"data-hint": explanation, "class": "hint--bottom"} ) ) else: res.append(abbr) end = match.end() res.append(gloss[end:]) return filter(None, res) def alt_translation(sentence): res = "" if sentence.jsondata.get("alt_translation"): text = sentence.jsondata["alt_translation"] name = "" if ALT_TRANSLATION_LANGUAGE_PATTERN.match(text): name, text = [t.strip() for t in text.split(":", 1)] name = HTML.span(name + ": ") res = HTML.div(name, HTML.span(text, class_="translation")) return res units = [] if sentence.analyzed and sentence.gloss: analyzed = sentence.analyzed glossed = sentence.gloss for morpheme, gloss in zip(analyzed.split("\t"), glossed.split("\t")): units.append( HTML.div( HTML.div(morpheme, class_="morpheme"), HTML.div(*gloss_with_tooltip(gloss), **{"class": "gloss"}), class_="gloss-unit", ) ) return HTML.p( HTML.div( HTML.div( HTML.div(sentence.original_script, class_="original-script") if sentence.original_script else "", HTML.div(literal(sentence.markup_text or sentence.name), class_="object-language"), HTML.div(*units, **{"class": "gloss-box"}) if units else "", HTML.div(sentence.description, class_="translation") if sentence.description else "", alt_translation(sentence), class_="body", ), class_="sentence", ), class_="sentence", )
def text2html(text, mode='br', sep='\n\n'): """Turn plain text into simple HTML.""" if mode == 'p': return HTML.div(*[HTML.p(literal(newline2br(line))) for line in text.split(sep)]) return HTML.p(literal(newline2br(text)))
def test_HTML(self): from clld.web.util.htmllib import HTML self.assertTrue('class' in HTML.div(HTML.cdata(), class_='abc')) self.assertEqual(str(HTML.a), '<a />')
def text2html(text, mode='br', sep='\n\n'): """Turn plain text into simple HTML.""" if mode == 'p': return HTML.div(*[HTML.p(literal(newline2br(line))) for line in text.split(sep)]) return HTML.p(literal(newline2br(text)))
def ipa_consonants(req, segments): # # a row_spec for a row in the segment chart is a pair (name, segment map), where # segment map maps column index to our internal segment number. # row_specs = [ ( 'plosive/affricate', {1: 1, 2: 5, 7: 7, 8: 9, 9: 24, 10: 80, 11: 25, 12: 27, 13: 11, 14: 12, 15: 13, 16: 14, 17: 2, 18: 17, 19: 75, 20: 76, 21: 18, 22: 19} ), ('aspirated plosive/affricate', {1: 4, 7: 8, 8: 6, 9: 79, 11: 26, 17: 16}), ( 'glottalized stop/affricate', {1: 20, 2: 23, 7: 21, 9: 81, 11: 28, 17: 22, 21: 78} ), ('nasal', {2: 42, 8: 43, 14: 44, 16: 45, 18: 46}), ('trill, tap or flap', {7: 47, 8: 48}), ( 'fricative', { 1: 29, 2: 30, 3: 31, 4: 32, 5: 82, 6: 33, 7: 34, 8: 35, 11: 36, 12: 37, 17: 38, 18: 39, 21: 40, 22: 41} ), ('lateral/approximant', {7: 85, 8: 49, 14: 50, 16: 51, 20: 52}), ] rows = [] for i, spec in enumerate(row_specs): # build the chart row by row name, segment_map = spec cells = [HTML.th(name, class_="row-header")] for j in range(22): if j + 1 in segment_map: title, symbol, class_, p, exists, vs = segments[segment_map[j + 1]] cells.append(HTML.td( parameter_link(req, symbol, vs or p), title=title, class_=class_)) else: cells.append(HTML.td()) rows.append(HTML.tr(*cells)) return HTML.table( HTML.thead( HTML.tr( HTML.td(''), HTML.th(HTML.div('bilabial', class_="vertical"), colspan="2"), HTML.th(HTML.div('labiodental', class_="vertical"), colspan="2"), HTML.th(HTML.div('dental', class_="vertical"), colspan="2"), HTML.th(HTML.div('dental/alveolar', class_="vertical"), colspan="2"), HTML.th( HTML.div( 'dental/alveolar', HTML.br(), 'affricate', class_="vertical"), colspan="2"), HTML.th(HTML.div('palato-alveolar', class_="vertical"), colspan="2"), HTML.th(HTML.div('retroflex', class_="vertical"), colspan="2"), HTML.th(HTML.div('palatal', class_="vertical"), colspan="2"), HTML.th(HTML.div('velar', class_="vertical"), colspan="2"), HTML.th(HTML.div('labial-velar', class_="vertical"), colspan="2"), HTML.th(HTML.div('uvular', class_="vertical")), HTML.th(HTML.div('glottal', class_="vertical")), ), ), HTML.tbody(*rows), style="margin-top: 5em;", )
def format_audio_file(req, file_): return HTML.div(HTML.audio(HTML.source(src=req.file_url(file_)))) if file_ else ''
def ipa_vowels(req, segments): segments[0] = ('separator', u'•', 'segment-separator', None, False, None) div_specs = [ # high (4, -29, 125, [87, 54, 53, 0, 55, 88]), (4, 135, 60, [62, 0]), (4, 264, 110, [66, 0, 67, 68, 93]), # lowered high (35, 80, 60, [56, 0]), (35, 221, 60, [0, 69]), # higher mid (71, 12, 90, [89, 58, 57, 0]), (71, 283, 90, [0, 70, 71, 94]), # mid (98, 182, 60, [63]), # lower mid (135, 55, 90, [90, 60, 59, 0]), (135, 282, 90, [0, 72, 86, 95]), # raised low (166, 96, 60, [91, 61, 0]), # low (198, 100, 90, [92, 65, 64, 0]), (198, 247, 60, [96, 73, 0]), ] divs = [ HTML.div(*[ HTML.span(parameter_link(req, symbol, vs or p), class_=class_, title=name) for name, symbol, class_, p, exists, vs in [segments[i] for i in content] ], style="top:%spx; left:%spx; width:%spx;" % (top, left, width), class_='segment-container') for top, left, width, content in div_specs ] def wm_url(path): return '//upload.wikimedia.org/wikipedia/commons/thumb/4/4f/'\ 'Blank_vowel_trapezoid.svg' + path diagram = HTML.div( HTML.img( height="224", width="320", alt="Blank vowel trapezoid.svg", src=wm_url("/320px-Blank_vowel_trapezoid.svg.png"), srcset=', '.join([ wm_url('/480px-Blank_vowel_trapezoid.svg.png 1.5x'), wm_url('/640px-Blank_vowel_trapezoid.svg.png 2x') ]), ), HTML.div( HTML.table( HTML.tbody(HTML.tr(HTML.td(*divs))), style= "position:relative; width:320px; height:224px; text-align:center; " "background:transparent; font-size:131%;", ), style= "background:transparent; position:absolute; top:0px; left:0px;", ), style="position:relative;", ) return HTML.table( HTML.tbody( HTML.tr( HTML.td(' '), HTML.td(HTML.span( 'front', style="position:relative; left:-0.4em; font-weight: bold;" ), style="width:64px;"), HTML.td('near-front', style="width:62px; font-weight: bold;"), HTML.td('central', style="width:64px; font-weight: bold;"), HTML.td('near-back', style="width:62px; font-weight: bold;"), HTML.td('back', style="width:64px; font-weight: bold;"), style="text-align: center;", ), HTML.tr( HTML.td( 'high', style="height:32px; text-align:right; font-weight: bold;"), HTML.td(diagram, style="height:210px; padding-left: 30px;", colspan="5", rowspan="7"), ), HTML.tr(HTML.td('', style="height:32px; text-align:right;")), HTML.tr( HTML. td('higher-mid', style="height:32px; text-align:right; font-weight: bold;")), HTML.tr( HTML. td('mid', style="height:32px; text-align:right; font-weight: bold;")), HTML.tr( HTML. td('lower-mid', style="height:32px; text-align:right; font-weight: bold;")), HTML.tr(HTML.td('', style="height:32px; text-align:right;")), HTML.tr( HTML. td('low', style="height:32px; text-align:right; font-weight: bold;")), ), style= "line-height:1.4em; background:transparent; margin:0em auto 0em auto;", cellspacing="0")
def ipa_consonants(req, segments): # # a row_spec for a row in the segment chart is a pair (name, segment map), where # segment map maps column index to our internal segment number. # row_specs = [ ('plosive/affricate', { 1: 1, 2: 5, 7: 7, 8: 9, 9: 24, 10: 80, 11: 25, 12: 27, 13: 11, 14: 12, 15: 13, 16: 14, 17: 2, 18: 17, 19: 75, 20: 76, 21: 18, 22: 19 }), ('aspirated plosive/affricate', { 1: 4, 7: 8, 8: 6, 9: 79, 11: 26, 17: 16 }), ('glottalized stop/affricate', { 1: 20, 2: 23, 7: 21, 9: 81, 11: 28, 17: 22, 21: 78 }), ('nasal', { 2: 42, 8: 43, 14: 44, 16: 45, 18: 46 }), ('trill, tap or flap', { 7: 47, 8: 48 }), ('fricative', { 1: 29, 2: 30, 3: 31, 4: 32, 5: 82, 6: 33, 7: 34, 8: 35, 11: 36, 12: 37, 17: 38, 18: 39, 21: 40, 22: 41 }), ('lateral/approximant', { 7: 85, 8: 49, 14: 50, 16: 51, 20: 52 }), ] rows = [] for i, spec in enumerate(row_specs): # build the chart row by row name, segment_map = spec cells = [HTML.th(name, class_="row-header")] for j in range(22): if j + 1 in segment_map: title, symbol, class_, p, exists, vs = segments[segment_map[j + 1]] cells.append( HTML.td(parameter_link(req, symbol, vs or p), title=title, class_=class_)) else: cells.append(HTML.td()) rows.append(HTML.tr(*cells)) return HTML.table( HTML.thead( HTML.tr( HTML.td(''), HTML.th(HTML.div('bilabial', class_="vertical"), colspan="2"), HTML.th(HTML.div('labiodental', class_="vertical"), colspan="2"), HTML.th(HTML.div('dental', class_="vertical"), colspan="2"), HTML.th(HTML.div('dental/alveolar', class_="vertical"), colspan="2"), HTML.th(HTML.div('dental/alveolar', HTML.br(), 'affricate', class_="vertical"), colspan="2"), HTML.th(HTML.div('palato-alveolar', class_="vertical"), colspan="2"), HTML.th(HTML.div('retroflex', class_="vertical"), colspan="2"), HTML.th(HTML.div('palatal', class_="vertical"), colspan="2"), HTML.th(HTML.div('velar', class_="vertical"), colspan="2"), HTML.th(HTML.div('labial-velar', class_="vertical"), colspan="2"), HTML.th(HTML.div('uvular', class_="vertical")), HTML.th(HTML.div('glottal', class_="vertical")), ), ), HTML.tbody(*rows), style="margin-top: 5em;", )
def format(self, item): return HTML.div( link(self.dt.req, item.dictionary), #' by ', #linked_contributors(self.dt.req, item.valueset.contribution) )
def rendered_sentence(sentence, abbrs=None, fmt='long'): """Format a sentence as HTML.""" if sentence.xhtml: return HTML.div( HTML.div(Markup(sentence.xhtml), class_='body'), class_="sentence") if abbrs is None: q = DBSession.query(models.GlossAbbreviation).filter( or_(models.GlossAbbreviation.language_pk == sentence.language_pk, models.GlossAbbreviation.language_pk == None) ) abbrs = dict((g.id, g.name) for g in q) def gloss_with_tooltip(gloss): person_map = { '1': 'first person', '2': 'second person', '3': 'third person', } res = [] end = 0 for match in GLOSS_ABBR_PATTERN.finditer(gloss): if match.start() > end: res.append(gloss[end:match.start()]) abbr = match.group('abbr') if abbr in abbrs: explanation = abbrs[abbr] if match.group('personprefix'): explanation = '%s %s' % ( person_map[match.group('personprefix')], explanation) if match.group('personsuffix'): explanation = '%s %s' % ( explanation, person_map[match.group('personsuffix')]) res.append(HTML.span( HTML.span(gloss[match.start():match.end()].lower(), class_='sc'), **{'data-hint': explanation, 'class': 'hint--bottom'})) else: res.append(abbr) end = match.end() res.append(gloss[end:]) return filter(None, res) def alt_translation(sentence): res = '' if sentence.jsondata.get('alt_translation'): text = sentence.jsondata['alt_translation'] name = '' if ALT_TRANSLATION_LANGUAGE_PATTERN.match(text): name, text = [t.strip() for t in text.split(':', 1)] name = HTML.span(name + ': ') res = HTML.div(name, HTML.span(text, class_='translation')) return res units = [] if sentence.analyzed and sentence.gloss: analyzed = sentence.analyzed glossed = sentence.gloss for morpheme, gloss in zip(analyzed.split('\t'), glossed.split('\t')): units.append(HTML.div( HTML.div(morpheme, class_='morpheme'), HTML.div(*gloss_with_tooltip(gloss), **{'class': 'gloss'}), class_='gloss-unit')) return HTML.div( HTML.div( HTML.div( HTML.div(sentence.original_script, class_='original-script') if sentence.original_script else '', HTML.div(literal(sentence.markup_text or sentence.name), class_='object-language'), HTML.div(*units, **{'class': 'gloss-box'}) if units else '', HTML.div(sentence.description, class_='translation') if sentence.description else '', alt_translation(sentence), class_='body', ), class_="sentence", ), class_="sentence-wrapper", )
def rendered_sentence(sentence, abbrs=None, fmt='long'): """Format a sentence as HTML.""" if sentence.xhtml: return HTML.div( HTML.div(Markup(sentence.xhtml), class_='body'), class_="sentence") if abbrs is None: q = DBSession.query(models.GlossAbbreviation).filter( or_(models.GlossAbbreviation.language_pk == sentence.language_pk, models.GlossAbbreviation.language_pk == None) ) abbrs = dict((g.id, g.name) for g in q) def gloss_with_tooltip(gloss): person_map = { '1': 'first person', '2': 'second person', '3': 'third person', } res = [] end = 0 for match in GLOSS_ABBR_PATTERN.finditer(gloss): if match.start() > end: res.append(gloss[end:match.start()]) abbr = match.group('abbr') if abbr in abbrs: explanation = abbrs[abbr] if match.group('personprefix'): explanation = '%s %s' % ( person_map[match.group('personprefix')], explanation) if match.group('personsuffix'): explanation = '%s %s' % ( explanation, person_map[match.group('personsuffix')]) res.append(HTML.span( HTML.span(gloss[match.start():match.end()].lower(), class_='sc'), **{'data-hint': explanation, 'class': 'hint--bottom'})) else: res.append(abbr) end = match.end() res.append(gloss[end:]) return filter(None, res) def alt_translation(sentence): res = '' if sentence.jsondata.get('alt_translation'): text = sentence.jsondata['alt_translation'] name = '' if ALT_TRANSLATION_LANGUAGE_PATTERN.match(text): name, text = [t.strip() for t in text.split(':', 1)] name = HTML.span(name + ': ') res = HTML.div(name, HTML.span(text, class_='translation')) return res units = [] if sentence.analyzed and sentence.gloss: analyzed = sentence.analyzed glossed = sentence.gloss for morpheme, gloss in zip(analyzed.split('\t'), glossed.split('\t')): units.append(HTML.div( HTML.div(morpheme, class_='morpheme'), HTML.div(*gloss_with_tooltip(gloss), **{'class': 'gloss'}), class_='gloss-unit')) return HTML.div( HTML.div( HTML.div( HTML.div(sentence.original_script, class_='original-script') if sentence.original_script else '', HTML.div(literal(sentence.markup_text or sentence.name), class_='object-language'), HTML.div(*units, **{'class': 'gloss-box'}) if units else '', HTML.div(sentence.description, class_='translation') if sentence.description else '', alt_translation(sentence), class_='body', ), class_="sentence", ), class_="sentence-wrapper", )
def ipa_vowels(req, segments): segments[0] = ('separator', u'•', 'segment-separator', None, False, None) div_specs = [ # high (4, -29, 125, [87, 54, 53, 0, 55, 88]), (4, 135, 60, [62, 0]), (4, 264, 110, [66, 0, 67, 68, 93]), # lowered high (35, 80, 60, [56, 0]), (35, 221, 60, [0, 69]), # higher mid (71, 12, 90, [89, 58, 57, 0]), (71, 283, 90, [0, 70, 71, 94]), # mid (98, 182, 60, [63]), # lower mid (135, 55, 90, [90, 60, 59, 0]), (135, 282, 90, [0, 72, 86, 95]), # raised low (166, 96, 60, [91, 61, 0]), # low (198, 100, 90, [92, 65, 64, 0]), (198, 247, 60, [96, 73, 0]), ] divs = [ HTML.div( *[HTML.span(parameter_link(req, symbol, vs or p), class_=class_, title=name) for name, symbol, class_, p, exists, vs in [segments[i] for i in content]], style="top:%spx; left:%spx; width:%spx;" % (top, left, width), class_='segment-container') for top, left, width, content in div_specs] def wm_url(path): return '//upload.wikimedia.org/wikipedia/commons/thumb/4/4f/'\ 'Blank_vowel_trapezoid.svg' + path diagram = HTML.div( HTML.img( height="224", width="320", alt="Blank vowel trapezoid.svg", src=wm_url("/320px-Blank_vowel_trapezoid.svg.png"), srcset=', '.join([ wm_url('/480px-Blank_vowel_trapezoid.svg.png 1.5x'), wm_url('/640px-Blank_vowel_trapezoid.svg.png 2x')]), ), HTML.div( HTML.table( HTML.tbody(HTML.tr(HTML.td(*divs))), style="position:relative; width:320px; height:224px; text-align:center; " "background:transparent; font-size:131%;", ), style="background:transparent; position:absolute; top:0px; left:0px;", ), style="position:relative;", ) return HTML.table( HTML.tbody( HTML.tr( HTML.td(' '), HTML.td( HTML.span( 'front', style="position:relative; left:-0.4em; font-weight: bold;"), style="width:64px;"), HTML.td( 'near-front', style="width:62px; font-weight: bold;"), HTML.td( 'central', style="width:64px; font-weight: bold;"), HTML.td( 'near-back', style="width:62px; font-weight: bold;"), HTML.td( 'back', style="width:64px; font-weight: bold;"), style="text-align: center;", ), HTML.tr( HTML.td( 'high', style="height:32px; text-align:right; font-weight: bold;"), HTML.td( diagram, style="height:210px; padding-left: 30px;", colspan="5", rowspan="7"), ), HTML.tr(HTML.td('', style="height:32px; text-align:right;")), HTML.tr(HTML.td( 'higher-mid', style="height:32px; text-align:right; font-weight: bold;")), HTML.tr(HTML.td( 'mid', style="height:32px; text-align:right; font-weight: bold;")), HTML.tr(HTML.td( 'lower-mid', style="height:32px; text-align:right; font-weight: bold;")), HTML.tr(HTML.td('', style="height:32px; text-align:right;")), HTML.tr(HTML.td( 'low', style="height:32px; text-align:right; font-weight: bold;")), ), style="line-height:1.4em; background:transparent; margin:0em auto 0em auto;", cellspacing="0")
def rendered_sentence(sentence, abbrs=None, fmt='long'): if sentence.xhtml: return HTML.div( HTML.div(Markup(sentence.xhtml), class_='body'), class_="sentence") if abbrs is None: q = DBSession.query(models.GlossAbbreviation).filter( or_(models.GlossAbbreviation.language_pk == sentence.language_pk, models.GlossAbbreviation.language_pk == None) ) abbrs = dict((g.id, g.name) for g in q) def gloss_with_tooltip(gloss): person_map = { '1': 'first person', '2': 'second person', '3': 'third person', } res = [] end = 0 for match in GLOSS_ABBR_PATTERN.finditer(gloss): if match.start() > end: res.append(literal(gloss[end:match.start()])) abbr = match.group('abbr') if abbr in abbrs: explanation = abbrs[abbr] if match.group('personprefix'): explanation = '%s %s' % ( person_map[match.group('personprefix')], explanation) if match.group('personsuffix'): explanation = '%s %s' % ( explanation, person_map[match.group('personsuffix')]) res.append(HTML.span( HTML.span(gloss[match.start():match.end()].lower(), class_='sc'), **{'data-hint': explanation, 'class': 'hint--bottom'})) else: res.append(abbr) end = match.end() res.append(literal(gloss[end:])) return filter(None, res) units = [] if sentence.analyzed and sentence.gloss: analyzed = sentence.analyzed glossed = sentence.gloss for morpheme, gloss in zip(analyzed.split('\t'), glossed.split('\t')): units.append(HTML.div( HTML.div(literal(morpheme), class_='morpheme'), HTML.div(*gloss_with_tooltip(gloss), **{'class': 'gloss'}), class_='gloss-unit')) return HTML.p( HTML.div( HTML.div( HTML.div(literal(sentence.markup_text or sentence.name), class_='object-language'), HTML.div(*units, **{'class': 'gloss-box'}) if units else '', HTML.div(sentence.description, class_='translation') if sentence.description else '', HTML.div(sentence.original_script, class_='original_script') if sentence.original_script else '', #HTML.small(literal(sentence.comment)) if sentence.comment and fmt == 'long' else '', class_='body', ), class_="sentence", ), class_="sentence", )
def rendered_sentence(sentence, abbrs=None, fmt='long'): if sentence.xhtml: return HTML.div(HTML.div(Markup(sentence.xhtml), class_='body'), class_="sentence") if abbrs is None: q = DBSession.query(models.GlossAbbreviation).filter( or_(models.GlossAbbreviation.language_pk == sentence.language_pk, models.GlossAbbreviation.language_pk == None)) abbrs = dict((g.id, g.name) for g in q) def gloss_with_tooltip(gloss): person_map = { '1': 'first person', '2': 'second person', '3': 'third person', } res = [] end = 0 for match in GLOSS_ABBR_PATTERN.finditer(gloss): if match.start() > end: res.append(literal(gloss[end:match.start()])) abbr = match.group('abbr') if abbr in abbrs: explanation = abbrs[abbr] if match.group('personprefix'): explanation = '%s %s' % ( person_map[match.group('personprefix')], explanation) if match.group('personsuffix'): explanation = '%s %s' % ( explanation, person_map[match.group('personsuffix')]) res.append( HTML.span( HTML.span(gloss[match.start():match.end()].lower(), class_='sc'), **{ 'data-hint': explanation, 'class': 'hint--bottom' })) else: res.append(abbr) end = match.end() res.append(literal(gloss[end:])) return filter(None, res) units = [] if sentence.analyzed and sentence.gloss: analyzed = sentence.analyzed glossed = sentence.gloss for morpheme, gloss in zip(analyzed.split('\t'), glossed.split('\t')): units.append( HTML.div(HTML.div(literal(morpheme), class_='morpheme'), HTML.div(*gloss_with_tooltip(gloss), **{'class': 'gloss'}), class_='gloss-unit')) return HTML.p( HTML.div( HTML.div( HTML.div(literal(sentence.markup_text or sentence.name), class_='object-language'), HTML.div(*units, **{'class': 'gloss-box'}) if units else '', HTML.div(sentence.description, class_='translation') if sentence.description else '', HTML.div(sentence.original_script, class_='original_script') if sentence.original_script else '', #HTML.small(literal(sentence.comment)) if sentence.comment and fmt == 'long' else '', class_='body', ), class_="sentence", ), class_="sentence", )
def collapsed(id_, content, button_content=None): return HTML.div( HTML.p(HTML.a( button_content or icon('plus-sign'), **{'class': 'btn', 'data-toggle': 'collapse', 'data-target': '#%s' % id_})), HTML.div(content, id=id_, class_='collapse'))
def format(self, item): obj = self.get_obj(item) return HTML.div(map_marker_img(self.dt.req, obj), ' {}'.format(obj.canton))
def item(lang, label): return HTML.div(map_marker_img(self.req, lang), ' ', label, style="padding-left: 5px")
def test_HTML(): from clld.web.util.htmllib import HTML assert 'class' in HTML.div(HTML.cdata(), class_='abc') assert str(HTML.a()) == '<a></a>'