From 8f82dc37138053327bb3244c362328e49d0c6cf0 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Thu, 14 Oct 2010 15:56:38 -0600 Subject: [PATCH 01/19] Orsai by DM. Fixes #7176 (New recipe for famous blog in Spanish - Orsai) --- resources/images/news/orsai.png | Bin 0 -> 684 bytes resources/recipes/orsai.recipe | 37 ++++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+) create mode 100644 resources/images/news/orsai.png create mode 100644 resources/recipes/orsai.recipe diff --git a/resources/images/news/orsai.png b/resources/images/news/orsai.png new file mode 100644 index 0000000000000000000000000000000000000000..e65f02206c19fed25f1632ff43531bd8609df8e6 GIT binary patch literal 684 zcmV;d0#p5oP)=e}8EFYAp^0E59e7=nZX1&9IxDN=+c zX{hKBk?4|$f|8DObkr27k}8UnKY%U>2^tIW(NKVGA+XrUVEncF-kcQkO!A6(Q`|Ya z_nhCAvyCX90cA{pLCQb?8FE16wk|+5kO-7%0NbDp4n%ou0+X=?LHQF!!xb13Kn0+N zxH*rzePTEP-2uOTKgX4?`u{bj1_+Fhgo|9ONW#5o4xBv7zT;Em-E&<1eSyCgmrG~c zH5QTq5RfQ$B%o1ubG z>WtCx7?W;zI2f|OT12Vwf*L3@rOKFgHnj+EhZTlwL|x!> zA|!(nI9QlB|J>VFFGox5C+8gn;BA&=+n-u;F+~4gYd~(w%DHSZ)F_K4D*gqvYY`M! Sit~H`0000 Date: Thu, 14 Oct 2010 15:59:54 -0600 Subject: [PATCH 02/19] ... --- resources/content_server/browse/browse.css | 11 ++ src/calibre/library/server/browse.py | 164 ++++++++++++--------- 2 files changed, 109 insertions(+), 66 deletions(-) diff --git a/resources/content_server/browse/browse.css b/resources/content_server/browse/browse.css index 07cf22f1cc..d66ae744cf 100644 --- a/resources/content_server/browse/browse.css +++ b/resources/content_server/browse/browse.css @@ -259,4 +259,15 @@ h2.library_name { /* }}} */ +/* Booklist {{{ */ + +#booklist .page { + display: none; +} + +.loading img { + vertical-align: middle; +} + +/* }}} */ diff --git a/src/calibre/library/server/browse.py b/src/calibre/library/server/browse.py index 6a557e423a..ffbd958688 100644 --- a/src/calibre/library/server/browse.py +++ b/src/calibre/library/server/browse.py @@ -7,7 +7,7 @@ __docformat__ = 'restructuredtext en' import operator, os, json from urllib import quote -from binascii import hexlify +from binascii import hexlify, unhexlify import cherrypy @@ -15,64 +15,33 @@ from calibre.constants import filesystem_encoding from calibre import isbytestring, force_unicode, prepare_string_for_xml as xml from calibre.utils.ordered_dict import OrderedDict -def paginate(offsets, content, base_url, up_url=None): # {{{ - 'Create markup for pagination' - - if '?' not in base_url: - base_url += '?' - - if base_url[-1] != '?': - base_url += '&' - - def navlink(decoration, name, cls, offset): - label = xml(name) - if cls in ('next', 'last'): - label += ' ' + decoration - else: - label = decoration + ' ' + label - return (u'' - u'{label}').format(cls=cls, decoration=decoration, - name=xml(name, True), offset=offset, - base_url=xml(base_url, True), label=label) - left = '' - if offsets.offset > 0 and offsets.previous_offset > 0: - left += navlink(u'\u219e', _('First'), 'first', 0) - if offsets.offset > 0: - left += ' ' + navlink('←', _('Previous'), 'previous', - offsets.previous_offset) - - middle = '' - if up_url: - middle = '[{1} ↑]'.format(xml(up_url, True), - xml(_('Up'))) - - right = '' - if offsets.next_offset > -1: - right += navlink('&rarr', _('Next'), 'next', offsets.next_offset) - if offsets.last_offset > offsets.next_offset and offsets.last_offset > 0: - right += ' ' + navlink(u'\u21A0', _('Last'), 'last', offsets.last_offset) - - navbar = u''' - - - - - - - - '''.format(left=left, right=right, middle=middle) - - templ = u''' -
- {navbar} -
- {content} +def render_book_list(ids): + pages = [] + while ids: + page = list(ids[:25]) + pages.append(page) + ids = ids[25:] + page_template = u'''\ +
+
+
{2}
+
- {navbar} -
- ''' - return templ.format(navbar=navbar, content=content) -# }}} + ''' + rpages = [] + for i, pg in enumerate(pages): + ld = xml(json.dumps(pg), True) + rpages.append(page_template.format(i, ld, + xml(_('Loading, please wait')) + '…')) + rpages = u'\n\n'.join(rpages) + + templ = u'''\ +

{0}

+
+ {pages} +
+ ''' + return templ.format(_('Browsing %d books')%len(ids), pages=rpages) def utf8(x): # {{{ if isinstance(x, unicode): @@ -171,10 +140,15 @@ class BrowseServer(object): connect('browse_category_group', base_href+'/category_group/{category}/{group}', self.browse_category_group) - connect('browse_list', base_href+'/list/{query}', self.browse_list) + connect('browse_matches', + base_href+'/matches/{category}/{cid}', + self.browse_matches) + connect('browse_booklist_page', + base_href+'/booklist_page', + self.browse_booklist_page) + connect('browse_search', base_href+'/search/{query}', self.browse_search) - connect('browse_book', base_href+'/book/{uuid}', self.browse_book) def browse_template(self, sort, category=True): @@ -267,12 +241,12 @@ class BrowseServer(object): def browse_category(self, category, sort): categories = self.categories_cache() + if category not in categories: + raise cherrypy.HTTPError(404, 'category not found') category_meta = self.db.field_metadata category_name = category_meta[category]['name'] datatype = category_meta[category]['datatype'] - if category not in categories: - raise cherrypy.HTTPError(404, 'category not found') items = categories[category] sort = self.browse_sort_categories(items, sort) @@ -331,11 +305,12 @@ class BrowseServer(object): if sort not in ('rating', 'name', 'popularity'): sort = 'name' categories = self.categories_cache() + if category not in categories: + raise cherrypy.HTTPError(404, 'category not found') + category_meta = self.db.field_metadata datatype = category_meta[category]['datatype'] - if category not in categories: - raise cherrypy.HTTPError(404, 'category not found') if not group: raise cherrypy.HTTPError(404, 'invalid group') @@ -360,6 +335,8 @@ class BrowseServer(object): 'Entry point for top-level, categories and sub-categories' if category == None: ans = self.browse_toplevel() + elif category == 'newest': + raise cherrypy.InternalRedirect('/browse/matches/newest/dummy') else: ans = self.browse_category(category, category_sort) @@ -368,8 +345,63 @@ class BrowseServer(object): # }}} # Book Lists {{{ - def browse_list(self, query=None, offset=0, sort=None): - raise NotImplementedError() + + def browse_sort_book_list(self, items, sort): + fm = self.db.field_metadata + keys = frozenset(fm.sortable_field_keys()) + if sort not in keys: + sort = 'title' + self.sort(items, 'title', True) + if sort != 'title': + ascending = fm[sort]['datatype'] not in ('rating', 'datetime') + self.sort(items, sort, ascending) + return sort + + @Endpoint(sort_type='list') + def browse_matches(self, category=None, cid=None, list_sort=None): + if not cid: + raise cherrypy.HTTPError(404, 'invalid category id: %r'%cid) + categories = self.categories_cache() + + if category not in categories and category != 'newest': + raise cherrypy.HTTPError(404, 'category not found') + try: + category_name = self.db.field_metadata[category]['name'] + except: + if category != 'newest': + raise + category_name = _('Newest') + + if category == 'search': + which = unhexlify(cid) + try: + ids = self.search_cache('search:"%s"'%which) + except: + raise cherrypy.HTTPError(404, 'Search: %r not understood'%which) + elif category == 'newest': + ids = list(self.db.data.iterallids()) + else: + ids = self.db.get_books_for_category(category, cid) + + items = [self.db.data._data[x] for x in ids] + if category == 'newest': + list_sort = 'timestamp' + sort = self.browse_sort_book_list(items, list_sort) + ids = [x[0] for x in items] + html = render_book_list(ids) + return self.browse_template(sort).format( + title=_('Books in') + " " +category_name, + script='booklist();', main=html) + + @Endpoint(mimetype='application/json; charset=utf-8', sort_type='list') + def browse_booklist_page(self, ids=None, list_sort=None): + if ids is None: + ids = json.dumps('[]') + try: + ids = json.loads(ids) + except: + raise cherrypy.HTTPError(404, 'invalid ids') + # }}} # Search {{{ From d5462c8d0063c844f5e8370a17e8da382d80dd37 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Thu, 14 Oct 2010 17:39:00 -0600 Subject: [PATCH 03/19] Update Globe and Mail. Fix #405 (New news feed) --- resources/recipes/globe_and_mail.recipe | 31 ++++---------------- resources/recipes/volksrant.recipe | 39 ++++++++++++++----------- 2 files changed, 28 insertions(+), 42 deletions(-) diff --git a/resources/recipes/globe_and_mail.recipe b/resources/recipes/globe_and_mail.recipe index b2a9915250..b6e6b5c25b 100644 --- a/resources/recipes/globe_and_mail.recipe +++ b/resources/recipes/globe_and_mail.recipe @@ -26,31 +26,12 @@ class GlobeAndMail(BasicNewsRecipe): #credit {margin-top:0px;} .tag {font-size: 22pt;}''' description = 'Canada\'s national newspaper' - remove_tags_before = dict(id="article-top") - remove_tags = [ - {'id':['util', 'article-tabs', 'comments', 'article-relations', - 'gallery-controls', 'video', 'galleryLoading','deck','header', - 'toolsBottom'] }, - {'class':['credit','inline-img-caption','tab-pointer'] }, - dict(name='div', attrs={'id':['lead-photo', 'most-popular-story']}), - dict(name='div', attrs={'class':'right'}), - dict(name='div', attrs={'id':'footer'}), - dict(name='div', attrs={'id':'beta-msg'}), - dict(name='img', attrs={'class':'headshot'}), - dict(name='div', attrs={'class':'brand'}), - dict(name='div', attrs={'id':'nav-wrap'}), - dict(name='div', attrs={'id':'featureTopics'}), - dict(name='div', attrs={'id':'videoNav'}), - dict(name='div', attrs={'id':'blog-header'}), - dict(name='div', attrs={'id':'right-rail'}), - dict(name='div', attrs={'id':'group-footer-container'}), - dict(name=['iframe', 'style']) - ] - remove_attributes = ['style'] - remove_tags_after = [{'id':['article-content']}, - {'class':['pull','inline-img'] }, - dict(name='img', attrs={'class':'inline-media-embed'}), - ] + keep_only_tags = [dict(name='article')] + remove_tags = [dict(name='aside'), + dict(name='footer'), + dict(name='div', attrs={'class':(lambda x: isinstance(x, (str,unicode)) and 'articlecommentcountholder' in x.split(' '))}), + dict(name='ul', attrs={'class':(lambda x: isinstance(x, (str,unicode)) and 'articletoolbar' in x.split(' '))}), + ] feeds = [ (u'Latest headlines', u'http://www.theglobeandmail.com/?service=rss'), (u'Top stories', u'http://www.theglobeandmail.com/?service=rss&feed=topstories'), diff --git a/resources/recipes/volksrant.recipe b/resources/recipes/volksrant.recipe index dcc8c042ee..6f3ec4ce0d 100644 --- a/resources/recipes/volksrant.recipe +++ b/resources/recipes/volksrant.recipe @@ -11,6 +11,7 @@ __docformat__ = 'restructuredtext en' on 10/10/10 to include function to grab print version of articles ''' +from datetime import date from calibre.web.feeds.news import BasicNewsRecipe ''' added by Tony Stegall @@ -27,7 +28,6 @@ class AdvancedUserRecipe1249039563(BasicNewsRecipe): no_stylesheets = True language = 'nl' - extra_css = ''' body{font-family:Arial,Helvetica,sans-serif; font-size:small;} h1{font-size:large;} @@ -43,14 +43,16 @@ class AdvancedUserRecipe1249039563(BasicNewsRecipe): def get_obfuscated_article(self, url): br = self.get_browser() + print 'THE CURRENT URL IS: ', url br.open(url) + year = date.today().year try: - response = br.follow_link(url_regex='.*?(2010)(\\/)(article)(\\/)(print)(\\/)', nr = 0) - html = response.read() + response = br.follow_link(url_regex='.*?(%d)(\\/)(article)(\\/)(print)(\\/)'%year, nr = 0) + html = response.read() except: - response = br.open(url) - html = response.read() + response = br.open(url) + html = response.read() self.temp_files.append(PersistentTemporaryFile('_fa.html')) self.temp_files[-1].write(html) @@ -59,19 +61,22 @@ class AdvancedUserRecipe1249039563(BasicNewsRecipe): ############################################################################################################### - feeds = [ - (u'Laatste Nieuws', u'http://volkskrant.nl/rss/laatstenieuws.rss'), - (u'Binnenlands nieuws', u'http://volkskrant.nl/rss/nederland.rss'), - (u'Buitenlands nieuws', u'http://volkskrant.nl/rss/internationaal.rss'), - (u'Economisch nieuws', u'http://volkskrant.nl/rss/economie.rss'), - (u'Sportnieuws', u'http://volkskrant.nl/rss/sport.rss'), - (u'Kunstnieuws', u'http://volkskrant.nl/rss/kunst.rss'), + ''' + Change Log: + Date: 10/15/2010 + Feeds updated by Martin Tarenskeen + ''' + + feeds = [ + (u'Laatste Nieuws', u'http://www.volkskrant.nl/rss/laatstenieuws.rss'), + (u'Binnenland', u'http://www.volkskrant.nl/rss/nederland.rss'), + (u'Buitenland', u'http://www.volkskrant.nl/rss/internationaal.rss'), + (u'Economie', u'http://www.volkskrant.nl/rss/economie.rss'), + (u'Sport', u'http://www.volkskrant.nl/rss/sport.rss'), + (u'Cultuur', u'http://www.volkskrant.nl/rss/kunst.rss'), + (u'Gezondheid & Wetenschap', u'http://www.volkskrant.nl/rss/wetenschap.rss'), + (u'Internet & Media', u'http://www.volkskrant.nl/rss/media.rss') ] - #both of these rss feeds link back to the main volksrant.nl url a.k.a Broken - #If someone happens to know the correct paths then they can put them in here - #(u'Wetenschapsnieuws', u'http://feeds.feedburner.com/DeVolkskrantWetenschap'), - #(u'Technologienieuws', u'http://feeds.feedburner.com/vkmedia') - ] ''' example for formating From 4fc74bdcd0e6403b8d46884a42d6767b0488be3d Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Thu, 14 Oct 2010 19:41:55 -0600 Subject: [PATCH 04/19] Content server: Allow variable sized thumbnails and replace use of PIL with ImageMagick --- src/calibre/library/server/content.py | 66 ++++++++++++++------------- src/calibre/utils/magick/draw.py | 8 +++- 2 files changed, 41 insertions(+), 33 deletions(-) diff --git a/src/calibre/library/server/content.py b/src/calibre/library/server/content.py index 59fed03fbd..8c5fef4ee1 100644 --- a/src/calibre/library/server/content.py +++ b/src/calibre/library/server/content.py @@ -5,18 +5,15 @@ __license__ = 'GPL v3' __copyright__ = '2010, Kovid Goyal ' __docformat__ = 'restructuredtext en' -import re, os, cStringIO +import re, os import cherrypy -try: - from PIL import Image as PILImage - PILImage -except ImportError: - import Image as PILImage from calibre import fit_image, guess_type from calibre.utils.date import fromtimestamp from calibre.library.caches import SortKeyGenerator +from calibre.utils.magick.draw import save_cover_data_to, Image, \ + thumbnail as generate_thumbnail class CSSortKeyGenerator(SortKeyGenerator): @@ -77,8 +74,13 @@ class ContentServer(object): id = int(match.group()) if not self.db.has_id(id): raise cherrypy.HTTPError(400, 'id:%d does not exist in database'%id) - if what == 'thumb': - return self.get_cover(id, thumbnail=True) + if what == 'thumb' or what.startswith('thumb_'): + try: + width, height = map(int, what.split('_')[1:]) + except: + width, height = 60, 80 + return self.get_cover(id, thumbnail=True, thumb_width=width, + thumb_height=height) if what == 'cover': return self.get_cover(id) return self.get_format(id, what) @@ -128,37 +130,39 @@ class ContentServer(object): return self.static('index.html') # Actually get content from the database {{{ - def get_cover(self, id, thumbnail=False): - cover = self.db.cover(id, index_is_id=True, as_file=False) - if cover is None: - cover = self.default_cover - cherrypy.response.headers['Content-Type'] = 'image/jpeg' - cherrypy.response.timeout = 3600 - path = getattr(cover, 'name', False) - updated = fromtimestamp(os.stat(path).st_mtime) if path and \ - os.access(path, os.R_OK) else self.build_time - cherrypy.response.headers['Last-Modified'] = self.last_modified(updated) + def get_cover(self, id, thumbnail=False, thumb_width=60, thumb_height=80): try: - f = cStringIO.StringIO(cover) - try: - im = PILImage.open(f) - except IOError: - raise cherrypy.HTTPError(404, 'No valid cover found') - width, height = im.size + cherrypy.response.headers['Content-Type'] = 'image/jpeg' + cherrypy.response.timeout = 3600 + cover = self.db.cover(id, index_is_id=True, as_file=True) + if cover is None: + cover = self.default_cover + updated = self.build_time + else: + with cover as f: + updated = fromtimestamp(os.stat(f.name).st_mtime) + cover = f.read() + cherrypy.response.headers['Last-Modified'] = self.last_modified(updated) + + if thumbnail: + return generate_thumbnail(cover, + width=thumb_width, height=thumb_height)[-1] + + img = Image() + img.load(cover) + width, height = img.size scaled, width, height = fit_image(width, height, - 60 if thumbnail else self.max_cover_width, - 80 if thumbnail else self.max_cover_height) + thumb_width if thumbnail else self.max_cover_width, + thumb_height if thumbnail else self.max_cover_height) if not scaled: return cover - im = im.resize((int(width), int(height)), PILImage.ANTIALIAS) - of = cStringIO.StringIO() - im.convert('RGB').save(of, 'JPEG') - return of.getvalue() + return save_cover_data_to(img, 'img.jpg', return_data=True, + resize_to=(width, height)) except Exception, err: import traceback cherrypy.log.error('Failed to generate cover:') cherrypy.log.error(traceback.print_exc()) - raise cherrypy.HTTPError(404, 'Failed to generate cover: %s'%err) + raise cherrypy.HTTPError(404, 'Failed to generate cover: %r'%err) def get_format(self, id, format): format = format.upper() diff --git a/src/calibre/utils/magick/draw.py b/src/calibre/utils/magick/draw.py index 6808215554..5c978a27e0 100644 --- a/src/calibre/utils/magick/draw.py +++ b/src/calibre/utils/magick/draw.py @@ -25,6 +25,7 @@ def save_cover_data_to(data, path, bgcolor='#ffffff', resize_to=None, resize and the input and output image formats are the same, no changes are made. + :param data: Image data as bytestring or Image object :param compression_quality: The quality of the image after compression. Number between 1 and 100. 1 means highest compression, 100 means no compression (lossless). @@ -33,8 +34,11 @@ def save_cover_data_to(data, path, bgcolor='#ffffff', resize_to=None, ''' changed = False - img = Image() - img.load(data) + if isinstance(data, Image): + img = data + else: + img = Image() + img.load(data) orig_fmt = normalize_format_name(img.format) fmt = os.path.splitext(path)[1] fmt = normalize_format_name(fmt[1:]) From 217eedf8feaa443819b3467fc90acedc6566ca04 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Thu, 14 Oct 2010 19:42:12 -0600 Subject: [PATCH 05/19] ... --- src/calibre/manual/faq.rst | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/calibre/manual/faq.rst b/src/calibre/manual/faq.rst index 51660d2620..359cc4755f 100644 --- a/src/calibre/manual/faq.rst +++ b/src/calibre/manual/faq.rst @@ -387,6 +387,12 @@ solve it, look for a corrupted font file on your system, in ~/Library/Fonts or t check for corrupted fonts in OS X is to start the "Font Book" application, select all fonts and then in the File menu, choose "Validate fonts". + +I downloaded the installer, but it is not working? +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Downloading from the internet can sometimes result in a corrupted download. If the |app| installer you downloaded is not opening, try downloading it again. If re-downloading it does not work, download it from `an alternate location `_. If the installer still doesn't work, then something on your computer is preventing it from running. Best place to ask for more help is in the `forums `_. + My antivirus program claims |app| is a virus/trojan? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ From 0a4da453beca720a47f5d93da7a0e47b8f1e8dad Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Fri, 15 Oct 2010 09:46:42 -0600 Subject: [PATCH 06/19] ... --- src/calibre/manual/news.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/calibre/manual/news.rst b/src/calibre/manual/news.rst index de50fd1c19..88b6dd47bc 100644 --- a/src/calibre/manual/news.rst +++ b/src/calibre/manual/news.rst @@ -295,6 +295,9 @@ To learn more about writing advanced recipes using some of the facilities, avail `Built-in recipes `_ The source code for the built-in recipes that come with |app| + `The calibre recipes forum `_ + Lots of knowledgeable |app| recipe writers hang out here. + API documentation -------------------- From 1f0d61c630af6888841e83cfc3439dc816d69b94 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Fri, 15 Oct 2010 11:41:50 -0600 Subject: [PATCH 07/19] Basic book list in the new content server --- resources/content_server/browse/browse.css | 57 ++++++++++++++ resources/content_server/browse/browse.js | 53 ++++++++++++- resources/content_server/browse/summary.html | 14 ++++ src/calibre/library/comments.py | 2 + src/calibre/library/server/browse.py | 78 +++++++++++++++++--- 5 files changed, 188 insertions(+), 16 deletions(-) create mode 100644 resources/content_server/browse/summary.html diff --git a/resources/content_server/browse/browse.css b/resources/content_server/browse/browse.css index d66ae744cf..d2e8106ba0 100644 --- a/resources/content_server/browse/browse.css +++ b/resources/content_server/browse/browse.css @@ -265,9 +265,66 @@ h2.library_name { display: none; } +#booklist .load_data { display: none } + .loading img { vertical-align: middle; } +#booklist .summary { + margin-bottom: 2ex; + border-bottom: solid 1px black; +} + +#booklist div.left { + float: left; + height: 190px; + vertical-align: middle; + text-align: center; + margin-left: 1em; + margin-right: 2em; +} + +#booklist div.left img { + display: block; + margin-bottom: 1ex; +} + +#booklist div.right { + height: 190px; + overflow: auto; + margin-left: 1em; + margin-right: 1em; +} + +#booklist div.right .stars { + float:right; + margin-right: 1em; +} + +#booklist div.right .stars .rating_container { + display: block; +} + +#booklist .title { + font-size: larger; +} + +#booklist .formats a { + text-decoration: none; +} + +#booklist .formats a:hover { + color: red; +} + +#booklist .left .ui-button-text { + font-weight: bold; + padding-left: 0.25em; + padding-right: 0.25em; + padding-top: 0.25em; + padding-bottom: 0.25em; +} + /* }}} */ diff --git a/resources/content_server/browse/browse.js b/resources/content_server/browse/browse.js index f3f278fc48..5f2af3299e 100644 --- a/resources/content_server/browse/browse.js +++ b/resources/content_server/browse/browse.js @@ -89,11 +89,14 @@ function render_error(msg) { } // Category feed {{{ + +function category_clicked() { + var href = $(this).find("span.href").html(); + window.location = href; +} + function category() { - $(".category .category-item").click(function() { - var href = $(this).find("span.href").html(); - window.location = href; - }); + $(".category .category-item").click(category_clicked); $(".category a.navlink").button(); @@ -115,6 +118,7 @@ function category() { this.children(".loaded").html(data); this.children(".loaded").show(); this.children(".loading").hide(); + this.find('.category-item').click(category_clicked); }, context: ui.newContent, dataType: "json", @@ -132,4 +136,45 @@ function category() { } // }}} +// Booklist {{{ +function load_page(elem) { + var ids = elem.find(".load_data").attr('title'); + var href = elem.find(".load_data").html(); + $.ajax({ + url: href, + context: elem, + dataType: "json", + type: 'POST', + timeout: 600000, //milliseconds (10 minutes) + data: {'ids': ids}, + error: function(xhr, stat, err) { + this.children(".loaded").html(render_error(stat)); + this.children(".loaded").show(); + this.children(".loading").hide(); + }, + success: function(data) { + this.children(".loaded").html(data); + this.children(".loaded").show(); + this.children(".loading").hide(); + this.find(".left a.read").button(); + } + }); + $("#booklist .page").hide(); + elem.children(".loaded").hide(); + elem.children(".loading").show(); + elem.show(); +} + +function booklist() { + var test = $("#booklist #page0").html(); + if (!test) { + $("#booklist").html(render_error("No books found")); + return; + } + + load_page($("#booklist #page0")); + +} + +// }}} diff --git a/resources/content_server/browse/summary.html b/resources/content_server/browse/summary.html new file mode 100644 index 0000000000..0caf710a43 --- /dev/null +++ b/resources/content_server/browse/summary.html @@ -0,0 +1,14 @@ +
+ +
+
{stars}{series}
+
{title}
+
{authors}
+
{comments}
+
{tags}
+
{other_formats}
+
+
diff --git a/src/calibre/library/comments.py b/src/calibre/library/comments.py index 32ae65b31e..670d9f2564 100644 --- a/src/calibre/library/comments.py +++ b/src/calibre/library/comments.py @@ -42,6 +42,8 @@ def comments_to_html(comments): Deprecated HTML returns as HTML via BeautifulSoup() ''' + if not comments: + return u'

' if not isinstance(comments, unicode): comments = comments.decode(preferred_encoding, 'replace') diff --git a/src/calibre/library/server/browse.py b/src/calibre/library/server/browse.py index ffbd958688..e1415decdb 100644 --- a/src/calibre/library/server/browse.py +++ b/src/calibre/library/server/browse.py @@ -14,16 +14,20 @@ import cherrypy from calibre.constants import filesystem_encoding from calibre import isbytestring, force_unicode, prepare_string_for_xml as xml from calibre.utils.ordered_dict import OrderedDict +from calibre.utils.filenames import ascii_filename +from calibre.utils.config import prefs +from calibre.library.comments import comments_to_html def render_book_list(ids): pages = [] + num = len(ids) while ids: page = list(ids[:25]) pages.append(page) ids = ids[25:] page_template = u'''\
-
+
/browse/booklist_page
{2}
@@ -41,7 +45,7 @@ def render_book_list(ids): {pages}
''' - return templ.format(_('Browsing %d books')%len(ids), pages=rpages) + return templ.format(_('Browsing %d books')%num, pages=rpages) def utf8(x): # {{{ if isinstance(x, unicode): @@ -49,11 +53,13 @@ def utf8(x): # {{{ return x # }}} -def render_rating(rating, container='span'): # {{{ +def render_rating(rating, container='span', prefix=None): # {{{ if rating < 0.1: return '', '' added = 0 - rstring = xml(_('Average rating: %.1f stars')% (rating if rating else 0.0), + if prefix is None: + prefix = _('Average rating') + rstring = xml(_('%s: %.1f stars')% (prefix, rating if rating else 0.0), True) ans = ['<%s class="rating">' % (container)] for i in range(5): @@ -89,7 +95,7 @@ def get_category_items(category, items, db, datatype): # {{{ id_ = xml(str(id_)) desc = '' if i.count > 0: - desc += '[' + _('%d items')%i.count + ']' + desc += '[' + _('%d books')%i.count + ']' href = '/browse/matches/%s/%s'%(category, id_) return templ.format(xml(name), rating, xml(desc), xml(quote(href)), rstring) @@ -193,6 +199,14 @@ class BrowseServer(object): self.__browse_template__ = generate() return self.__browse_template__ + @property + def browse_summary_template(self): + if not hasattr(self, '__browse_summary_template__') or \ + self.opts.develop: + self.__browse_summary_template__ = \ + P('content_server/browse/summary.html', data=True).decode('utf-8') + return self.__browse_summary_template__ + # Catalogs {{{ def browse_toplevel(self): @@ -329,7 +343,6 @@ class BrowseServer(object): return json.dumps(entries, ensure_ascii=False) - @Endpoint() def browse_catalog(self, category=None, category_sort=None): 'Entry point for top-level, categories and sub-categories' @@ -401,16 +414,57 @@ class BrowseServer(object): ids = json.loads(ids) except: raise cherrypy.HTTPError(404, 'invalid ids') + summs = [] + for id_ in ids: + try: + id_ = int(id_) + mi = self.db.get_metadata(id_, index_is_id=True) + except: + continue + fmts = self.db.formats(id_, index_is_id=True) + if not fmts: + fmts = '' + fmts = [x.lower() for x in fmts.split(',') if x] + pf = prefs['output_format'].lower() + fmt = pf if pf in fmts else fmts[0] + args = {'id':id_, 'mi':mi, 'read_string':_('Read'),} + for key in mi.all_field_keys(): + val = mi.format_field(key)[1] + if not val: + val = '' + args[key] = xml(val, True) + fname = ascii_filename(args['title']) + ' - ' + ascii_filename(args['authors']) + args['href'] = '/get/%s/%s_%d.%s'%( + fmt, fname, id_, fmt) + args['comments'] = comments_to_html(mi.comments) + args['read_tooltip'] = \ + _('Read %s in the %s format')%(args['title'], fmt.upper()) + args['stars'] = '' + if mi.rating: + args['stars'] = render_rating(mi.rating/2.0, prefix=_('Rating'))[0] + if args['tags']: + args['tags'] = u'%s: '%_('Tags') + args['tags'] + args['other_formats'] = '' + other_fmts = [x for x in fmts if x.lower() != fmt.lower()] + + if other_fmts: + ofmts = [u'{3}'\ + .format(fmt, fname, id_, fmt.upper()) for fmt in + other_fmts] + ofmts = ', '.join(ofmts) + args['other_formats'] = u'%s: ' % \ + _('Other formats') + ofmts + + + summs.append(self.browse_summary_template.format(**args)) + + + return json.dumps('\n'.join(summs), ensure_ascii=False) # }}} # Search {{{ - def browse_search(self, query=None, offset=0, sort=None): - raise NotImplementedError() - # }}} - - # Book {{{ - def browse_book(self, uuid=None): + def browse_search(self, query=None): raise NotImplementedError() # }}} From 06c36eac92f848aa3312664ad56bab4bff5d0d93 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Fri, 15 Oct 2010 16:58:39 -0600 Subject: [PATCH 08/19] Pagination of book lists --- resources/content_server/browse/browse.css | 46 ++++++++++++++++++ resources/content_server/browse/browse.js | 39 +++++++++++++--- resources/content_server/browse/summary.html | 2 +- src/calibre/library/server/browse.py | 49 ++++++++++++++++---- 4 files changed, 119 insertions(+), 17 deletions(-) diff --git a/resources/content_server/browse/browse.css b/resources/content_server/browse/browse.css index d2e8106ba0..f3dfc89caf 100644 --- a/resources/content_server/browse/browse.css +++ b/resources/content_server/browse/browse.css @@ -279,6 +279,7 @@ h2.library_name { #booklist div.left { float: left; height: 190px; + width: 100px; vertical-align: middle; text-align: center; margin-left: 1em; @@ -288,6 +289,8 @@ h2.library_name { #booklist div.left img { display: block; margin-bottom: 1ex; + margin-left: auto; + margin-right: auto; } #booklist div.right { @@ -312,6 +315,7 @@ h2.library_name { #booklist .formats a { text-decoration: none; + color: blue; } #booklist .formats a:hover { @@ -326,5 +330,47 @@ h2.library_name { padding-bottom: 0.25em; } +#booklist .listnav { + display: table; + width: 100%; +} + +#booklist .listnav a { + color: blue; + text-decoration: none; +} + +#booklist .listnav a:hover { + color: red; +} + +#booklist .topnav { + border-bottom: solid black 1px; + margin-bottom: 1ex; +} + +#booklist .navleft { + display: table-cell; + text-align: left; +} + +#booklist .navleft a { + margin-right: 1em; +} + +#booklist .navmiddle { + display: table-cell; + text-align: center; +} + +#booklist .navright { + display: table-cell; + text-align: right; +} + +#booklist .navright a { + margin-left: 1em; +} + /* }}} */ diff --git a/resources/content_server/browse/browse.js b/resources/content_server/browse/browse.js index 5f2af3299e..d6383d3646 100644 --- a/resources/content_server/browse/browse.js +++ b/resources/content_server/browse/browse.js @@ -138,9 +138,33 @@ function category() { // Booklist {{{ +function first_page() { + load_page($("#booklist #page0")); +} + +function last_page() { + load_page($("#booklist .page").last()); +} + +function next_page() { + var elem = $("#booklist .page:visible").next('.page'); + if (elem.length > 0) load_page(elem); + else first_page(); +} + +function previous_page() { + var elem = $("#booklist .page:visible").prev('.page'); + if (elem.length > 0) load_page(elem); + else last_page(); +} + function load_page(elem) { - var ids = elem.find(".load_data").attr('title'); - var href = elem.find(".load_data").html(); + if (elem.is(":visible")) return; + var ld = elem.find('.load_data'); + var ids = ld.attr('title'); + var href = ld.find(".url").attr('title'); + elem.children(".loaded").hide(); + $.ajax({ url: href, context: elem, @@ -155,12 +179,14 @@ function load_page(elem) { }, success: function(data) { this.children(".loaded").html(data); - this.children(".loaded").show(); - this.children(".loading").hide(); this.find(".left a.read").button(); + this.children(".loading").hide(); + this.parent().find('.navmiddle .start').html(this.find('.load_data .start').attr('title')); + this.parent().find('.navmiddle .end').html(this.find('.load_data .end').attr('title')); + this.children(".loaded").fadeIn(1000); } }); - $("#booklist .page").hide(); + $("#booklist .page:visible").hide(); elem.children(".loaded").hide(); elem.children(".loading").show(); elem.show(); @@ -173,8 +199,7 @@ function booklist() { return; } - load_page($("#booklist #page0")); - + first_page(); } // }}} diff --git a/resources/content_server/browse/summary.html b/resources/content_server/browse/summary.html index 0caf710a43..01f2b333f2 100644 --- a/resources/content_server/browse/summary.html +++ b/resources/content_server/browse/summary.html @@ -1,6 +1,6 @@
diff --git a/src/calibre/library/server/browse.py b/src/calibre/library/server/browse.py index e1415decdb..bd63325ecc 100644 --- a/src/calibre/library/server/browse.py +++ b/src/calibre/library/server/browse.py @@ -21,31 +21,62 @@ from calibre.library.comments import comments_to_html def render_book_list(ids): pages = [] num = len(ids) + pos = 0 + delta = 25 while ids: - page = list(ids[:25]) - pages.append(page) - ids = ids[25:] + page = list(ids[:delta]) + pages.append((page, pos)) + ids = ids[delta:] + pos += len(page) page_template = u'''\
-
/browse/booklist_page
+
+ + + +
{2}
''' rpages = [] - for i, pg in enumerate(pages): + for i, x in enumerate(pages): + pg, pos = x ld = xml(json.dumps(pg), True) rpages.append(page_template.format(i, ld, - xml(_('Loading, please wait')) + '…')) + xml(_('Loading, please wait')) + '…', + start=pos+1, end=pos+len(pg))) rpages = u'\n\n'.join(rpages) templ = u'''\

{0}

+
+ {navbar} +
{pages} +
+ {navbar} +
''' - return templ.format(_('Browsing %d books')%num, pages=rpages) + + navbar = u'''\ + + + + '''.format(first=_('First'), last=_('Last'), previous=_('Previous'), + next=_('Next'), num=num) + + return templ.format(_('Browsing %d books')%num, pages=rpages, navbar=navbar) def utf8(x): # {{{ if isinstance(x, unicode): @@ -182,7 +213,7 @@ class BrowseServer(object): opts = ['' % ( 'selected="selected" ' if k==sort else '', xml(k), xml(n), ) for k, n in - sorted(sort_opts, key=operator.itemgetter(1))] + sorted(sort_opts, key=operator.itemgetter(1)) if k and n] ans = ans.replace('{sort_select_options}', ('\n'+' '*20).join(opts)) lp = self.db.library_path if isbytestring(lp): @@ -402,7 +433,7 @@ class BrowseServer(object): sort = self.browse_sort_book_list(items, list_sort) ids = [x[0] for x in items] html = render_book_list(ids) - return self.browse_template(sort).format( + return self.browse_template(sort, category=False).format( title=_('Books in') + " " +category_name, script='booklist();', main=html) From f7b3f6a442666358f78026f6bc23433affaa78bf Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Fri, 15 Oct 2010 17:26:49 -0600 Subject: [PATCH 09/19] Fix #5249 (Error parsing accented characters in content server) --- resources/content_server/browse/browse.html | 2 +- resources/content_server/index.html | 2 +- src/calibre/library/server/mobile.py | 6 +++++- src/calibre/library/server/xml.py | 2 ++ 4 files changed, 9 insertions(+), 3 deletions(-) diff --git a/resources/content_server/browse/browse.html b/resources/content_server/browse/browse.html index e1e4cd47f5..cd556b87a4 100644 --- a/resources/content_server/browse/browse.html +++ b/resources/content_server/browse/browse.html @@ -76,7 +76,7 @@
');/sw|se|ne|nw/.test(f)&&g.css({zIndex:++a.zIndex});"se"==f&&g.addClass("ui-icon ui-icon-gripsmall-diagonal-se");this.handles[f]=".ui-resizable-"+f;this.element.append(g)}}this._renderAxis=function(h){h=h||this.element;for(var i in this.handles){if(this.handles[i].constructor== +String)this.handles[i]=e(this.handles[i],this.element).show();if(this.elementIsWrapper&&this.originalElement[0].nodeName.match(/textarea|input|select|button/i)){var j=e(this.handles[i],this.element),k=0;k=/sw|ne|nw|se|n|s/.test(i)?j.outerHeight():j.outerWidth();j=["padding",/ne|nw|n/.test(i)?"Top":/se|sw|s/.test(i)?"Bottom":/^e$/.test(i)?"Right":"Left"].join("");h.css(j,k);this._proportionallyResize()}e(this.handles[i])}};this._renderAxis(this.element);this._handles=e(".ui-resizable-handle",this.element).disableSelection(); +this._handles.mouseover(function(){if(!b.resizing){if(this.className)var h=this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i);b.axis=h&&h[1]?h[1]:"se"}});if(a.autoHide){this._handles.hide();e(this.element).addClass("ui-resizable-autohide").hover(function(){e(this).removeClass("ui-resizable-autohide");b._handles.show()},function(){if(!b.resizing){e(this).addClass("ui-resizable-autohide");b._handles.hide()}})}this._mouseInit()},destroy:function(){this._mouseDestroy();var b=function(c){e(c).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing").removeData("resizable").unbind(".resizable").find(".ui-resizable-handle").remove()}; +if(this.elementIsWrapper){b(this.element);var a=this.element;a.after(this.originalElement.css({position:a.css("position"),width:a.outerWidth(),height:a.outerHeight(),top:a.css("top"),left:a.css("left")})).remove()}this.originalElement.css("resize",this.originalResizeStyle);b(this.originalElement);return this},_mouseCapture:function(b){var a=false;for(var c in this.handles)if(e(this.handles[c])[0]==b.target)a=true;return!this.options.disabled&&a},_mouseStart:function(b){var a=this.options,c=this.element.position(), +d=this.element;this.resizing=true;this.documentScroll={top:e(document).scrollTop(),left:e(document).scrollLeft()};if(d.is(".ui-draggable")||/absolute/.test(d.css("position")))d.css({position:"absolute",top:c.top,left:c.left});e.browser.opera&&/relative/.test(d.css("position"))&&d.css({position:"relative",top:"auto",left:"auto"});this._renderProxy();c=m(this.helper.css("left"));var f=m(this.helper.css("top"));if(a.containment){c+=e(a.containment).scrollLeft()||0;f+=e(a.containment).scrollTop()||0}this.offset= +this.helper.offset();this.position={left:c,top:f};this.size=this._helper?{width:d.outerWidth(),height:d.outerHeight()}:{width:d.width(),height:d.height()};this.originalSize=this._helper?{width:d.outerWidth(),height:d.outerHeight()}:{width:d.width(),height:d.height()};this.originalPosition={left:c,top:f};this.sizeDiff={width:d.outerWidth()-d.width(),height:d.outerHeight()-d.height()};this.originalMousePosition={left:b.pageX,top:b.pageY};this.aspectRatio=typeof a.aspectRatio=="number"?a.aspectRatio: +this.originalSize.width/this.originalSize.height||1;a=e(".ui-resizable-"+this.axis).css("cursor");e("body").css("cursor",a=="auto"?this.axis+"-resize":a);d.addClass("ui-resizable-resizing");this._propagate("start",b);return true},_mouseDrag:function(b){var a=this.helper,c=this.originalMousePosition,d=this._change[this.axis];if(!d)return false;c=d.apply(this,[b,b.pageX-c.left||0,b.pageY-c.top||0]);if(this._aspectRatio||b.shiftKey)c=this._updateRatio(c,b);c=this._respectSize(c,b);this._propagate("resize", +b);a.css({top:this.position.top+"px",left:this.position.left+"px",width:this.size.width+"px",height:this.size.height+"px"});!this._helper&&this._proportionallyResizeElements.length&&this._proportionallyResize();this._updateCache(c);this._trigger("resize",b,this.ui());return false},_mouseStop:function(b){this.resizing=false;var a=this.options,c=this;if(this._helper){var d=this._proportionallyResizeElements,f=d.length&&/textarea/i.test(d[0].nodeName);d=f&&e.ui.hasScroll(d[0],"left")?0:c.sizeDiff.height; +f={width:c.size.width-(f?0:c.sizeDiff.width),height:c.size.height-d};d=parseInt(c.element.css("left"),10)+(c.position.left-c.originalPosition.left)||null;var g=parseInt(c.element.css("top"),10)+(c.position.top-c.originalPosition.top)||null;a.animate||this.element.css(e.extend(f,{top:g,left:d}));c.helper.height(c.size.height);c.helper.width(c.size.width);this._helper&&!a.animate&&this._proportionallyResize()}e("body").css("cursor","auto");this.element.removeClass("ui-resizable-resizing");this._propagate("stop", +b);this._helper&&this.helper.remove();return false},_updateCache:function(b){this.offset=this.helper.offset();if(l(b.left))this.position.left=b.left;if(l(b.top))this.position.top=b.top;if(l(b.height))this.size.height=b.height;if(l(b.width))this.size.width=b.width},_updateRatio:function(b){var a=this.position,c=this.size,d=this.axis;if(b.height)b.width=c.height*this.aspectRatio;else if(b.width)b.height=c.width/this.aspectRatio;if(d=="sw"){b.left=a.left+(c.width-b.width);b.top=null}if(d=="nw"){b.top= +a.top+(c.height-b.height);b.left=a.left+(c.width-b.width)}return b},_respectSize:function(b){var a=this.options,c=this.axis,d=l(b.width)&&a.maxWidth&&a.maxWidthb.width,h=l(b.height)&&a.minHeight&&a.minHeight>b.height;if(g)b.width=a.minWidth;if(h)b.height=a.minHeight;if(d)b.width=a.maxWidth;if(f)b.height=a.maxHeight;var i=this.originalPosition.left+this.originalSize.width,j=this.position.top+this.size.height, +k=/sw|nw|w/.test(c);c=/nw|ne|n/.test(c);if(g&&k)b.left=i-a.minWidth;if(d&&k)b.left=i-a.maxWidth;if(h&&c)b.top=j-a.minHeight;if(f&&c)b.top=j-a.maxHeight;if((a=!b.width&&!b.height)&&!b.left&&b.top)b.top=null;else if(a&&!b.top&&b.left)b.left=null;return b},_proportionallyResize:function(){if(this._proportionallyResizeElements.length)for(var b=this.helper||this.element,a=0;a
');var a=e.browser.msie&&e.browser.version<7,c=a?1:0;a=a?2:-1;this.helper.addClass(this._helper).css({width:this.element.outerWidth()+a,height:this.element.outerHeight()+a,position:"absolute",left:this.elementOffset.left-c+"px",top:this.elementOffset.top-c+"px",zIndex:++b.zIndex});this.helper.appendTo("body").disableSelection()}else this.helper=this.element},_change:{e:function(b,a){return{width:this.originalSize.width+ +a}},w:function(b,a){return{left:this.originalPosition.left+a,width:this.originalSize.width-a}},n:function(b,a,c){return{top:this.originalPosition.top+c,height:this.originalSize.height-c}},s:function(b,a,c){return{height:this.originalSize.height+c}},se:function(b,a,c){return e.extend(this._change.s.apply(this,arguments),this._change.e.apply(this,[b,a,c]))},sw:function(b,a,c){return e.extend(this._change.s.apply(this,arguments),this._change.w.apply(this,[b,a,c]))},ne:function(b,a,c){return e.extend(this._change.n.apply(this, +arguments),this._change.e.apply(this,[b,a,c]))},nw:function(b,a,c){return e.extend(this._change.n.apply(this,arguments),this._change.w.apply(this,[b,a,c]))}},_propagate:function(b,a){e.ui.plugin.call(this,b,[a,this.ui()]);b!="resize"&&this._trigger(b,a,this.ui())},plugins:{},ui:function(){return{originalElement:this.originalElement,element:this.element,helper:this.helper,position:this.position,size:this.size,originalSize:this.originalSize,originalPosition:this.originalPosition}}});e.extend(e.ui.resizable, +{version:"1.8.5"});e.ui.plugin.add("resizable","alsoResize",{start:function(){var b=e(this).data("resizable").options,a=function(c){e(c).each(function(){var d=e(this);d.data("resizable-alsoresize",{width:parseInt(d.width(),10),height:parseInt(d.height(),10),left:parseInt(d.css("left"),10),top:parseInt(d.css("top"),10),position:d.css("position")})})};if(typeof b.alsoResize=="object"&&!b.alsoResize.parentNode)if(b.alsoResize.length){b.alsoResize=b.alsoResize[0];a(b.alsoResize)}else e.each(b.alsoResize, +function(c){a(c)});else a(b.alsoResize)},resize:function(b,a){var c=e(this).data("resizable");b=c.options;var d=c.originalSize,f=c.originalPosition,g={height:c.size.height-d.height||0,width:c.size.width-d.width||0,top:c.position.top-f.top||0,left:c.position.left-f.left||0},h=function(i,j){e(i).each(function(){var k=e(this),q=e(this).data("resizable-alsoresize"),p={},r=j&&j.length?j:k.parents(a.originalElement[0]).length?["width","height"]:["width","height","top","left"];e.each(r,function(n,o){if((n= +(q[o]||0)+(g[o]||0))&&n>=0)p[o]=n||null});if(e.browser.opera&&/relative/.test(k.css("position"))){c._revertToRelativePosition=true;k.css({position:"absolute",top:"auto",left:"auto"})}k.css(p)})};typeof b.alsoResize=="object"&&!b.alsoResize.nodeType?e.each(b.alsoResize,function(i,j){h(i,j)}):h(b.alsoResize)},stop:function(){var b=e(this).data("resizable"),a=b.options,c=function(d){e(d).each(function(){var f=e(this);f.css({position:f.data("resizable-alsoresize").position})})};if(b._revertToRelativePosition){b._revertToRelativePosition= +false;typeof a.alsoResize=="object"&&!a.alsoResize.nodeType?e.each(a.alsoResize,function(d){c(d)}):c(a.alsoResize)}e(this).removeData("resizable-alsoresize")}});e.ui.plugin.add("resizable","animate",{stop:function(b){var a=e(this).data("resizable"),c=a.options,d=a._proportionallyResizeElements,f=d.length&&/textarea/i.test(d[0].nodeName),g=f&&e.ui.hasScroll(d[0],"left")?0:a.sizeDiff.height;f={width:a.size.width-(f?0:a.sizeDiff.width),height:a.size.height-g};g=parseInt(a.element.css("left"),10)+(a.position.left- +a.originalPosition.left)||null;var h=parseInt(a.element.css("top"),10)+(a.position.top-a.originalPosition.top)||null;a.element.animate(e.extend(f,h&&g?{top:h,left:g}:{}),{duration:c.animateDuration,easing:c.animateEasing,step:function(){var i={width:parseInt(a.element.css("width"),10),height:parseInt(a.element.css("height"),10),top:parseInt(a.element.css("top"),10),left:parseInt(a.element.css("left"),10)};d&&d.length&&e(d[0]).css({width:i.width,height:i.height});a._updateCache(i);a._propagate("resize", +b)}})}});e.ui.plugin.add("resizable","containment",{start:function(){var b=e(this).data("resizable"),a=b.element,c=b.options.containment;if(a=c instanceof e?c.get(0):/parent/.test(c)?a.parent().get(0):c){b.containerElement=e(a);if(/document/.test(c)||c==document){b.containerOffset={left:0,top:0};b.containerPosition={left:0,top:0};b.parentData={element:e(document),left:0,top:0,width:e(document).width(),height:e(document).height()||document.body.parentNode.scrollHeight}}else{var d=e(a),f=[];e(["Top", +"Right","Left","Bottom"]).each(function(i,j){f[i]=m(d.css("padding"+j))});b.containerOffset=d.offset();b.containerPosition=d.position();b.containerSize={height:d.innerHeight()-f[3],width:d.innerWidth()-f[1]};c=b.containerOffset;var g=b.containerSize.height,h=b.containerSize.width;h=e.ui.hasScroll(a,"left")?a.scrollWidth:h;g=e.ui.hasScroll(a)?a.scrollHeight:g;b.parentData={element:a,left:c.left,top:c.top,width:h,height:g}}}},resize:function(b){var a=e(this).data("resizable"),c=a.options,d=a.containerOffset, +f=a.position;b=a._aspectRatio||b.shiftKey;var g={top:0,left:0},h=a.containerElement;if(h[0]!=document&&/static/.test(h.css("position")))g=d;if(f.left<(a._helper?d.left:0)){a.size.width+=a._helper?a.position.left-d.left:a.position.left-g.left;if(b)a.size.height=a.size.width/c.aspectRatio;a.position.left=c.helper?d.left:0}if(f.top<(a._helper?d.top:0)){a.size.height+=a._helper?a.position.top-d.top:a.position.top;if(b)a.size.width=a.size.height*c.aspectRatio;a.position.top=a._helper?d.top:0}a.offset.left= +a.parentData.left+a.position.left;a.offset.top=a.parentData.top+a.position.top;c=Math.abs((a._helper?a.offset.left-g.left:a.offset.left-g.left)+a.sizeDiff.width);d=Math.abs((a._helper?a.offset.top-g.top:a.offset.top-d.top)+a.sizeDiff.height);f=a.containerElement.get(0)==a.element.parent().get(0);g=/relative|absolute/.test(a.containerElement.css("position"));if(f&&g)c-=a.parentData.left;if(c+a.size.width>=a.parentData.width){a.size.width=a.parentData.width-c;if(b)a.size.height=a.size.width/a.aspectRatio}if(d+ +a.size.height>=a.parentData.height){a.size.height=a.parentData.height-d;if(b)a.size.width=a.size.height*a.aspectRatio}},stop:function(){var b=e(this).data("resizable"),a=b.options,c=b.containerOffset,d=b.containerPosition,f=b.containerElement,g=e(b.helper),h=g.offset(),i=g.outerWidth()-b.sizeDiff.width;g=g.outerHeight()-b.sizeDiff.height;b._helper&&!a.animate&&/relative/.test(f.css("position"))&&e(this).css({left:h.left-d.left-c.left,width:i,height:g});b._helper&&!a.animate&&/static/.test(f.css("position"))&& +e(this).css({left:h.left-d.left-c.left,width:i,height:g})}});e.ui.plugin.add("resizable","ghost",{start:function(){var b=e(this).data("resizable"),a=b.options,c=b.size;b.ghost=b.originalElement.clone();b.ghost.css({opacity:0.25,display:"block",position:"relative",height:c.height,width:c.width,margin:0,left:0,top:0}).addClass("ui-resizable-ghost").addClass(typeof a.ghost=="string"?a.ghost:"");b.ghost.appendTo(b.helper)},resize:function(){var b=e(this).data("resizable");b.ghost&&b.ghost.css({position:"relative", +height:b.size.height,width:b.size.width})},stop:function(){var b=e(this).data("resizable");b.ghost&&b.helper&&b.helper.get(0).removeChild(b.ghost.get(0))}});e.ui.plugin.add("resizable","grid",{resize:function(){var b=e(this).data("resizable"),a=b.options,c=b.size,d=b.originalSize,f=b.originalPosition,g=b.axis;a.grid=typeof a.grid=="number"?[a.grid,a.grid]:a.grid;var h=Math.round((c.width-d.width)/(a.grid[0]||1))*(a.grid[0]||1);a=Math.round((c.height-d.height)/(a.grid[1]||1))*(a.grid[1]||1);if(/^(se|s|e)$/.test(g)){b.size.width= +d.width+h;b.size.height=d.height+a}else if(/^(ne)$/.test(g)){b.size.width=d.width+h;b.size.height=d.height+a;b.position.top=f.top-a}else{if(/^(sw)$/.test(g)){b.size.width=d.width+h;b.size.height=d.height+a}else{b.size.width=d.width+h;b.size.height=d.height+a;b.position.top=f.top-a}b.position.left=f.left-h}}});var m=function(b){return parseInt(b,10)||0},l=function(b){return!isNaN(parseInt(b,10))}})(jQuery); ;/* * jQuery UI Accordion 1.8.5 * @@ -119,222 +166,42 @@ c=a("").addClass("ui-button-text").html(this.options.label).appendT this.hasTitle||b.attr("title",c)}}else b.addClass("ui-button-text-only")}}});a.widget("ui.buttonset",{_create:function(){this.element.addClass("ui-buttonset");this._init()},_init:function(){this.refresh()},_setOption:function(b,c){b==="disabled"&&this.buttons.button("option",b,c);a.Widget.prototype._setOption.apply(this,arguments)},refresh:function(){this.buttons=this.element.find(":button, :submit, :reset, :checkbox, :radio, a, :data(button)").filter(":ui-button").button("refresh").end().not(":ui-button").button().end().map(function(){return a(this).button("widget")[0]}).removeClass("ui-corner-all ui-corner-left ui-corner-right").filter(":visible").filter(":first").addClass("ui-corner-left").end().filter(":last").addClass("ui-corner-right").end().end().end()}, destroy:function(){this.element.removeClass("ui-buttonset");this.buttons.map(function(){return a(this).button("widget")[0]}).removeClass("ui-corner-left ui-corner-right").end().button("destroy");a.Widget.prototype.destroy.call(this)}})})(jQuery); ;/* - * jQuery UI Effects 1.8.5 + * jQuery UI Dialog 1.8.5 * * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) * Dual licensed under the MIT or GPL Version 2 licenses. * http://jquery.org/license * - * http://docs.jquery.com/UI/Effects/ - */ -jQuery.effects||function(f,j){function l(c){var a;if(c&&c.constructor==Array&&c.length==3)return c;if(a=/rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(c))return[parseInt(a[1],10),parseInt(a[2],10),parseInt(a[3],10)];if(a=/rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(c))return[parseFloat(a[1])*2.55,parseFloat(a[2])*2.55,parseFloat(a[3])*2.55];if(a=/#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(c))return[parseInt(a[1], -16),parseInt(a[2],16),parseInt(a[3],16)];if(a=/#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(c))return[parseInt(a[1]+a[1],16),parseInt(a[2]+a[2],16),parseInt(a[3]+a[3],16)];if(/rgba\(0, 0, 0, 0\)/.exec(c))return m.transparent;return m[f.trim(c).toLowerCase()]}function r(c,a){var b;do{b=f.curCSS(c,a);if(b!=""&&b!="transparent"||f.nodeName(c,"body"))break;a="backgroundColor"}while(c=c.parentNode);return l(b)}function n(){var c=document.defaultView?document.defaultView.getComputedStyle(this,null):this.currentStyle, -a={},b,d;if(c&&c.length&&c[0]&&c[c[0]])for(var e=c.length;e--;){b=c[e];if(typeof c[b]=="string"){d=b.replace(/\-(\w)/g,function(g,h){return h.toUpperCase()});a[d]=c[b]}}else for(b in c)if(typeof c[b]==="string")a[b]=c[b];return a}function o(c){var a,b;for(a in c){b=c[a];if(b==null||f.isFunction(b)||a in s||/scrollbar/.test(a)||!/color/i.test(a)&&isNaN(parseFloat(b)))delete c[a]}return c}function t(c,a){var b={_:0},d;for(d in a)if(c[d]!=a[d])b[d]=a[d];return b}function k(c,a,b,d){if(typeof c=="object"){d= -a;b=null;a=c;c=a.effect}if(f.isFunction(a)){d=a;b=null;a={}}if(typeof a=="number"||f.fx.speeds[a]){d=b;b=a;a={}}if(f.isFunction(b)){d=b;b=null}a=a||{};b=b||a.duration;b=f.fx.off?0:typeof b=="number"?b:f.fx.speeds[b]||f.fx.speeds._default;d=d||a.complete;return[c,a,b,d]}f.effects={};f.each(["backgroundColor","borderBottomColor","borderLeftColor","borderRightColor","borderTopColor","color","outlineColor"],function(c,a){f.fx.step[a]=function(b){if(!b.colorInit){b.start=r(b.elem,a);b.end=l(b.end);b.colorInit= -true}b.elem.style[a]="rgb("+Math.max(Math.min(parseInt(b.pos*(b.end[0]-b.start[0])+b.start[0],10),255),0)+","+Math.max(Math.min(parseInt(b.pos*(b.end[1]-b.start[1])+b.start[1],10),255),0)+","+Math.max(Math.min(parseInt(b.pos*(b.end[2]-b.start[2])+b.start[2],10),255),0)+")"}});var m={aqua:[0,255,255],azure:[240,255,255],beige:[245,245,220],black:[0,0,0],blue:[0,0,255],brown:[165,42,42],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgrey:[169,169,169],darkgreen:[0,100,0],darkkhaki:[189, -183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkviolet:[148,0,211],fuchsia:[255,0,255],gold:[255,215,0],green:[0,128,0],indigo:[75,0,130],khaki:[240,230,140],lightblue:[173,216,230],lightcyan:[224,255,255],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightyellow:[255,255,224],lime:[0,255,0],magenta:[255,0,255],maroon:[128,0,0],navy:[0,0,128],olive:[128,128,0],orange:[255, -165,0],pink:[255,192,203],purple:[128,0,128],violet:[128,0,128],red:[255,0,0],silver:[192,192,192],white:[255,255,255],yellow:[255,255,0],transparent:[255,255,255]},p=["add","remove","toggle"],s={border:1,borderBottom:1,borderColor:1,borderLeft:1,borderRight:1,borderTop:1,borderWidth:1,margin:1,padding:1};f.effects.animateClass=function(c,a,b,d){if(f.isFunction(b)){d=b;b=null}return this.each(function(){var e=f(this),g=e.attr("style")||" ",h=o(n.call(this)),q,u=e.attr("className");f.each(p,function(v, -i){c[i]&&e[i+"Class"](c[i])});q=o(n.call(this));e.attr("className",u);e.animate(t(h,q),a,b,function(){f.each(p,function(v,i){c[i]&&e[i+"Class"](c[i])});if(typeof e.attr("style")=="object"){e.attr("style").cssText="";e.attr("style").cssText=g}else e.attr("style",g);d&&d.apply(this,arguments)})})};f.fn.extend({_addClass:f.fn.addClass,addClass:function(c,a,b,d){return a?f.effects.animateClass.apply(this,[{add:c},a,b,d]):this._addClass(c)},_removeClass:f.fn.removeClass,removeClass:function(c,a,b,d){return a? -f.effects.animateClass.apply(this,[{remove:c},a,b,d]):this._removeClass(c)},_toggleClass:f.fn.toggleClass,toggleClass:function(c,a,b,d,e){return typeof a=="boolean"||a===j?b?f.effects.animateClass.apply(this,[a?{add:c}:{remove:c},b,d,e]):this._toggleClass(c,a):f.effects.animateClass.apply(this,[{toggle:c},a,b,d])},switchClass:function(c,a,b,d,e){return f.effects.animateClass.apply(this,[{add:a,remove:c},b,d,e])}});f.extend(f.effects,{version:"1.8.5",save:function(c,a){for(var b=0;b").addClass("ui-effects-wrapper").css({fontSize:"100%",background:"transparent",border:"none",margin:0,padding:0});c.wrap(b);b=c.parent();if(c.css("position")=="static"){b.css({position:"relative"});c.css({position:"relative"})}else{f.extend(a,{position:c.css("position"),zIndex:c.css("z-index")});f.each(["top","left","bottom","right"],function(d,e){a[e]=c.css(e);if(isNaN(parseInt(a[e],10)))a[e]="auto"}); -c.css({position:"relative",top:0,left:0})}return b.css(a).show()},removeWrapper:function(c){if(c.parent().is(".ui-effects-wrapper"))return c.parent().replaceWith(c);return c},setTransition:function(c,a,b,d){d=d||{};f.each(a,function(e,g){unit=c.cssUnit(g);if(unit[0]>0)d[g]=unit[0]*b+unit[1]});return d}});f.fn.extend({effect:function(c){var a=k.apply(this,arguments);a={options:a[1],duration:a[2],callback:a[3]};var b=f.effects[c];return b&&!f.fx.off?b.call(this,a):this},_show:f.fn.show,show:function(c){if(!c|| -typeof c=="number"||f.fx.speeds[c]||!f.effects[c])return this._show.apply(this,arguments);else{var a=k.apply(this,arguments);a[1].mode="show";return this.effect.apply(this,a)}},_hide:f.fn.hide,hide:function(c){if(!c||typeof c=="number"||f.fx.speeds[c]||!f.effects[c])return this._hide.apply(this,arguments);else{var a=k.apply(this,arguments);a[1].mode="hide";return this.effect.apply(this,a)}},__toggle:f.fn.toggle,toggle:function(c){if(!c||typeof c=="number"||f.fx.speeds[c]||!f.effects[c]||typeof c== -"boolean"||f.isFunction(c))return this.__toggle.apply(this,arguments);else{var a=k.apply(this,arguments);a[1].mode="toggle";return this.effect.apply(this,a)}},cssUnit:function(c){var a=this.css(c),b=[];f.each(["em","px","%","pt"],function(d,e){if(a.indexOf(e)>0)b=[parseFloat(a),e]});return b}});f.easing.jswing=f.easing.swing;f.extend(f.easing,{def:"easeOutQuad",swing:function(c,a,b,d,e){return f.easing[f.easing.def](c,a,b,d,e)},easeInQuad:function(c,a,b,d,e){return d*(a/=e)*a+b},easeOutQuad:function(c, -a,b,d,e){return-d*(a/=e)*(a-2)+b},easeInOutQuad:function(c,a,b,d,e){if((a/=e/2)<1)return d/2*a*a+b;return-d/2*(--a*(a-2)-1)+b},easeInCubic:function(c,a,b,d,e){return d*(a/=e)*a*a+b},easeOutCubic:function(c,a,b,d,e){return d*((a=a/e-1)*a*a+1)+b},easeInOutCubic:function(c,a,b,d,e){if((a/=e/2)<1)return d/2*a*a*a+b;return d/2*((a-=2)*a*a+2)+b},easeInQuart:function(c,a,b,d,e){return d*(a/=e)*a*a*a+b},easeOutQuart:function(c,a,b,d,e){return-d*((a=a/e-1)*a*a*a-1)+b},easeInOutQuart:function(c,a,b,d,e){if((a/= -e/2)<1)return d/2*a*a*a*a+b;return-d/2*((a-=2)*a*a*a-2)+b},easeInQuint:function(c,a,b,d,e){return d*(a/=e)*a*a*a*a+b},easeOutQuint:function(c,a,b,d,e){return d*((a=a/e-1)*a*a*a*a+1)+b},easeInOutQuint:function(c,a,b,d,e){if((a/=e/2)<1)return d/2*a*a*a*a*a+b;return d/2*((a-=2)*a*a*a*a+2)+b},easeInSine:function(c,a,b,d,e){return-d*Math.cos(a/e*(Math.PI/2))+d+b},easeOutSine:function(c,a,b,d,e){return d*Math.sin(a/e*(Math.PI/2))+b},easeInOutSine:function(c,a,b,d,e){return-d/2*(Math.cos(Math.PI*a/e)-1)+ -b},easeInExpo:function(c,a,b,d,e){return a==0?b:d*Math.pow(2,10*(a/e-1))+b},easeOutExpo:function(c,a,b,d,e){return a==e?b+d:d*(-Math.pow(2,-10*a/e)+1)+b},easeInOutExpo:function(c,a,b,d,e){if(a==0)return b;if(a==e)return b+d;if((a/=e/2)<1)return d/2*Math.pow(2,10*(a-1))+b;return d/2*(-Math.pow(2,-10*--a)+2)+b},easeInCirc:function(c,a,b,d,e){return-d*(Math.sqrt(1-(a/=e)*a)-1)+b},easeOutCirc:function(c,a,b,d,e){return d*Math.sqrt(1-(a=a/e-1)*a)+b},easeInOutCirc:function(c,a,b,d,e){if((a/=e/2)<1)return-d/ -2*(Math.sqrt(1-a*a)-1)+b;return d/2*(Math.sqrt(1-(a-=2)*a)+1)+b},easeInElastic:function(c,a,b,d,e){c=1.70158;var g=0,h=d;if(a==0)return b;if((a/=e)==1)return b+d;g||(g=e*0.3);if(h").css({position:"absolute",visibility:"visible",left:-f*(h/d),top:-e*(i/c)}).parent().addClass("ui-effects-explode").css({position:"absolute",overflow:"hidden",width:h/d,height:i/c,left:g.left+f*(h/d)+(a.options.mode=="show"?(f-Math.floor(d/2))*(h/d):0),top:g.top+e*(i/c)+(a.options.mode=="show"?(e-Math.floor(c/2))*(i/c):0),opacity:a.options.mode=="show"?0:1}).animate({left:g.left+f*(h/d)+(a.options.mode=="show"?0:(f-Math.floor(d/2))*(h/d)),top:g.top+ -e*(i/c)+(a.options.mode=="show"?0:(e-Math.floor(c/2))*(i/c)),opacity:a.options.mode=="show"?1:0},a.duration||500);setTimeout(function(){a.options.mode=="show"?b.css({visibility:"visible"}):b.css({visibility:"visible"}).hide();a.callback&&a.callback.apply(b[0]);b.dequeue();j("div.ui-effects-explode").remove()},a.duration||500)})}})(jQuery); -;/* - * jQuery UI Effects Fade 1.8.5 - * - * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Effects/Fade - * - * Depends: - * jquery.effects.core.js - */ -(function(b){b.effects.fade=function(a){return this.queue(function(){var c=b(this),d=b.effects.setMode(c,a.options.mode||"hide");c.animate({opacity:d},{queue:false,duration:a.duration,easing:a.options.easing,complete:function(){a.callback&&a.callback.apply(this,arguments);c.dequeue()}})})}})(jQuery); -;/* - * jQuery UI Effects Fold 1.8.5 - * - * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Effects/Fold - * - * Depends: - * jquery.effects.core.js - */ -(function(c){c.effects.fold=function(a){return this.queue(function(){var b=c(this),j=["position","top","left"],d=c.effects.setMode(b,a.options.mode||"hide"),g=a.options.size||15,h=!!a.options.horizFirst,k=a.duration?a.duration/2:c.fx.speeds._default/2;c.effects.save(b,j);b.show();var e=c.effects.createWrapper(b).css({overflow:"hidden"}),f=d=="show"!=h,l=f?["width","height"]:["height","width"];f=f?[e.width(),e.height()]:[e.height(),e.width()];var i=/([0-9]+)%/.exec(g);if(i)g=parseInt(i[1],10)/100* -f[d=="hide"?0:1];if(d=="show")e.css(h?{height:0,width:g}:{height:g,width:0});h={};i={};h[l[0]]=d=="show"?f[0]:g;i[l[1]]=d=="show"?f[1]:0;e.animate(h,k,a.options.easing).animate(i,k,a.options.easing,function(){d=="hide"&&b.hide();c.effects.restore(b,j);c.effects.removeWrapper(b);a.callback&&a.callback.apply(b[0],arguments);b.dequeue()})})}})(jQuery); -;/* - * jQuery UI Effects Highlight 1.8.5 - * - * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Effects/Highlight - * - * Depends: - * jquery.effects.core.js - */ -(function(b){b.effects.highlight=function(c){return this.queue(function(){var a=b(this),e=["backgroundImage","backgroundColor","opacity"],d=b.effects.setMode(a,c.options.mode||"show"),f={backgroundColor:a.css("backgroundColor")};if(d=="hide")f.opacity=0;b.effects.save(a,e);a.show().css({backgroundImage:"none",backgroundColor:c.options.color||"#ffff99"}).animate(f,{queue:false,duration:c.duration,easing:c.options.easing,complete:function(){d=="hide"&&a.hide();b.effects.restore(a,e);d=="show"&&!b.support.opacity&& -this.style.removeAttribute("filter");c.callback&&c.callback.apply(this,arguments);a.dequeue()}})})}})(jQuery); -;/* - * jQuery UI Effects Pulsate 1.8.5 - * - * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Effects/Pulsate - * - * Depends: - * jquery.effects.core.js - */ -(function(d){d.effects.pulsate=function(a){return this.queue(function(){var b=d(this),c=d.effects.setMode(b,a.options.mode||"show");times=(a.options.times||5)*2-1;duration=a.duration?a.duration/2:d.fx.speeds._default/2;isVisible=b.is(":visible");animateTo=0;if(!isVisible){b.css("opacity",0).show();animateTo=1}if(c=="hide"&&isVisible||c=="show"&&!isVisible)times--;for(c=0;c').appendTo(document.body).addClass(a.options.className).css({top:d.top,left:d.left,height:b.innerHeight(),width:b.innerWidth(),position:"absolute"}).animate(c,a.duration,a.options.easing,function(){f.remove();a.callback&&a.callback.apply(b[0],arguments); -b.dequeue()})})}})(jQuery); +(function(c,j){c.widget("ui.dialog",{options:{autoOpen:true,buttons:{},closeOnEscape:true,closeText:"close",dialogClass:"",draggable:true,hide:null,height:"auto",maxHeight:false,maxWidth:false,minHeight:150,minWidth:150,modal:false,position:{my:"center",at:"center",of:window,collision:"fit",using:function(a){var b=c(this).css(a).offset().top;b<0&&c(this).css("top",a.top-b)}},resizable:true,show:null,stack:true,title:"",width:300,zIndex:1E3},_create:function(){this.originalTitle=this.element.attr("title"); +if(typeof this.originalTitle!=="string")this.originalTitle="";this.options.title=this.options.title||this.originalTitle;var a=this,b=a.options,d=b.title||" ",f=c.ui.dialog.getTitleId(a.element),g=(a.uiDialog=c("
")).appendTo(document.body).hide().addClass("ui-dialog ui-widget ui-widget-content ui-corner-all "+b.dialogClass).css({zIndex:b.zIndex}).attr("tabIndex",-1).css("outline",0).keydown(function(i){if(b.closeOnEscape&&i.keyCode&&i.keyCode===c.ui.keyCode.ESCAPE){a.close(i);i.preventDefault()}}).attr({role:"dialog", +"aria-labelledby":f}).mousedown(function(i){a.moveToTop(false,i)});a.element.show().removeAttr("title").addClass("ui-dialog-content ui-widget-content").appendTo(g);var e=(a.uiDialogTitlebar=c("
")).addClass("ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix").prependTo(g),h=c('').addClass("ui-dialog-titlebar-close ui-corner-all").attr("role","button").hover(function(){h.addClass("ui-state-hover")},function(){h.removeClass("ui-state-hover")}).focus(function(){h.addClass("ui-state-focus")}).blur(function(){h.removeClass("ui-state-focus")}).click(function(i){a.close(i); +return false}).appendTo(e);(a.uiDialogTitlebarCloseText=c("")).addClass("ui-icon ui-icon-closethick").text(b.closeText).appendTo(h);c("").addClass("ui-dialog-title").attr("id",f).html(d).prependTo(e);if(c.isFunction(b.beforeclose)&&!c.isFunction(b.beforeClose))b.beforeClose=b.beforeclose;e.find("*").add(e).disableSelection();b.draggable&&c.fn.draggable&&a._makeDraggable();b.resizable&&c.fn.resizable&&a._makeResizable();a._createButtons(b.buttons);a._isOpen=false;c.fn.bgiframe&& +g.bgiframe()},_init:function(){this.options.autoOpen&&this.open()},destroy:function(){var a=this;a.overlay&&a.overlay.destroy();a.uiDialog.hide();a.element.unbind(".dialog").removeData("dialog").removeClass("ui-dialog-content ui-widget-content").hide().appendTo("body");a.uiDialog.remove();a.originalTitle&&a.element.attr("title",a.originalTitle);return a},widget:function(){return this.uiDialog},close:function(a){var b=this,d;if(false!==b._trigger("beforeClose",a)){b.overlay&&b.overlay.destroy();b.uiDialog.unbind("keypress.ui-dialog"); +b._isOpen=false;if(b.options.hide)b.uiDialog.hide(b.options.hide,function(){b._trigger("close",a)});else{b.uiDialog.hide();b._trigger("close",a)}c.ui.dialog.overlay.resize();if(b.options.modal){d=0;c(".ui-dialog").each(function(){if(this!==b.uiDialog[0])d=Math.max(d,c(this).css("z-index"))});c.ui.dialog.maxZ=d}return b}},isOpen:function(){return this._isOpen},moveToTop:function(a,b){var d=this,f=d.options;if(f.modal&&!a||!f.stack&&!f.modal)return d._trigger("focus",b);if(f.zIndex>c.ui.dialog.maxZ)c.ui.dialog.maxZ= +f.zIndex;if(d.overlay){c.ui.dialog.maxZ+=1;d.overlay.$el.css("z-index",c.ui.dialog.overlay.maxZ=c.ui.dialog.maxZ)}a={scrollTop:d.element.attr("scrollTop"),scrollLeft:d.element.attr("scrollLeft")};c.ui.dialog.maxZ+=1;d.uiDialog.css("z-index",c.ui.dialog.maxZ);d.element.attr(a);d._trigger("focus",b);return d},open:function(){if(!this._isOpen){var a=this,b=a.options,d=a.uiDialog;a.overlay=b.modal?new c.ui.dialog.overlay(a):null;d.next().length&&d.appendTo("body");a._size();a._position(b.position);d.show(b.show); +a.moveToTop(true);b.modal&&d.bind("keypress.ui-dialog",function(f){if(f.keyCode===c.ui.keyCode.TAB){var g=c(":tabbable",this),e=g.filter(":first");g=g.filter(":last");if(f.target===g[0]&&!f.shiftKey){e.focus(1);return false}else if(f.target===e[0]&&f.shiftKey){g.focus(1);return false}}});c(a.element.find(":tabbable").get().concat(d.find(".ui-dialog-buttonpane :tabbable").get().concat(d.get()))).eq(0).focus();a._isOpen=true;a._trigger("open");return a}},_createButtons:function(a){var b=this,d=false, +f=c("
").addClass("ui-dialog-buttonpane ui-widget-content ui-helper-clearfix"),g=c("
").addClass("ui-dialog-buttonset").appendTo(f);b.uiDialog.find(".ui-dialog-buttonpane").remove();typeof a==="object"&&a!==null&&c.each(a,function(){return!(d=true)});if(d){c.each(a,function(e,h){h=c.isFunction(h)?{click:h,text:e}:h;e=c("",h).unbind("click").click(function(){h.click.apply(b.element[0],arguments)}).appendTo(g);c.fn.button&&e.button()});f.appendTo(b.uiDialog)}},_makeDraggable:function(){function a(e){return{position:e.position, +offset:e.offset}}var b=this,d=b.options,f=c(document),g;b.uiDialog.draggable({cancel:".ui-dialog-content, .ui-dialog-titlebar-close",handle:".ui-dialog-titlebar",containment:"document",start:function(e,h){g=d.height==="auto"?"auto":c(this).height();c(this).height(c(this).height()).addClass("ui-dialog-dragging");b._trigger("dragStart",e,a(h))},drag:function(e,h){b._trigger("drag",e,a(h))},stop:function(e,h){d.position=[h.position.left-f.scrollLeft(),h.position.top-f.scrollTop()];c(this).removeClass("ui-dialog-dragging").height(g); +b._trigger("dragStop",e,a(h));c.ui.dialog.overlay.resize()}})},_makeResizable:function(a){function b(e){return{originalPosition:e.originalPosition,originalSize:e.originalSize,position:e.position,size:e.size}}a=a===j?this.options.resizable:a;var d=this,f=d.options,g=d.uiDialog.css("position");a=typeof a==="string"?a:"n,e,s,w,se,sw,ne,nw";d.uiDialog.resizable({cancel:".ui-dialog-content",containment:"document",alsoResize:d.element,maxWidth:f.maxWidth,maxHeight:f.maxHeight,minWidth:f.minWidth,minHeight:d._minHeight(), +handles:a,start:function(e,h){c(this).addClass("ui-dialog-resizing");d._trigger("resizeStart",e,b(h))},resize:function(e,h){d._trigger("resize",e,b(h))},stop:function(e,h){c(this).removeClass("ui-dialog-resizing");f.height=c(this).height();f.width=c(this).width();d._trigger("resizeStop",e,b(h));c.ui.dialog.overlay.resize()}}).css("position",g).find(".ui-resizable-se").addClass("ui-icon ui-icon-grip-diagonal-se")},_minHeight:function(){var a=this.options;return a.height==="auto"?a.minHeight:Math.min(a.minHeight, +a.height)},_position:function(a){var b=[],d=[0,0],f;if(a){if(typeof a==="string"||typeof a==="object"&&"0"in a){b=a.split?a.split(" "):[a[0],a[1]];if(b.length===1)b[1]=b[0];c.each(["left","top"],function(g,e){if(+b[g]===b[g]){d[g]=b[g];b[g]=e}});a={my:b.join(" "),at:b.join(" "),offset:d.join(" ")}}a=c.extend({},c.ui.dialog.prototype.options.position,a)}else a=c.ui.dialog.prototype.options.position;(f=this.uiDialog.is(":visible"))||this.uiDialog.show();this.uiDialog.css({top:0,left:0}).position(a); +f||this.uiDialog.hide()},_setOption:function(a,b){var d=this,f=d.uiDialog,g=f.is(":data(resizable)"),e=false;switch(a){case "beforeclose":a="beforeClose";break;case "buttons":d._createButtons(b);e=true;break;case "closeText":d.uiDialogTitlebarCloseText.text(""+b);break;case "dialogClass":f.removeClass(d.options.dialogClass).addClass("ui-dialog ui-widget ui-widget-content ui-corner-all "+b);break;case "disabled":b?f.addClass("ui-dialog-disabled"):f.removeClass("ui-dialog-disabled");break;case "draggable":b? +d._makeDraggable():f.draggable("destroy");break;case "height":e=true;break;case "maxHeight":g&&f.resizable("option","maxHeight",b);e=true;break;case "maxWidth":g&&f.resizable("option","maxWidth",b);e=true;break;case "minHeight":g&&f.resizable("option","minHeight",b);e=true;break;case "minWidth":g&&f.resizable("option","minWidth",b);e=true;break;case "position":d._position(b);break;case "resizable":g&&!b&&f.resizable("destroy");g&&typeof b==="string"&&f.resizable("option","handles",b);!g&&b!==false&& +d._makeResizable(b);break;case "title":c(".ui-dialog-title",d.uiDialogTitlebar).html(""+(b||" "));break;case "width":e=true;break}c.Widget.prototype._setOption.apply(d,arguments);e&&d._size()},_size:function(){var a=this.options,b;this.element.css({width:"auto",minHeight:0,height:0});if(a.minWidth>a.width)a.width=a.minWidth;b=this.uiDialog.css({height:"auto",width:a.width}).height();this.element.css(a.height==="auto"?{minHeight:Math.max(a.minHeight-b,0),height:c.support.minHeight?"auto":Math.max(a.minHeight- +b,0)}:{minHeight:0,height:Math.max(a.height-b,0)}).show();this.uiDialog.is(":data(resizable)")&&this.uiDialog.resizable("option","minHeight",this._minHeight())}});c.extend(c.ui.dialog,{version:"1.8.5",uuid:0,maxZ:0,getTitleId:function(a){a=a.attr("id");if(!a){this.uuid+=1;a=this.uuid}return"ui-dialog-title-"+a},overlay:function(a){this.$el=c.ui.dialog.overlay.create(a)}});c.extend(c.ui.dialog.overlay,{instances:[],oldInstances:[],maxZ:0,events:c.map("focus,mousedown,mouseup,keydown,keypress,click".split(","), +function(a){return a+".dialog-overlay"}).join(" "),create:function(a){if(this.instances.length===0){setTimeout(function(){c.ui.dialog.overlay.instances.length&&c(document).bind(c.ui.dialog.overlay.events,function(d){if(c(d.target).zIndex()").addClass("ui-widget-overlay")).appendTo(document.body).css({width:this.width(),height:this.height()});c.fn.bgiframe&&b.bgiframe();this.instances.push(b);return b},destroy:function(a){this.oldInstances.push(this.instances.splice(c.inArray(a,this.instances),1)[0]);this.instances.length===0&&c([document,window]).unbind(".dialog-overlay");a.remove();var b=0;c.each(this.instances,function(){b=Math.max(b,this.css("z-index"))});this.maxZ=b},height:function(){var a, +b;if(c.browser.msie&&c.browser.version<7){a=Math.max(document.documentElement.scrollHeight,document.body.scrollHeight);b=Math.max(document.documentElement.offsetHeight,document.body.offsetHeight);return a Date: Fri, 15 Oct 2010 19:57:41 -0600 Subject: [PATCH 12/19] /browse: Show category being currently listed and hide sort combobox in newest book list --- resources/content_server/browse/browse.js | 3 ++- src/calibre/library/server/browse.py | 16 ++++++++++------ 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/resources/content_server/browse/browse.js b/resources/content_server/browse/browse.js index 397db397bf..5e0d9f8ee4 100644 --- a/resources/content_server/browse/browse.js +++ b/resources/content_server/browse/browse.js @@ -193,7 +193,8 @@ function load_page(elem) { elem.show(); } -function booklist() { +function booklist(hide_sort) { + if (hide_sort) $("#content > .sort_select").hide(); var test = $("#booklist #page0").html(); if (!test) { $("#booklist").html(render_error("No books found")); diff --git a/src/calibre/library/server/browse.py b/src/calibre/library/server/browse.py index 69a931b1e2..c8c816d617 100644 --- a/src/calibre/library/server/browse.py +++ b/src/calibre/library/server/browse.py @@ -18,7 +18,7 @@ from calibre.utils.filenames import ascii_filename from calibre.utils.config import prefs from calibre.library.comments import comments_to_html -def render_book_list(ids): # {{{ +def render_book_list(ids, suffix=''): # {{{ pages = [] num = len(ids) pos = 0 @@ -49,7 +49,7 @@ def render_book_list(ids): # {{{ rpages = u'\n\n'.join(rpages) templ = u'''\ -

{0}

+

{0} {suffix}

{navbar} @@ -76,7 +76,8 @@ def render_book_list(ids): # {{{ '''.format(first=_('First'), last=_('Last'), previous=_('Previous'), next=_('Next'), num=num) - return templ.format(_('Browsing %d books')%num, pages=rpages, navbar=navbar) + return templ.format(_('Browsing %d books')%num, suffix=suffix, + pages=rpages, navbar=navbar) # }}} @@ -420,6 +421,7 @@ class BrowseServer(object): raise category_name = _('Newest') + hide_sort = 'false' if category == 'search': which = unhexlify(cid) try: @@ -428,6 +430,7 @@ class BrowseServer(object): raise cherrypy.HTTPError(404, 'Search: %r not understood'%which) elif category == 'newest': ids = list(self.db.data.iterallids()) + hide_sort = 'true' else: ids = self.db.get_books_for_category(category, cid) @@ -436,10 +439,11 @@ class BrowseServer(object): list_sort = 'timestamp' sort = self.browse_sort_book_list(items, list_sort) ids = [x[0] for x in items] - html = render_book_list(ids) + html = render_book_list(ids, suffix=_('in') + ' ' + category_name) + return self.browse_template(sort, category=False).format( title=_('Books in') + " " +category_name, - script='booklist();', main=html) + script='booklist(%s);'%hide_sort, main=html) @Endpoint(mimetype='application/json; charset=utf-8') def browse_booklist_page(self, ids=None, sort=None): @@ -509,7 +513,7 @@ class BrowseServer(object): items = [self.db.data._data[x] for x in ids] sort = self.browse_sort_book_list(items, list_sort) ids = [x[0] for x in items] - html = render_book_list(ids) + html = render_book_list(ids, suffix=_('in search')+': '+query) return self.browse_template(sort, category=False, initial_search=query).format( title=_('Matching books'), script='booklist();', main=html) From 5c02ca217343ee71004dfdcb1e8d19f653134b97 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Fri, 15 Oct 2010 19:59:29 -0600 Subject: [PATCH 13/19] ... --- src/calibre/library/server/browse.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/calibre/library/server/browse.py b/src/calibre/library/server/browse.py index c8c816d617..439c0f4cf2 100644 --- a/src/calibre/library/server/browse.py +++ b/src/calibre/library/server/browse.py @@ -191,6 +191,7 @@ class BrowseServer(object): connect('browse_search', base_href+'/search', self.browse_search) + # Templates {{{ def browse_template(self, sort, category=True, initial_search=''): def generate(): @@ -243,6 +244,7 @@ class BrowseServer(object): P('content_server/browse/summary.html', data=True).decode('utf-8') return self.__browse_summary_template__ + # }}} # Catalogs {{{ def browse_toplevel(self): From 5b1cfa68650b742fabf781b5cc011433e1581ea7 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Fri, 15 Oct 2010 20:49:57 -0600 Subject: [PATCH 14/19] ... --- resources/content_server/browse/browse.css | 12 +++-- resources/content_server/browse/browse.html | 1 + resources/content_server/browse/browse.js | 15 +++++- resources/content_server/browse/summary.html | 6 ++- .../images/ui-bg_glass_100_f5f0e5_1x400.png | Bin 157 -> 123 bytes .../images/ui-bg_glass_70_ede4d4_1x400.png | Bin 125 -> 161 bytes .../ui-bg_inset-soft_100_f4f0ec_1x100.png | Bin 141 -> 113 bytes .../images/ui-icons_f08000_256x240.png | Bin 5355 -> 4369 bytes .../images/ui-icons_f35f07_256x240.png | Bin 4369 -> 5355 bytes .../images/ui-icons_ff7519_256x240.png | Bin 4369 -> 5355 bytes .../jquery-ui-1.8.5.custom.css | 44 +++++++++++++++++- src/calibre/library/server/browse.py | 6 ++- 12 files changed, 76 insertions(+), 8 deletions(-) diff --git a/resources/content_server/browse/browse.css b/resources/content_server/browse/browse.css index f3dfc89caf..aceb595383 100644 --- a/resources/content_server/browse/browse.css +++ b/resources/content_server/browse/browse.css @@ -309,21 +309,27 @@ h2.library_name { display: block; } +#booklist div.right .stars .series { + display: block; +} + #booklist .title { font-size: larger; } -#booklist .formats a { +#booklist a { text-decoration: none; color: blue; } -#booklist .formats a:hover { +#booklist a:hover { color: red; } + #booklist .left .ui-button-text { - font-weight: bold; + font-size: medium; + color: black; padding-left: 0.25em; padding-right: 0.25em; padding-top: 0.25em; diff --git a/resources/content_server/browse/browse.html b/resources/content_server/browse/browse.html index 8c6d310015..b3039f8c4e 100644 --- a/resources/content_server/browse/browse.html +++ b/resources/content_server/browse/browse.html @@ -94,5 +94,6 @@
+ diff --git a/resources/content_server/browse/browse.js b/resources/content_server/browse/browse.js index 5e0d9f8ee4..9d3c01fa15 100644 --- a/resources/content_server/browse/browse.js +++ b/resources/content_server/browse/browse.js @@ -200,8 +200,21 @@ function booklist(hide_sort) { $("#booklist").html(render_error("No books found")); return; } - + $("#book_details_dialog").dialog({ + autoOpen: false, + modal: true + }); first_page(); } +function show_details(a_dom) { + var book = $(a_dom).closest('div.summary'); + var id = book.attr('id').split('_')[1]; + var bd = $('#book_details_dialog'); + bd.attr('title', 'test'); + bd.html('test'); + bd.dialog('option', 'width', $('#container').width() - 50); + bd.dialog('open'); +} + // }}} diff --git a/resources/content_server/browse/summary.html b/resources/content_server/browse/summary.html index 01f2b333f2..8df42de366 100644 --- a/resources/content_server/browse/summary.html +++ b/resources/content_server/browse/summary.html @@ -4,7 +4,11 @@ {read_string}
-
{stars}{series}
+
+ {stars} + {series} + {details} +
{title}
{authors}
{comments}
diff --git a/resources/content_server/jquery_ui/css/humanity-custom/images/ui-bg_glass_100_f5f0e5_1x400.png b/resources/content_server/jquery_ui/css/humanity-custom/images/ui-bg_glass_100_f5f0e5_1x400.png index 688c2f3e8806f3afcc0b659d397d142ee4a0bb1c..4fb71be1b40892d5b6ef1e4091104a876a9892f6 100644 GIT binary patch delta 101 zcmV-r0Gj`u0eg@fUjT1d3flkx076MbK~y-6?awg^fKUts(V4yfUF|+7f)?_%u@_{U z$0Vc)>sXEelu~}nzKuC55oZ|!5|ve*qX@I!yoo0Axu-K~y-6?a?s`!!Qs;(Z63-Ain=S-6_bCiJKHT zfUyKh^VqF+hNYJ6BR~(@UNGe+njSYFr)%@0Rb29lgi|%|N_)RhGnz7n%Lu7%VB(+8 qOWO-Zh++Dj2)`@D2uc53#0gdk9<2slO@jac002ovPDHLk0$_qBz&J<% diff --git a/resources/content_server/jquery_ui/css/humanity-custom/images/ui-bg_glass_70_ede4d4_1x400.png b/resources/content_server/jquery_ui/css/humanity-custom/images/ui-bg_glass_70_ede4d4_1x400.png index 779ef0d0e24ce761cdbf952b5f1db4c80face3fe..0b4ae4776b3627a480c7fa2a04a7198c9a8f6584 100644 GIT binary patch delta 140 zcmV;70CWF+p#hK_e*qX@I!yoo0BA`>K~y-6?a@IB!axv2(ciz@D1!Gto(FK{A|W9W z-Q)<85ys7A%C=0HHSC1-3#|^I uCuV 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 delta 5037 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 diff --git a/resources/content_server/jquery_ui/css/humanity-custom/images/ui-icons_ff7519_256x240.png b/resources/content_server/jquery_ui/css/humanity-custom/images/ui-icons_ff7519_256x240.png index 544517142205f1adfc22b44eda10028e10abd42c..5a4070af92983caef197fffc854029b8047b31e7 100644 GIT binary patch delta 5037 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 diff --git a/resources/content_server/jquery_ui/css/humanity-custom/jquery-ui-1.8.5.custom.css b/resources/content_server/jquery_ui/css/humanity-custom/jquery-ui-1.8.5.custom.css index f1625b027f..6b221bca77 100644 --- a/resources/content_server/jquery_ui/css/humanity-custom/jquery-ui-1.8.5.custom.css +++ b/resources/content_server/jquery_ui/css/humanity-custom/jquery-ui-1.8.5.custom.css @@ -50,13 +50,13 @@ * * http://docs.jquery.com/UI/Theming/API * - * To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Verdana,Arial,sans-serif&fwDefault=normal&fsDefault=1em&cornerRadius=6px&bgColorHeader=cb842e&bgTextureHeader=02_glass.png&bgImgOpacityHeader=25&borderColorHeader=d49768&fcHeader=ffffff&iconColorHeader=ffffff&bgColorContent=f4f0ec&bgTextureContent=05_inset_soft.png&bgImgOpacityContent=100&borderColorContent=e0cfc2&fcContent=1e1b1d&iconColorContent=c47a23&bgColorDefault=ede4d4&bgTextureDefault=02_glass.png&bgImgOpacityDefault=70&borderColorDefault=cdc3b7&fcDefault=3f3731&iconColorDefault=f08000&bgColorHover=f5f0e5&bgTextureHover=02_glass.png&bgImgOpacityHover=100&borderColorHover=f5ad66&fcHover=a46313&iconColorHover=f08000&bgColorActive=f4f0ec&bgTextureActive=04_highlight_hard.png&bgImgOpacityActive=100&borderColorActive=e0cfc2&fcActive=b85700&iconColorActive=f35f07&bgColorHighlight=f5f5b5&bgTextureHighlight=04_highlight_hard.png&bgImgOpacityHighlight=75&borderColorHighlight=d9bb73&fcHighlight=060200&iconColorHighlight=cb672b&bgColorError=fee4bd&bgTextureError=04_highlight_hard.png&bgImgOpacityError=65&borderColorError=f8893f&fcError=592003&iconColorError=ff7519&bgColorOverlay=aaaaaa&bgTextureOverlay=01_flat.png&bgImgOpacityOverlay=75&opacityOverlay=30&bgColorShadow=aaaaaa&bgTextureShadow=01_flat.png&bgImgOpacityShadow=75&opacityShadow=30&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=8px + * To view and modify this theme, visit http://jqueryui.com/themeroller/?tr=ffDefault=Helvetica,Arial,sans-serif&fwDefault=normal&fsDefault=1.1em&cornerRadius=6px&bgColorHeader=cb842e&bgTextureHeader=02_glass.png&bgImgOpacityHeader=25&borderColorHeader=d49768&fcHeader=ffffff&iconColorHeader=ffffff&bgColorContent=f4f0ec&bgTextureContent=05_inset_soft.png&bgImgOpacityContent=100&borderColorContent=e0cfc2&fcContent=1e1b1d&iconColorContent=c47a23&bgColorDefault=ede4d4&bgTextureDefault=02_glass.png&bgImgOpacityDefault=70&borderColorDefault=cdc3b7&fcDefault=3f3731&iconColorDefault=f08000&bgColorHover=f5f0e5&bgTextureHover=02_glass.png&bgImgOpacityHover=100&borderColorHover=f5ad66&fcHover=a46313&iconColorHover=f08000&bgColorActive=f4f0ec&bgTextureActive=04_highlight_hard.png&bgImgOpacityActive=100&borderColorActive=e0cfc2&fcActive=b85700&iconColorActive=f35f07&bgColorHighlight=f5f5b5&bgTextureHighlight=04_highlight_hard.png&bgImgOpacityHighlight=75&borderColorHighlight=d9bb73&fcHighlight=060200&iconColorHighlight=cb672b&bgColorError=fee4bd&bgTextureError=04_highlight_hard.png&bgImgOpacityError=65&borderColorError=f8893f&fcError=592003&iconColorError=ff7519&bgColorOverlay=aaaaaa&bgTextureOverlay=01_flat.png&bgImgOpacityOverlay=75&opacityOverlay=30&bgColorShadow=aaaaaa&bgTextureShadow=01_flat.png&bgImgOpacityShadow=75&opacityShadow=30&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=8px */ /* Component containers ----------------------------------*/ -.ui-widget { font-family: Verdana,Arial,sans-serif; font-size: 1em; } +.ui-widget { font-family: Verdana,Arial,sans-serif; font-size: 1.1em; } .ui-widget .ui-widget { font-size: 1em; } .ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Verdana,Arial,sans-serif; font-size: 1em; } .ui-widget-content { border: 1px solid #e0cfc2; background: #f4f0ec url(images/ui-bg_inset-soft_100_f4f0ec_1x100.png) 50% bottom repeat-x; color: #1e1b1d; } @@ -293,6 +293,25 @@ /* Overlays */ .ui-widget-overlay { background: #aaaaaa url(images/ui-bg_flat_75_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); } .ui-widget-shadow { margin: -8px 0 0 -8px; padding: 8px; background: #aaaaaa url(images/ui-bg_flat_75_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); -moz-border-radius: 8px; -webkit-border-radius: 8px; border-radius: 8px; }/* + * jQuery UI Resizable @VERSION + * + * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Resizable#theming + */ +.ui-resizable { position: relative;} +.ui-resizable-handle { position: absolute;font-size: 0.1px;z-index: 99999; display: block;} +.ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle { display: none; } +.ui-resizable-n { cursor: n-resize; height: 7px; width: 100%; top: -5px; left: 0; } +.ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0; } +.ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0; height: 100%; } +.ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0; height: 100%; } +.ui-resizable-se { cursor: se-resize; width: 12px; height: 12px; right: 1px; bottom: 1px; } +.ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: -5px; bottom: -5px; } +.ui-resizable-nw { cursor: nw-resize; width: 9px; height: 9px; left: -5px; top: -5px; } +.ui-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: -5px; top: -5px;}/* * jQuery UI Accordion @VERSION * * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) @@ -348,3 +367,24 @@ input.ui-button { padding: .4em 1em; } /* workarounds */ button.ui-button::-moz-focus-inner { border: 0; padding: 0; } /* reset extra padding in Firefox */ +/* + * jQuery UI Dialog @VERSION + * + * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Dialog#theming + */ +.ui-dialog { position: absolute; padding: .2em; width: 300px; overflow: hidden; } +.ui-dialog .ui-dialog-titlebar { padding: .5em 1em .3em; position: relative; } +.ui-dialog .ui-dialog-title { float: left; margin: .1em 16px .2em 0; } +.ui-dialog .ui-dialog-titlebar-close { position: absolute; right: .3em; top: 50%; width: 19px; margin: -10px 0 0 0; padding: 1px; height: 18px; } +.ui-dialog .ui-dialog-titlebar-close span { display: block; margin: 1px; } +.ui-dialog .ui-dialog-titlebar-close:hover, .ui-dialog .ui-dialog-titlebar-close:focus { padding: 0; } +.ui-dialog .ui-dialog-content { position: relative; border: 0; padding: .5em 1em; background: none; overflow: auto; zoom: 1; } +.ui-dialog .ui-dialog-buttonpane { text-align: left; border-width: 1px 0 0 0; background-image: none; margin: .5em 0 0 0; padding: .3em 1em .5em .4em; } +.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset { float: right; } +.ui-dialog .ui-dialog-buttonpane button { margin: .5em .4em .5em 0; cursor: pointer; } +.ui-dialog .ui-resizable-se { width: 14px; height: 14px; right: 3px; bottom: 3px; } +.ui-draggable .ui-dialog-titlebar { cursor: move; } diff --git a/src/calibre/library/server/browse.py b/src/calibre/library/server/browse.py index 439c0f4cf2..7d476ade3b 100644 --- a/src/calibre/library/server/browse.py +++ b/src/calibre/library/server/browse.py @@ -470,7 +470,11 @@ class BrowseServer(object): fmts = [x.lower() for x in fmts.split(',') if x] pf = prefs['output_format'].lower() fmt = pf if pf in fmts else fmts[0] - args = {'id':id_, 'mi':mi, 'read_string':_('Read'),} + args = {'id':id_, 'mi':mi, + 'read_string':xml(_('Read'), True), + 'details': xml(_('Details'), True), + 'details_tt': xml(_('Show book details'), True) + } for key in mi.all_field_keys(): val = mi.format_field(key)[1] if not val: From a657a3fb67f0593f89003d3b49fc8f4ae45cefd8 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Fri, 15 Oct 2010 21:02:18 -0600 Subject: [PATCH 15/19] ... --- resources/content_server/browse/browse.js | 9 +- .../js/jquery-ui-1.8.5.custom.min.js | 219 ++++++++++++++++++ 2 files changed, 225 insertions(+), 3 deletions(-) diff --git a/resources/content_server/browse/browse.js b/resources/content_server/browse/browse.js index 9d3c01fa15..f5b04db5f8 100644 --- a/resources/content_server/browse/browse.js +++ b/resources/content_server/browse/browse.js @@ -202,7 +202,8 @@ function booklist(hide_sort) { } $("#book_details_dialog").dialog({ autoOpen: false, - modal: true + modal: true, + show: 'slide' }); first_page(); } @@ -211,9 +212,11 @@ function show_details(a_dom) { var book = $(a_dom).closest('div.summary'); var id = book.attr('id').split('_')[1]; var bd = $('#book_details_dialog'); - bd.attr('title', 'test'); - bd.html('test'); + bd.html('LoadingLoading, please wait…'); bd.dialog('option', 'width', $('#container').width() - 50); + bd.dialog('option', 'height', $(window).height() - 100); + + bd.dialog('option', 'title', book.find('.title').text()); bd.dialog('open'); } diff --git a/resources/content_server/jquery_ui/js/jquery-ui-1.8.5.custom.min.js b/resources/content_server/jquery_ui/js/jquery-ui-1.8.5.custom.min.js index 034d13a25a..d858ce51de 100644 --- a/resources/content_server/jquery_ui/js/jquery-ui-1.8.5.custom.min.js +++ b/resources/content_server/jquery_ui/js/jquery-ui-1.8.5.custom.min.js @@ -204,4 +204,223 @@ function(a){return a+".dialog-overlay"}).join(" "),create:function(a){if(this.in (this.oldInstances.pop()||c("
").addClass("ui-widget-overlay")).appendTo(document.body).css({width:this.width(),height:this.height()});c.fn.bgiframe&&b.bgiframe();this.instances.push(b);return b},destroy:function(a){this.oldInstances.push(this.instances.splice(c.inArray(a,this.instances),1)[0]);this.instances.length===0&&c([document,window]).unbind(".dialog-overlay");a.remove();var b=0;c.each(this.instances,function(){b=Math.max(b,this.css("z-index"))});this.maxZ=b},height:function(){var a, b;if(c.browser.msie&&c.browser.version<7){a=Math.max(document.documentElement.scrollHeight,document.body.scrollHeight);b=Math.max(document.documentElement.offsetHeight,document.body.offsetHeight);return a
").addClass("ui-effects-wrapper").css({fontSize:"100%",background:"transparent",border:"none",margin:0,padding:0});c.wrap(b);b=c.parent();if(c.css("position")=="static"){b.css({position:"relative"});c.css({position:"relative"})}else{f.extend(a,{position:c.css("position"),zIndex:c.css("z-index")});f.each(["top","left","bottom","right"],function(d,e){a[e]=c.css(e);if(isNaN(parseInt(a[e],10)))a[e]="auto"}); +c.css({position:"relative",top:0,left:0})}return b.css(a).show()},removeWrapper:function(c){if(c.parent().is(".ui-effects-wrapper"))return c.parent().replaceWith(c);return c},setTransition:function(c,a,b,d){d=d||{};f.each(a,function(e,g){unit=c.cssUnit(g);if(unit[0]>0)d[g]=unit[0]*b+unit[1]});return d}});f.fn.extend({effect:function(c){var a=k.apply(this,arguments);a={options:a[1],duration:a[2],callback:a[3]};var b=f.effects[c];return b&&!f.fx.off?b.call(this,a):this},_show:f.fn.show,show:function(c){if(!c|| +typeof c=="number"||f.fx.speeds[c]||!f.effects[c])return this._show.apply(this,arguments);else{var a=k.apply(this,arguments);a[1].mode="show";return this.effect.apply(this,a)}},_hide:f.fn.hide,hide:function(c){if(!c||typeof c=="number"||f.fx.speeds[c]||!f.effects[c])return this._hide.apply(this,arguments);else{var a=k.apply(this,arguments);a[1].mode="hide";return this.effect.apply(this,a)}},__toggle:f.fn.toggle,toggle:function(c){if(!c||typeof c=="number"||f.fx.speeds[c]||!f.effects[c]||typeof c== +"boolean"||f.isFunction(c))return this.__toggle.apply(this,arguments);else{var a=k.apply(this,arguments);a[1].mode="toggle";return this.effect.apply(this,a)}},cssUnit:function(c){var a=this.css(c),b=[];f.each(["em","px","%","pt"],function(d,e){if(a.indexOf(e)>0)b=[parseFloat(a),e]});return b}});f.easing.jswing=f.easing.swing;f.extend(f.easing,{def:"easeOutQuad",swing:function(c,a,b,d,e){return f.easing[f.easing.def](c,a,b,d,e)},easeInQuad:function(c,a,b,d,e){return d*(a/=e)*a+b},easeOutQuad:function(c, +a,b,d,e){return-d*(a/=e)*(a-2)+b},easeInOutQuad:function(c,a,b,d,e){if((a/=e/2)<1)return d/2*a*a+b;return-d/2*(--a*(a-2)-1)+b},easeInCubic:function(c,a,b,d,e){return d*(a/=e)*a*a+b},easeOutCubic:function(c,a,b,d,e){return d*((a=a/e-1)*a*a+1)+b},easeInOutCubic:function(c,a,b,d,e){if((a/=e/2)<1)return d/2*a*a*a+b;return d/2*((a-=2)*a*a+2)+b},easeInQuart:function(c,a,b,d,e){return d*(a/=e)*a*a*a+b},easeOutQuart:function(c,a,b,d,e){return-d*((a=a/e-1)*a*a*a-1)+b},easeInOutQuart:function(c,a,b,d,e){if((a/= +e/2)<1)return d/2*a*a*a*a+b;return-d/2*((a-=2)*a*a*a-2)+b},easeInQuint:function(c,a,b,d,e){return d*(a/=e)*a*a*a*a+b},easeOutQuint:function(c,a,b,d,e){return d*((a=a/e-1)*a*a*a*a+1)+b},easeInOutQuint:function(c,a,b,d,e){if((a/=e/2)<1)return d/2*a*a*a*a*a+b;return d/2*((a-=2)*a*a*a*a+2)+b},easeInSine:function(c,a,b,d,e){return-d*Math.cos(a/e*(Math.PI/2))+d+b},easeOutSine:function(c,a,b,d,e){return d*Math.sin(a/e*(Math.PI/2))+b},easeInOutSine:function(c,a,b,d,e){return-d/2*(Math.cos(Math.PI*a/e)-1)+ +b},easeInExpo:function(c,a,b,d,e){return a==0?b:d*Math.pow(2,10*(a/e-1))+b},easeOutExpo:function(c,a,b,d,e){return a==e?b+d:d*(-Math.pow(2,-10*a/e)+1)+b},easeInOutExpo:function(c,a,b,d,e){if(a==0)return b;if(a==e)return b+d;if((a/=e/2)<1)return d/2*Math.pow(2,10*(a-1))+b;return d/2*(-Math.pow(2,-10*--a)+2)+b},easeInCirc:function(c,a,b,d,e){return-d*(Math.sqrt(1-(a/=e)*a)-1)+b},easeOutCirc:function(c,a,b,d,e){return d*Math.sqrt(1-(a=a/e-1)*a)+b},easeInOutCirc:function(c,a,b,d,e){if((a/=e/2)<1)return-d/ +2*(Math.sqrt(1-a*a)-1)+b;return d/2*(Math.sqrt(1-(a-=2)*a)+1)+b},easeInElastic:function(c,a,b,d,e){c=1.70158;var g=0,h=d;if(a==0)return b;if((a/=e)==1)return b+d;g||(g=e*0.3);if(h").css({position:"absolute",visibility:"visible",left:-f*(h/d),top:-e*(i/c)}).parent().addClass("ui-effects-explode").css({position:"absolute",overflow:"hidden",width:h/d,height:i/c,left:g.left+f*(h/d)+(a.options.mode=="show"?(f-Math.floor(d/2))*(h/d):0),top:g.top+e*(i/c)+(a.options.mode=="show"?(e-Math.floor(c/2))*(i/c):0),opacity:a.options.mode=="show"?0:1}).animate({left:g.left+f*(h/d)+(a.options.mode=="show"?0:(f-Math.floor(d/2))*(h/d)),top:g.top+ +e*(i/c)+(a.options.mode=="show"?0:(e-Math.floor(c/2))*(i/c)),opacity:a.options.mode=="show"?1:0},a.duration||500);setTimeout(function(){a.options.mode=="show"?b.css({visibility:"visible"}):b.css({visibility:"visible"}).hide();a.callback&&a.callback.apply(b[0]);b.dequeue();j("div.ui-effects-explode").remove()},a.duration||500)})}})(jQuery); +;/* + * jQuery UI Effects Fade 1.8.5 + * + * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Effects/Fade + * + * Depends: + * jquery.effects.core.js + */ +(function(b){b.effects.fade=function(a){return this.queue(function(){var c=b(this),d=b.effects.setMode(c,a.options.mode||"hide");c.animate({opacity:d},{queue:false,duration:a.duration,easing:a.options.easing,complete:function(){a.callback&&a.callback.apply(this,arguments);c.dequeue()}})})}})(jQuery); +;/* + * jQuery UI Effects Fold 1.8.5 + * + * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Effects/Fold + * + * Depends: + * jquery.effects.core.js + */ +(function(c){c.effects.fold=function(a){return this.queue(function(){var b=c(this),j=["position","top","left"],d=c.effects.setMode(b,a.options.mode||"hide"),g=a.options.size||15,h=!!a.options.horizFirst,k=a.duration?a.duration/2:c.fx.speeds._default/2;c.effects.save(b,j);b.show();var e=c.effects.createWrapper(b).css({overflow:"hidden"}),f=d=="show"!=h,l=f?["width","height"]:["height","width"];f=f?[e.width(),e.height()]:[e.height(),e.width()];var i=/([0-9]+)%/.exec(g);if(i)g=parseInt(i[1],10)/100* +f[d=="hide"?0:1];if(d=="show")e.css(h?{height:0,width:g}:{height:g,width:0});h={};i={};h[l[0]]=d=="show"?f[0]:g;i[l[1]]=d=="show"?f[1]:0;e.animate(h,k,a.options.easing).animate(i,k,a.options.easing,function(){d=="hide"&&b.hide();c.effects.restore(b,j);c.effects.removeWrapper(b);a.callback&&a.callback.apply(b[0],arguments);b.dequeue()})})}})(jQuery); +;/* + * jQuery UI Effects Highlight 1.8.5 + * + * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Effects/Highlight + * + * Depends: + * jquery.effects.core.js + */ +(function(b){b.effects.highlight=function(c){return this.queue(function(){var a=b(this),e=["backgroundImage","backgroundColor","opacity"],d=b.effects.setMode(a,c.options.mode||"show"),f={backgroundColor:a.css("backgroundColor")};if(d=="hide")f.opacity=0;b.effects.save(a,e);a.show().css({backgroundImage:"none",backgroundColor:c.options.color||"#ffff99"}).animate(f,{queue:false,duration:c.duration,easing:c.options.easing,complete:function(){d=="hide"&&a.hide();b.effects.restore(a,e);d=="show"&&!b.support.opacity&& +this.style.removeAttribute("filter");c.callback&&c.callback.apply(this,arguments);a.dequeue()}})})}})(jQuery); +;/* + * jQuery UI Effects Pulsate 1.8.5 + * + * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Effects/Pulsate + * + * Depends: + * jquery.effects.core.js + */ +(function(d){d.effects.pulsate=function(a){return this.queue(function(){var b=d(this),c=d.effects.setMode(b,a.options.mode||"show");times=(a.options.times||5)*2-1;duration=a.duration?a.duration/2:d.fx.speeds._default/2;isVisible=b.is(":visible");animateTo=0;if(!isVisible){b.css("opacity",0).show();animateTo=1}if(c=="hide"&&isVisible||c=="show"&&!isVisible)times--;for(c=0;c').appendTo(document.body).addClass(a.options.className).css({top:d.top,left:d.left,height:b.innerHeight(),width:b.innerWidth(),position:"absolute"}).animate(c,a.duration,a.options.easing,function(){f.remove();a.callback&&a.callback.apply(b[0],arguments); +b.dequeue()})})}})(jQuery); ; \ No newline at end of file From 953da12b44fcf09cb34d4fe3473fc88b4813b08b Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Fri, 15 Oct 2010 21:32:05 -0600 Subject: [PATCH 16/19] ... --- resources/content_server/browse/browse.css | 4 ++++ resources/content_server/browse/browse.html | 2 +- resources/content_server/browse/browse.js | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/resources/content_server/browse/browse.css b/resources/content_server/browse/browse.css index aceb595383..406de09f53 100644 --- a/resources/content_server/browse/browse.css +++ b/resources/content_server/browse/browse.css @@ -176,6 +176,10 @@ h2.library_name { overflow: hidden; } +#search_box .ui-button { + padding: 0.25em; +} + /* }}} */ /* Top level {{{ */ diff --git a/resources/content_server/browse/browse.html b/resources/content_server/browse/browse.html index b3039f8c4e..4acc15f3ea 100644 --- a/resources/content_server/browse/browse.html +++ b/resources/content_server/browse/browse.html @@ -94,6 +94,6 @@ - +
diff --git a/resources/content_server/browse/browse.js b/resources/content_server/browse/browse.js index f5b04db5f8..16753a38b9 100644 --- a/resources/content_server/browse/browse.js +++ b/resources/content_server/browse/browse.js @@ -213,7 +213,7 @@ function show_details(a_dom) { var id = book.attr('id').split('_')[1]; var bd = $('#book_details_dialog'); bd.html('LoadingLoading, please wait…'); - bd.dialog('option', 'width', $('#container').width() - 50); + bd.dialog('option', 'width', $(window).width() - 100); bd.dialog('option', 'height', $(window).height() - 100); bd.dialog('option', 'title', book.find('.title').text()); From cf644ac63ecfd70e3d12614b82b6fff551ba3ee4 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Fri, 15 Oct 2010 22:05:51 -0600 Subject: [PATCH 17/19] ... --- resources/content_server/browse/browse.js | 16 +++- resources/content_server/browse/summary.html | 1 + src/calibre/library/server/browse.py | 93 ++++++++++++++------ 3 files changed, 79 insertions(+), 31 deletions(-) diff --git a/resources/content_server/browse/browse.js b/resources/content_server/browse/browse.js index 16753a38b9..367b8341d9 100644 --- a/resources/content_server/browse/browse.js +++ b/resources/content_server/browse/browse.js @@ -210,13 +210,25 @@ function booklist(hide_sort) { function show_details(a_dom) { var book = $(a_dom).closest('div.summary'); - var id = book.attr('id').split('_')[1]; var bd = $('#book_details_dialog'); bd.html('LoadingLoading, please wait…'); bd.dialog('option', 'width', $(window).width() - 100); bd.dialog('option', 'height', $(window).height() - 100); - bd.dialog('option', 'title', book.find('.title').text()); + + $.ajax({ + url: book.find('.details-href').attr('title'), + context: bd, + dataType: "json", + timeout: 600000, //milliseconds (10 minutes) + error: function(xhr, stat, err) { + this.html(render_error(stat)); + }, + success: function(data) { + this.html(data); + } + }); + bd.dialog('open'); } diff --git a/resources/content_server/browse/summary.html b/resources/content_server/browse/summary.html index 8df42de366..ba23ed854c 100644 --- a/resources/content_server/browse/summary.html +++ b/resources/content_server/browse/summary.html @@ -15,4 +15,5 @@
{tags}
{other_formats}
+ diff --git a/src/calibre/library/server/browse.py b/src/calibre/library/server/browse.py index 7d476ade3b..805a8f6424 100644 --- a/src/calibre/library/server/browse.py +++ b/src/calibre/library/server/browse.py @@ -187,9 +187,10 @@ class BrowseServer(object): connect('browse_booklist_page', base_href+'/booklist_page', self.browse_booklist_page) - connect('browse_search', base_href+'/search', self.browse_search) + connect('browse_details', base_href+'/details/{id}', + self.browse_details) # Templates {{{ def browse_template(self, sort, category=True, initial_search=''): @@ -447,6 +448,23 @@ class BrowseServer(object): title=_('Books in') + " " +category_name, script='booklist(%s);'%hide_sort, main=html) + def browse_get_book_args(self, mi, id_): + fmts = self.db.formats(id_, index_is_id=True) + if not fmts: + fmts = '' + fmts = [x.lower() for x in fmts.split(',') if x] + pf = prefs['output_format'].lower() + fmt = pf if pf in fmts else fmts[0] + args = {'id':id_, 'mi':mi, + } + for key in mi.all_field_keys(): + val = mi.format_field(key)[1] + if not val: + val = '' + args[key] = xml(val, True) + fname = ascii_filename(args['title']) + ' - ' + ascii_filename(args['authors']) + return args, fmt, fmts, fname + @Endpoint(mimetype='application/json; charset=utf-8') def browse_booklist_page(self, ids=None, sort=None): if sort == 'null': @@ -464,36 +482,9 @@ class BrowseServer(object): mi = self.db.get_metadata(id_, index_is_id=True) except: continue - fmts = self.db.formats(id_, index_is_id=True) - if not fmts: - fmts = '' - fmts = [x.lower() for x in fmts.split(',') if x] - pf = prefs['output_format'].lower() - fmt = pf if pf in fmts else fmts[0] - args = {'id':id_, 'mi':mi, - 'read_string':xml(_('Read'), True), - 'details': xml(_('Details'), True), - 'details_tt': xml(_('Show book details'), True) - } - for key in mi.all_field_keys(): - val = mi.format_field(key)[1] - if not val: - val = '' - args[key] = xml(val, True) - fname = ascii_filename(args['title']) + ' - ' + ascii_filename(args['authors']) - args['href'] = '/get/%s/%s_%d.%s'%( - fmt, fname, id_, fmt) - args['comments'] = comments_to_html(mi.comments) - args['read_tooltip'] = \ - _('Read %s in the %s format')%(args['title'], fmt.upper()) - args['stars'] = '' - if mi.rating: - args['stars'] = render_rating(mi.rating/2.0, prefix=_('Rating'))[0] - if args['tags']: - args['tags'] = u'%s: '%_('Tags') + args['tags'] + args, fmt, fmts, fname = self.browse_get_book_args(mi, id_) args['other_formats'] = '' other_fmts = [x for x in fmts if x.lower() != fmt.lower()] - if other_fmts: ofmts = [u'{3}'\ .format(fmt, fname, id_, fmt.upper()) for fmt in @@ -502,12 +493,56 @@ class BrowseServer(object): args['other_formats'] = u'%s: ' % \ _('Other formats') + ofmts + args['details_href'] = '/browse/details/'+str(id_) + args['read_tooltip'] = \ + _('Read %s in the %s format')%(args['title'], fmt.upper()) + args['href'] = '/get/%s/%s_%d.%s'%( + fmt, fname, id_, fmt) + args['comments'] = comments_to_html(mi.comments) + args['stars'] = '' + if mi.rating: + args['stars'] = render_rating(mi.rating/2.0, prefix=_('Rating'))[0] + if args['tags']: + args['tags'] = u'%s: '%_('Tags') + \ + xml(args['tags']) + if args['series']: + args['series'] = xml(args['series']) + args['read_string'] = xml(_('Read'), True) + args['details'] = xml(_('Details'), True) + args['details_tt'] = xml(_('Show book details'), True) summs.append(self.browse_summary_template.format(**args)) return json.dumps('\n'.join(summs), ensure_ascii=False) + @Endpoint(mimetype='application/json; charset=utf-8') + def browse_details(self, id=None): + try: + id_ = int(id) + except: + raise cherrypy.HTTPError(404, 'invalid id: %r'%id) + + try: + mi = self.db.get_metadata(id_, index_is_id=True) + except: + ans = _('This book has been deleted') + else: + args, fmt, fmts, fname = self.browse_get_book_args(mi, id_) + args['formats'] = '' + if fmts: + ofmts = [u'{3}'\ + .format(fmt, fname, id_, fmt.upper()) for fmt in + fmts] + ofmts = ', '.join(ofmts) + args['formats'] = u'%s: ' % \ + _('Formats') + ofmts + + + return json.dumps(ans, ensure_ascii=False) + + + # }}} # Search {{{ From ff8f949f97a267be14552acd728177dc1e742ab9 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Fri, 15 Oct 2010 23:05:35 -0600 Subject: [PATCH 18/19] /browse: Implement Book details --- resources/content_server/browse/browse.css | 38 ++++++++++++++++ resources/content_server/browse/details.html | 10 +++++ src/calibre/library/field_metadata.py | 2 +- src/calibre/library/server/browse.py | 47 +++++++++++++++++--- 4 files changed, 91 insertions(+), 6 deletions(-) create mode 100644 resources/content_server/browse/details.html diff --git a/resources/content_server/browse/browse.css b/resources/content_server/browse/browse.css index 406de09f53..d50b6936ff 100644 --- a/resources/content_server/browse/browse.css +++ b/resources/content_server/browse/browse.css @@ -384,3 +384,41 @@ h2.library_name { /* }}} */ +/* Details {{{ */ + +.details .left { + float: left; + max-width: 50%; + margin-right: 2em; + overflow: auto; +} + +.details .right { + overflow: auto; +} + +.details .formats { + margin-bottom: 2ex; +} + +#book_details_dialog .details a { + color: blue; + text-decoration: none; +} + +#book_details_dialog .details a:hover { + color: red; +} + +.details .field { + margin-bottom: 0.5em; +} + +.details .comment { + margin-left: 1em; + overflow: auto; + max-height: 50%; +} + +/* }}} */ + diff --git a/resources/content_server/browse/details.html b/resources/content_server/browse/details.html new file mode 100644 index 0000000000..59af5c535e --- /dev/null +++ b/resources/content_server/browse/details.html @@ -0,0 +1,10 @@ +
+
+ Cover of {title} +
+
+
{formats}
+ {fields} + {comments} +
+
diff --git a/src/calibre/library/field_metadata.py b/src/calibre/library/field_metadata.py index b43a6620d0..69dd7ae636 100644 --- a/src/calibre/library/field_metadata.py +++ b/src/calibre/library/field_metadata.py @@ -161,7 +161,7 @@ class FieldMetadata(dict): 'datatype':'text', 'is_multiple':None, 'kind':'field', - 'name':None, + 'name':_('Comments'), 'search_terms':['comments', 'comment'], 'is_custom':False, 'is_category':False}), ('cover', {'table':None, diff --git a/src/calibre/library/server/browse.py b/src/calibre/library/server/browse.py index 805a8f6424..5e7de43d45 100644 --- a/src/calibre/library/server/browse.py +++ b/src/calibre/library/server/browse.py @@ -245,6 +245,14 @@ class BrowseServer(object): P('content_server/browse/summary.html', data=True).decode('utf-8') return self.__browse_summary_template__ + @property + def browse_details_template(self): + if not hasattr(self, '__browse_details_template__') or \ + self.opts.develop: + self.__browse_details_template__ = \ + P('content_server/browse/details.html', data=True).decode('utf-8') + return self.__browse_details_template__ + # }}} # Catalogs {{{ @@ -503,10 +511,10 @@ class BrowseServer(object): if mi.rating: args['stars'] = render_rating(mi.rating/2.0, prefix=_('Rating'))[0] if args['tags']: - args['tags'] = u'%s: '%_('Tags') + \ - xml(args['tags']) + args['tags'] = u'%s: '%xml(_('Tags')) + \ + args['tags'] if args['series']: - args['series'] = xml(args['series']) + args['series'] = args['series'] args['read_string'] = xml(_('Read'), True) args['details'] = xml(_('Details'), True) args['details_tt'] = xml(_('Show book details'), True) @@ -535,9 +543,38 @@ class BrowseServer(object): .format(fmt, fname, id_, fmt.upper()) for fmt in fmts] ofmts = ', '.join(ofmts) - args['formats'] = u'%s: ' % \ - _('Formats') + ofmts + args['formats'] = ofmts + fields, comments = [], [] + for field, m in list(mi.get_all_standard_metadata(False).items()) + \ + list(mi.get_all_user_metadata(False).items()): + if m['datatype'] == 'comments' or field == 'comments': + comments.append((m['name'], comments_to_html(mi.get(field, + '')))) + continue + if field in ('title', 'formats') or not args.get(field, False) \ + or not m['name']: + continue + if m['datatype'] == 'rating': + r = u'%s: '%xml(m['name']) + \ + render_rating(mi.rating/2.0, prefix=m['name'])[0] + else: + r = u'%s: '%xml(m['name']) + \ + args[field] + fields.append((m['name'], r)) + fields.sort(key=lambda x: x[0].lower()) + fields = [u'
{0}
'.format(f[1]) for f in + fields] + fields = u'
%s
'%('\n\n'.join(fields)) + + comments.sort(key=lambda x: x[0].lower()) + comments = [(u'
%s: ' + u'
%s
') % (xml(c[0]), + c[1]) for c in comments] + comments = u'
%s
'%('\n\n'.join(comments)) + ans = self.browse_details_template.format(id=id_, + title=xml(mi.title, True), fields=fields, + formats=args['formats'], comments=comments) return json.dumps(ans, ensure_ascii=False) From 9bb060124ed756196658f9485709261b8096b553 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Fri, 15 Oct 2010 23:07:37 -0600 Subject: [PATCH 19/19] ... --- src/calibre/gui2/dialogs/metadata_single.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/calibre/gui2/dialogs/metadata_single.py b/src/calibre/gui2/dialogs/metadata_single.py index 64ac4a3ccb..8043016f9f 100644 --- a/src/calibre/gui2/dialogs/metadata_single.py +++ b/src/calibre/gui2/dialogs/metadata_single.py @@ -25,7 +25,7 @@ from calibre.ebooks.metadata.covers import download_cover from calibre.ebooks.metadata.meta import get_metadata from calibre.ebooks.metadata import MetaInformation from calibre.utils.config import prefs, tweaks -from calibre.utils.date import qt_to_dt, local_tz, utcfromtimestamp, utc_tz +from calibre.utils.date import qt_to_dt, local_tz, utcfromtimestamp from calibre.customize.ui import run_plugins_on_import, get_isbndb_key from calibre.gui2.preferences.social import SocialMetadata from calibre.gui2.custom_column_widgets import populate_metadata_page