# vim:fileencoding=utf-8 # License: GPL v3 Copyright: 2015, Kovid Goyal from elementmaker import E from dom import set_css, clear, build_rule from gettext import gettext as _ from book_list.theme import get_color, get_font_size modal_container = None class ModalContainer: def __init__(self): div = E.div(id='modal-container', E.div( # popup E.div(), # content area E.a(E.i(class_='fa fa-close', style='vertical-align:bottom;'), title=_('Close')) ), E.style( build_rule( '#modal-container > div > a:hover', color=get_color('dialog-foreground') + ' !important', background_color=get_color('dialog-background') + ' !important' ) + build_rule( '#modal-container a.dialog-simple-link:hover', color='red !important' ) ) ) document.body.appendChild(div) # Container style set_css(div, position='fixed', top='0', right='0', bottom='0', left='0', # Stretch over entire window background_color='rgba(0,0,0,0.8)', z_index='1000', display='none', text_align='center', user_select='none' ) # Popup style set_css(div.firstChild, position='relative', display='inline-block', top='50vh', transform='translateY(-50%)', min_width='25vw', max_width='75vw', border_radius='1em', padding='1em 2em', margin_right='1em', margin_left='1em', background=get_color('dialog-background'), color=get_color('dialog-foreground'), background_image=get_color('dialog-background-image'), get_color('dialog-background'), get_color('dialog-background2') ) # Close button style set_css(div.firstChild.lastChild, font_size='1.5em', line_height='100%', cursor='pointer', position='absolute', right='-0.5em', top='-0.5em', width='1em', height='1em', background_color=get_color('window-foreground'), color=get_color('window-background'), display='inline-box', border_radius='50%', padding='4px', text_align='center', box_shadow='1px 1px 3px black' ) div.firstChild.lastChild.addEventListener('click', def(event): event.preventDefault(), self.close_modal(event);) # Content container style set_css(div.firstChild.firstChild, user_select='text', max_height='60vh', overflow='auto') self.modals = v'[]' self.current_modal = None self.hide = self.close_modal.bind(self) @property def modal_container(self): return document.getElementById('modal-container') def show_modal(self, create_func, on_close=None): self.modals.push(v'[create_func, on_close]') self.update() def update(self): if self.current_modal is None and self.modals: self.current_modal = self.modals.shift() c = self.modal_container try: self.current_modal[0](c.firstChild.firstChild, self.hide) except: self.current_modal = None raise if c.style.display == 'none': set_css(c, display='block') def close_modal(self, event): if self.current_modal is not None: if self.current_modal[1] is not None and self.current_modal[1](event) is True: return self.current_modal = None c = self.modal_container clear(c.firstChild.firstChild) if self.modals.length == 0: set_css(c, display='none') else: self.update() def create_simple_dialog(title, msg, details, icon_name, prefix): details = details or '' def create_func(parent): show_details = E.a(class_='dialog-simple-link', style='cursor:pointer; color: blue; padding-top:1em; display:inline-block; margin-left: auto', _('Show details')) show_details.addEventListener('click', def(): show_details.style.display = 'none' show_details.nextSibling.style.display = 'block' ) is_html_msg = /<[a-zA-Z]/.test(msg) html_container = E.div() if is_html_msg: html_container.innerHTML = msg parent.appendChild( E.div( style='max-width:60em; text-align: left', E.h2( E.i(class_='fa fa-lg fa-' + icon_name, style='color:red'), E.span('\xa0' + prefix + '\xa0', style='font-variant:small-caps'), title, style='font-weight: bold; font-size: ' + get_font_size('title') ), E.div((html_container if is_html_msg else msg), style='padding-top: 1em; margin-top: 1em; border-top: 1px solid currentColor'), E.div(style='display: ' + ('block' if details else 'none'), show_details, E.div(details, style='display:none; white-space:pre-wrap; font-size: smaller; margin-top: 1em; border-top: solid 1px currentColor; padding-top: 1em' ) ) ) ) show_modal(create_func) def error_dialog(title, msg, details=None): create_simple_dialog(title, msg, details, 'bug', _('Error:')) def warning_dialog(title, msg, details=None): create_simple_dialog(title, msg, details, 'warning', _('Warning:')) # def test_error(): # error_dialog( # 'Hello, world!', # 'Some long text to test rendering/line breaking in error dialogs that contain lots of text like this test error dialog from hell in a handbasket with fruits and muppets making a scene.', # ['a word ' for i in range(10000)].join(' ') # ) def create_modal_container(): nonlocal modal_container if modal_container is None: modal_container = ModalContainer() # window.setTimeout(def(): # document.getElementById('books-view-1').addEventListener('click', test_error) # , 10) return modal_container def show_modal(create_func, on_close=None): modal_container.show_modal(create_func, on_close)