def gen_checkbox(self, checked, cls): nm = self.gensym("chk") attrs = { "style": "display: none" } # Most RSS readers ignore stylesheets if checked: attrs["checked"] = "checked" tags.input_(type="checkbox", id=nm, cls=cls, **attrs) return nm
def new_user(form, ws_url, errors=None): title = 'New User' d = _doc(title) with d: with t.form(action=form.action, method='post'): with t.fieldset(): t.legend(title) _errors(errors) with t.ol(cls='step_numbers'): with t.li(): t.p('First, create a one-word username for yourself (lowercase, no spaces)...' ) _text_input( *form.nv('new_username'), ('required', 'autofocus'), { 'pattern': valid.re_username, 'oninput': 'check_username(this.value)' }, 'Type new username here', _invalid(valid.inv_username, form.invalid('new_username'))) _invalid(valid.inv_username_exists, False, 'username_exists_message') with t.li(): t.p("Next, invent a password; type it in twice to make sure you've got it..." ) _text_input('password', None, ('required', ), {'pattern': valid.re_password}, 'Type new password here', _invalid(valid.inv_password, form.invalid('password')), type_='password') _text_input('password_confirmation', None, ('required', ), None, 'Type password again for confirmation', _invalid( valid.inv_password_confirmation, form.invalid('password_confirmation'), 'password_match_message'), type_='password') with t.li(): t.p("Finally, type in an email address that can be used if you ever need a password reset (optional, but this may be very useful someday!)..." ) _text_input( *form.nv('email'), None, {'pattern': valid.re_email}, 'Type email address here', _invalid(valid.inv_email, form.invalid('email'))) t.input_(type="submit", value="Done!") t.script(_js_validate_new_user_fields()) t.script(_js_check_username(ws_url)) return d.render()
def _text_input(name, value, bool_attrs=None, attrs=None, label=None, invalid_div=None, type_='text', internal_label=True): ''' The 'name' string is expected to be a lowercase alphanumeric "variable name" without spaces. Use underscores ('_') to separate words for a mult-word name. `label` will be calculated as name.replace('_', ' ').title() unless `label` exists. Set `type_` to 'password' for a password input field. ''' if not label: label = name.replace('_', ' ').title() attrs = _combine_attrs(attrs, bool_attrs) i = t.input_(name=name, id=name, type=type_, **attrs) if value: i['value'] = value if internal_label: i['placeholder'] = label result = t.label(i) else: result = t.label(label + ':', i) if invalid_div: result += invalid_div return result
def _text_input(name, value, bool_attrs=None, attrs=None, label=None, error_message=None, type_='text', internal_label=True): ''' `name_value` is a 2-tuple (usually, *Form.nv('my-field-name') will be convenient) The 'name' string (first in the 2-tuple) is expected to be a lowercase alphanumeric "variable name" without spaces. Use underscores ('_') to separate words for a mult-word name. `label` will be calculated as name.replace('_', ' ').title() unless `label` exists. Set `type_` to 'password' for a password input field. ''' if not label: label = name.replace('_', ' ').title() attrs = _combine_attrs(attrs, bool_attrs) i = t.input_(name=name, type=type_, **attrs) if value: i['value'] = value if internal_label: i['placeholder'] = label result = t.label(i) else: result = t.label(label + ':', i) if error_message: result += _error(error_message) return result
def visit_BooleanField(self, node): wrap = self._get_wrap(node, classes='checkbox') label = wrap.add(tags.label(_for=node.id)) label.add(tags.input_(type='checkbox')) label.add(node.label.text) return wrap
def _wrapped_input(self, node, type='text', classes=['form-control'], **kwargs): wrap = self._get_wrap(node) wrap.add(tags.label(node.label.text, _for=node.id)) wrap.add(tags.input_(type=type, _class=' '.join(classes), **kwargs)) return wrap
def html(self): attributes = { "id": self.id, "type": self.type, } self.add_css_class(attributes) if self.placeholder is not None: attributes["placeholder"] = self.placeholder return input_(**attributes)
def login(action, error=None): d = _doc('OHS-Test Login') with d: with t.form(action=action, method='post'): with t.fieldset(cls='small_fieldset'): t.legend('Log in...') _error(error) t.div(_text_input('username', None, ('required', 'autofocus'), {'pattern': valid.re_username}, invalid_div=_invalid(valid.inv_username, False)), cls='field') t.div(_text_input('password', None, ('required', ), type_='password'), cls='field') t.div(t.input_(type="submit", value="Log in!"), cls='field') t.script(_js_validate_login_fields()) return d.render()
def make_region_html(region, args): """Write region-specific HTML page.""" latest = max( m.frame.index.max() for m in region.metrics["covid"].values() if m.emphasis >= 0 ) doc = dominate.document(title=f"{region.name} COVID-19 ({latest.date()})") doc_url = urls.region_page(region) def doc_link(url): return urls.link(doc_url, url) with doc.head: style.add_head_style(doc_url) with doc.body: tags.attr(id="map_key_target", tabindex="-1") with tags.h1(): def write_breadcrumbs(r): if r is not None: write_breadcrumbs(r.parent) tags.a(r.short_name, href=doc_link(urls.region_page(r))) util.text(" » ") write_breadcrumbs(region.parent) util.text(region.name) with tags.div(): pop = region.totals["population"] vax = region.totals.get("vaccinated", 0) pos = region.totals.get("positives", 0) dead = region.totals.get("deaths", 0) nobreak = lambda t: tags.span(t, cls="nobreak") nobreak(f"{pop:,.0f} pop; ") if vax: nobreak(f"{vax:,.0f} ({100 * vax / pop:.2g}%) vacc, ") nobreak(f"{pos:,.0f} ({100 * pos / pop:.2g}%) pos, ") nobreak(f"{dead:,.0f} ({100 * dead / pop:.2g}%) deaths ") nobreak(f"as of {latest.date()}") if urls.has_map(region): with tags.div(cls="graphic"): with tags.video(id="map", preload="auto"): href = urls.link(doc_url, urls.map_video_maybe(region)) tags.source(type="video/webm", src=f"{href}#t=1000") with tags.div(cls="map_controls"): def i(n): return tags.i(cls=f"fas fa-{n}") tags.button(i("pause"), " ", i("play"), " P", id="map_play") tags.button(i("repeat"), " L", id="map_loop") tags.button(i("backward"), " R", id="map_rewind") tags.button(i("step-backward"), " [", id="map_prev") tags.input_(type="range", id="map_slider") tags.button(i("step-forward"), " ]", id="map_next") tags.button(i("forward"), " F", id="map_forward") tags.img(cls="graphic", src=doc_link(urls.chart_image(region))) notables = [p for p in region.policy_changes if p.score] if notables: tags.h2( tags.span("Closing", cls="policy_close"), " and ", tags.span("Reopening", cls="policy_open"), " policy changes", ) with tags.div(cls="policies"): last_date = None for p in notables: date, s = str(p.date.date()), p.score if date != last_date: tags.div(date, cls=f"date") last_date = date tags.div(p.emoji, cls=f"emoji") tags.div( p.text, cls="text" + (" policy_close" if s < 0 else "") + (" policy_open" if s > 0 else "") + (" policy_major" if abs(s) >= 2 else ""), ) subs = [ r for r in region.subregions.values() if r.matches_regex(args.region_regex) ] if subs: sub_pop = sum(s.totals["population"] for s in subs) if len(subs) >= 10 and sub_pop > 0.9 * region.totals["population"]: def pop(r): return r.totals.get("population", 0) def pos(r): m = r.metrics["covid"].get("COVID positives / day / 100Kp") return m.frame.value.iloc[-1] * pop(r) if m else 0 tags.h2("Top 5 by population") for s in list(sorted(subs, key=pop, reverse=True))[:5]: make_subregion_html(doc_url, s) tags.h2("Top 5 by new positives") for s in list(sorted(subs, key=pos, reverse=True))[:5]: make_subregion_html(doc_url, s) tags.h2(f'All {"divisions" if region.parent else "countries"}') else: tags.h2("Subdivisions") for s in sorted(subs, key=lambda r: r.name): make_subregion_html(doc_url, s) r = region credits = dict(c for p in r.policy_changes for c in p.credits.items()) for ms in r.metrics.values(): credits.update(c for m in ms.values() for c in m.credits.items()) with tags.p("Sources: ", cls="credits"): for i, (url, text) in enumerate(credits.items()): util.text(", ") if i > 0 else None tags.a(text, href=url) with open(urls.file(args.site_dir, doc_url), "w") as doc_file: doc_file.write(doc.render())