1# vim:fileencoding=utf-8 2# License: GPL v3 Copyright: 2016, Kovid Goyal <kovid at kovidgoyal.net> 3from __python__ import hash_literals, bound_methods 4 5from dom import clear, set_css, build_rule 6from elementmaker import E 7from gettext import gettext as _ 8 9 10COVER_GRID_CLASS = 'book-list-cover-grid' 11THUMBNAIL_MAX_WIDTH = 3 * 100 12THUMBNAIL_MAX_HEIGHT = 4 * 100 13THUMBNAIL_MIN_WIDTH = 3 * 35 14THUMBNAIL_MIN_HEIGHT = 4 * 35 15BORDER_RADIUS = 10 16 17 18def description(): 19 return _('A grid of book covers') 20 21 22def cover_grid_css(): 23 sel = '.' + COVER_GRID_CLASS 24 margin, margin_unit = 10, 'px' 25 ans = build_rule(sel, display='flex', flex_wrap='wrap', justify_content='space-around', align_items='flex-end', 26 align_content='flex-start', user_select='none', overflow='hidden', margin_top=f'{margin / 2}{margin_unit}') 27 28 # Container for an individual cover 29 sel += ' > a' 30 ans += build_rule( 31 sel, margin=f'{margin}{margin_unit}', display='flex', align_content='flex-end', align_items='center', justify_content='space-around', 32 max_width=THUMBNAIL_MAX_WIDTH+'px', max_height=THUMBNAIL_MAX_HEIGHT+'px', cursor='pointer', 33 min_width=THUMBNAIL_MIN_WIDTH+'px', min_height=THUMBNAIL_MIN_HEIGHT + 'px') 34 mq = '@media all and (orientation: {orient}) {{ {sel} {{ width: 21{dim}; height: 28{dim} }} }}\n' 35 for dim in 'vw', 'vh': 36 ans += mq.format(sel=sel, dim=dim, orient='portrait' if dim is 'vw' else 'landscape') 37 ans += build_rule(f'{sel}:hover', transform='scale(1.2)') 38 ans += build_rule(f'{sel}:active', transform='scale(2)') 39 ans += build_rule(sel + '.cover-grid-filler', height='0', max_height='0', min_height='0') 40 41 # Container for cover failed to load message 42 ans += build_rule(sel + ' > div', position='relative', top='-50%', transform='translateY(50%)', margin='0') 43 44 # The actual cover 45 sel += ' > img' 46 ans += build_rule(sel, max_width='100%', max_height='100%', display='block', width='auto', height='auto', border_radius=BORDER_RADIUS+'px') 47 return ans 48 49def init(container): 50 clear(container) 51 container.appendChild(E.div(class_=COVER_GRID_CLASS)) 52 for i in range(12): 53 container.lastChild.appendChild(E.div(class_='cover-grid-filler')) 54 55def on_img_load(img, load_type): 56 div = img.parentNode 57 if not div: 58 return 59 if load_type is not 'load': 60 clear(div) 61 div.appendChild(E.div( 62 E.h2(img.dataset.title, style='text-align:center; font-size:larger; font-weight: bold'), 63 E.div(_('by'), style='text-align: center'), 64 E.h2(img.dataset.authors, style='text-align:center; font-size:larger; font-weight: bold') 65 )) 66 set_css(div, border='dashed 1px currentColor', border_radius=BORDER_RADIUS+'px') 67 68def create_item(book_id, metadata, create_image, show_book_details, href): 69 authors = metadata.authors.join(' & ') if metadata.authors else _('Unknown') 70 img = create_image(book_id, THUMBNAIL_MAX_WIDTH, THUMBNAIL_MAX_HEIGHT, on_img_load) 71 tooltip = _('{} by {}').format(metadata.title, authors) 72 img.setAttribute('alt', tooltip) 73 img.dataset.title, img.dataset.authors = metadata.title, authors 74 ans = E.a(img, onclick=show_book_details, title=tooltip, href=href) 75 return ans 76 77def append_item(container, item): 78 first_filler = container.lastChild.querySelector('.cover-grid-filler') 79 container.lastChild.insertBefore(item, first_filler) 80