checkpoint
This commit is contained in:
		
							parent
							
								
									198900c990
								
							
						
					
					
						commit
						25a4b69cd8
					
				
					 5 changed files with 185 additions and 33 deletions
				
			
		|  | @ -33,6 +33,7 @@ MOTD_STRINGS = [ | ||||||
| #'Buckle up, it\'s time to:', | #'Buckle up, it\'s time to:', | ||||||
| ] | ] | ||||||
| 
 | 
 | ||||||
|  | THUMBDIR = phototagger.DEFAULT_THUMBDIR | ||||||
| ERROR_INVALID_ACTION = 'Invalid action' | ERROR_INVALID_ACTION = 'Invalid action' | ||||||
| ERROR_NO_TAG_GIVEN = 'No tag name supplied' | ERROR_NO_TAG_GIVEN = 'No tag name supplied' | ||||||
| ERROR_TAG_TOO_SHORT = 'Not enough valid chars' | ERROR_TAG_TOO_SHORT = 'Not enough valid chars' | ||||||
|  | @ -317,7 +318,7 @@ def get_album_html(albumid): | ||||||
|     response = flask.render_template( |     response = flask.render_template( | ||||||
|         'album.html', |         'album.html', | ||||||
|         album=album, |         album=album, | ||||||
|         child_albums=album['sub_albums'], |         child_albums=[jsonify_album(P_album(x)) for x in album['sub_albums']], | ||||||
|         photos=album['photos'], |         photos=album['photos'], | ||||||
|     ) |     ) | ||||||
|     return response |     return response | ||||||
|  | @ -392,7 +393,8 @@ def get_photo_json(photoid): | ||||||
| def get_search_core(): | def get_search_core(): | ||||||
|     print(request.args) |     print(request.args) | ||||||
| 
 | 
 | ||||||
|     # EXTENSION |     # FILENAME & EXTENSION | ||||||
|  |     filename_terms = request.args.get('filename', None) | ||||||
|     extension_string = request.args.get('extension', None) |     extension_string = request.args.get('extension', None) | ||||||
|     extension_not_string = request.args.get('extension_not', None) |     extension_not_string = request.args.get('extension_not', None) | ||||||
|     mimetype_string = request.args.get('mimetype', None) |     mimetype_string = request.args.get('mimetype', None) | ||||||
|  | @ -464,6 +466,7 @@ def get_search_core(): | ||||||
|         'created': created, |         'created': created, | ||||||
|         'extension': extension_list, |         'extension': extension_list, | ||||||
|         'extension_not': extension_not_list, |         'extension_not': extension_not_list, | ||||||
|  |         'filename': filename_terms, | ||||||
|         'has_tags': has_tags, |         'has_tags': has_tags, | ||||||
|         'mimetype': mimetype_list, |         'mimetype': mimetype_list, | ||||||
|         'tag_musts': tag_musts, |         'tag_musts': tag_musts, | ||||||
|  |  | ||||||
|  | @ -2,6 +2,8 @@ | ||||||
| # py -i etiquette_easy.py | # py -i etiquette_easy.py | ||||||
| 
 | 
 | ||||||
| import phototagger | import phototagger | ||||||
|  | import os | ||||||
|  | import sys | ||||||
| P = phototagger.PhotoDB() | P = phototagger.PhotoDB() | ||||||
| import traceback | import traceback | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -61,6 +61,7 @@ SQL_ALBUM_COLUMNS = [ | ||||||
|     'id', |     'id', | ||||||
|     'title', |     'title', | ||||||
|     'description', |     'description', | ||||||
|  |     'associated_directory' | ||||||
| ] | ] | ||||||
| SQL_PHOTO_COLUMNS = [ | SQL_PHOTO_COLUMNS = [ | ||||||
|     'id', |     'id', | ||||||
|  | @ -112,11 +113,12 @@ PRAGMA cache_size = 10000; | ||||||
| CREATE TABLE IF NOT EXISTS albums( | CREATE TABLE IF NOT EXISTS albums( | ||||||
|     id TEXT, |     id TEXT, | ||||||
|     title TEXT, |     title TEXT, | ||||||
|     description TEXT |     description TEXT, | ||||||
|  |     associated_directory TEXT COLLATE NOCASE | ||||||
| ); | ); | ||||||
| CREATE TABLE IF NOT EXISTS photos( | CREATE TABLE IF NOT EXISTS photos( | ||||||
|     id TEXT, |     id TEXT, | ||||||
|     filepath TEXT, |     filepath TEXT COLLATE NOCASE, | ||||||
|     extension TEXT, |     extension TEXT, | ||||||
|     width INT, |     width INT, | ||||||
|     height INT, |     height INT, | ||||||
|  | @ -160,7 +162,7 @@ CREATE INDEX IF NOT EXISTS index_albumrel_photoid on album_photo_rel(photoid); | ||||||
| 
 | 
 | ||||||
| -- Photo | -- Photo | ||||||
| CREATE INDEX IF NOT EXISTS index_photo_id on photos(id); | CREATE INDEX IF NOT EXISTS index_photo_id on photos(id); | ||||||
| CREATE INDEX IF NOT EXISTS index_photo_path on photos(filepath); | CREATE INDEX IF NOT EXISTS index_photo_path on photos(filepath COLLATE NOCASE); | ||||||
| CREATE INDEX IF NOT EXISTS index_photo_created on photos(created); | CREATE INDEX IF NOT EXISTS index_photo_created on photos(created); | ||||||
| CREATE INDEX IF NOT EXISTS index_photo_extension on photos(extension); | CREATE INDEX IF NOT EXISTS index_photo_extension on photos(extension); | ||||||
| 
 | 
 | ||||||
|  | @ -213,6 +215,10 @@ def _helper_extension(ext): | ||||||
|     ext = set(ext) |     ext = set(ext) | ||||||
|     return ext |     return ext | ||||||
| 
 | 
 | ||||||
|  | def _helper_filenamefilter(subject, terms): | ||||||
|  |     basename = subject.lower() | ||||||
|  |     return all(term in basename for term in terms) | ||||||
|  | 
 | ||||||
| def _helper_minmax(key, value, minimums, maximums): | def _helper_minmax(key, value, minimums, maximums): | ||||||
|     ''' |     ''' | ||||||
|     When searching, this function dissects a hyphenated range string |     When searching, this function dissects a hyphenated range string | ||||||
|  | @ -686,10 +692,27 @@ class PDBAlbumMixin: | ||||||
|     def get_album(self, id): |     def get_album(self, id): | ||||||
|         return self.get_thing_by_id('album', id) |         return self.get_thing_by_id('album', id) | ||||||
| 
 | 
 | ||||||
|  |     def get_album_by_path(self, filepath): | ||||||
|  |         ''' | ||||||
|  |         Return the album with the `associated_directory` of this value, NOT case-sensitive. | ||||||
|  |         ''' | ||||||
|  |         filepath = os.path.abspath(filepath) | ||||||
|  |         self.cur.execute('SELECT * FROM albums WHERE associated_directory == ?', [filepath]) | ||||||
|  |         f = self.cur.fetchone() | ||||||
|  |         if f is None: | ||||||
|  |             raise NoSuchAlbum(filepath) | ||||||
|  |         return self.get_album(f[SQL_ALBUM['id']]) | ||||||
|  | 
 | ||||||
|     def get_albums(self): |     def get_albums(self): | ||||||
|         yield from self.get_things(thing_type='album') |         yield from self.get_things(thing_type='album') | ||||||
| 
 | 
 | ||||||
|     def new_album(self, title=None, description=None, photos=None, commit=True): |     def new_album(self, | ||||||
|  |             associated_directory=None, | ||||||
|  |             commit=True, | ||||||
|  |             description=None, | ||||||
|  |             photos=None, | ||||||
|  |             title=None, | ||||||
|  |         ): | ||||||
|         ''' |         ''' | ||||||
|         Create a new album. Photos can be added now or later. |         Create a new album. Photos can be added now or later. | ||||||
|         ''' |         ''' | ||||||
|  | @ -697,6 +720,9 @@ class PDBAlbumMixin: | ||||||
|         albumid = self.generate_id('tags') |         albumid = self.generate_id('tags') | ||||||
|         title = title or '' |         title = title or '' | ||||||
|         description = description or '' |         description = description or '' | ||||||
|  |         if associated_directory is not None: | ||||||
|  |             associated_directory = os.path.abspath(associated_directory) | ||||||
|  | 
 | ||||||
|         if not isinstance(title, str): |         if not isinstance(title, str): | ||||||
|             raise TypeError('Title must be string, not %s' % type(title)) |             raise TypeError('Title must be string, not %s' % type(title)) | ||||||
| 
 | 
 | ||||||
|  | @ -707,8 +733,9 @@ class PDBAlbumMixin: | ||||||
|         data[SQL_ALBUM['id']] = albumid |         data[SQL_ALBUM['id']] = albumid | ||||||
|         data[SQL_ALBUM['title']] = title |         data[SQL_ALBUM['title']] = title | ||||||
|         data[SQL_ALBUM['description']] = description |         data[SQL_ALBUM['description']] = description | ||||||
|  |         data[SQL_ALBUM['associated_directory']] = associated_directory | ||||||
| 
 | 
 | ||||||
|         self.cur.execute('INSERT INTO albums VALUES(?, ?, ?)', data) |         self.cur.execute('INSERT INTO albums VALUES(?, ?, ?, ?)', data) | ||||||
|         album = Album(self, data) |         album = Album(self, data) | ||||||
|         if photos: |         if photos: | ||||||
|             for photo in photos: |             for photo in photos: | ||||||
|  | @ -716,6 +743,7 @@ class PDBAlbumMixin: | ||||||
|                 album.add_photo(photo, commit=False) |                 album.add_photo(photo, commit=False) | ||||||
| 
 | 
 | ||||||
|         if commit: |         if commit: | ||||||
|  |             log.debug('Committing - new Album') | ||||||
|             self.commit() |             self.commit() | ||||||
|         return album |         return album | ||||||
| 
 | 
 | ||||||
|  | @ -851,6 +879,7 @@ class PDBPhotoMixin: | ||||||
|             created=None, |             created=None, | ||||||
|             extension=None, |             extension=None, | ||||||
|             extension_not=None, |             extension_not=None, | ||||||
|  |             filename=None, | ||||||
|             has_tags=None, |             has_tags=None, | ||||||
|             mimetype=None, |             mimetype=None, | ||||||
|             tag_musts=None, |             tag_musts=None, | ||||||
|  | @ -878,6 +907,10 @@ class PDBPhotoMixin: | ||||||
|         extension_not: |         extension_not: | ||||||
|             A string or list of strings of unacceptable file extensions. |             A string or list of strings of unacceptable file extensions. | ||||||
| 
 | 
 | ||||||
|  |         filename: | ||||||
|  |             A string or list of strings which will be split into words. The file's basename | ||||||
|  |             must include every word, NOT case-sensitive. | ||||||
|  | 
 | ||||||
|         has_tags: |         has_tags: | ||||||
|             If True, require that the Photo has >=1 tag. |             If True, require that the Photo has >=1 tag. | ||||||
|             If False, require that the Photo has no tags. |             If False, require that the Photo has no tags. | ||||||
|  | @ -934,6 +967,11 @@ class PDBPhotoMixin: | ||||||
|         extension_not = _helper_extension(extension_not) |         extension_not = _helper_extension(extension_not) | ||||||
|         mimetype = _helper_extension(mimetype) |         mimetype = _helper_extension(mimetype) | ||||||
| 
 | 
 | ||||||
|  |         if filename is not None: | ||||||
|  |             if not isinstance(filename, str): | ||||||
|  |                 filename = ' '.join(filename) | ||||||
|  |             filename = set(term.lower() for term in filename.strip().split(' ')) | ||||||
|  | 
 | ||||||
|         if (tag_musts or tag_mays or tag_forbids) and tag_expression: |         if (tag_musts or tag_mays or tag_forbids) and tag_expression: | ||||||
|             raise XORException('Expression filter cannot be used with musts, mays, forbids') |             raise XORException('Expression filter cannot be used with musts, mays, forbids') | ||||||
| 
 | 
 | ||||||
|  | @ -984,6 +1022,11 @@ class PDBPhotoMixin: | ||||||
|                 continue |                 continue | ||||||
| 
 | 
 | ||||||
|             if mimetype and photo.mimetype() not in mimetype: |             if mimetype and photo.mimetype() not in mimetype: | ||||||
|  |                 #print('Failed mimetype') | ||||||
|  |                 continue | ||||||
|  | 
 | ||||||
|  |             if filename and not _helper_filenamefilter(subject=photo.basename, terms=filename): | ||||||
|  |                 #print('Failed filename') | ||||||
|                 continue |                 continue | ||||||
| 
 | 
 | ||||||
|             if any(not fetch[SQL_PHOTO[key]] or fetch[SQL_PHOTO[key]] > value for (key, value) in maximums.items()): |             if any(not fetch[SQL_PHOTO[key]] or fetch[SQL_PHOTO[key]] > value for (key, value) in maximums.items()): | ||||||
|  | @ -1173,7 +1216,9 @@ class PhotoDB(PDBAlbumMixin, PDBPhotoMixin, PDBTagMixin): | ||||||
| 
 | 
 | ||||||
|     def digest_directory(self, directory, exclude_directories=None, exclude_filenames=None, commit=True): |     def digest_directory(self, directory, exclude_directories=None, exclude_filenames=None, commit=True): | ||||||
|         ''' |         ''' | ||||||
|         Create an album, and add the directory's contents to it. |         Create an album, and add the directory's contents to it recursively. | ||||||
|  | 
 | ||||||
|  |         If a Photo object already exists for a file, it will be added to the correct album. | ||||||
|         ''' |         ''' | ||||||
|         if not os.path.isdir(directory): |         if not os.path.isdir(directory): | ||||||
|             raise ValueError('Not a directory: %s' % directory) |             raise ValueError('Not a directory: %s' % directory) | ||||||
|  | @ -1189,22 +1234,41 @@ class PhotoDB(PDBAlbumMixin, PDBPhotoMixin, PDBTagMixin): | ||||||
|             ] |             ] | ||||||
| 
 | 
 | ||||||
|         directory = spinal.str_to_fp(directory) |         directory = spinal.str_to_fp(directory) | ||||||
|  |         directory.correct_case() | ||||||
|         generator = spinal.walk_generator( |         generator = spinal.walk_generator( | ||||||
|             directory, |             directory, | ||||||
|             exclude_directories=exclude_directories, |             exclude_directories=exclude_directories, | ||||||
|             exclude_filenames=exclude_filenames, |             exclude_filenames=exclude_filenames, | ||||||
|             yield_style='nested', |             yield_style='nested', | ||||||
|         ) |         ) | ||||||
|         album = self.new_album(title=directory.basename, commit=False) |         try: | ||||||
|  |             album = self.get_album_by_path(directory.absolute_path) | ||||||
|  |         except NoSuchAlbum: | ||||||
|  |             album = self.new_album( | ||||||
|  |                 associated_directory=directory.absolute_path, | ||||||
|  |                 commit=False, | ||||||
|  |                 title=directory.basename, | ||||||
|  |             ) | ||||||
|  | 
 | ||||||
|         albums = {directory.absolute_path: album} |         albums = {directory.absolute_path: album} | ||||||
|         for (current_location, directories, files) in generator: |         for (current_location, directories, files) in generator: | ||||||
|             current_album = albums.get(current_location.absolute_path, None) |             current_album = albums.get(current_location.absolute_path, None) | ||||||
|             if current_album is None: |             if current_album is None: | ||||||
|                 current_album = self.new_album(title=current_location.basename, commit=False) |                 try: | ||||||
|  |                     current_album = self.get_album_by_path(current_location.absolute_path) | ||||||
|  |                 except NoSuchAlbum: | ||||||
|  |                     current_album = self.new_album( | ||||||
|  |                         associated_directory=current_location.absolute_path, | ||||||
|  |                         commit=False, | ||||||
|  |                         title=current_location.basename, | ||||||
|  |                     ) | ||||||
|                     print('Created %s' % current_album.title) |                     print('Created %s' % current_album.title) | ||||||
|                 albums[current_location.absolute_path] = current_album |                 albums[current_location.absolute_path] = current_album | ||||||
|                 parent = albums[current_location.parent.absolute_path] |                 parent = albums[current_location.parent.absolute_path] | ||||||
|  |                 try: | ||||||
|                     parent.add(current_album, commit=False) |                     parent.add(current_album, commit=False) | ||||||
|  |                 except GroupExists: | ||||||
|  |                     pass | ||||||
|                 #print('Added to %s' % parent.title) |                 #print('Added to %s' % parent.title) | ||||||
|             for filepath in files: |             for filepath in files: | ||||||
|                 try: |                 try: | ||||||
|  | @ -1561,6 +1625,7 @@ class Album(ObjectBase, GroupableMixin): | ||||||
|         self.photodb = photodb |         self.photodb = photodb | ||||||
|         self.id = row_tuple[SQL_ALBUM['id']] |         self.id = row_tuple[SQL_ALBUM['id']] | ||||||
|         self.title = row_tuple[SQL_ALBUM['title']] |         self.title = row_tuple[SQL_ALBUM['title']] | ||||||
|  |         self.name = 'Album %s' % self.id | ||||||
|         self.description = row_tuple[SQL_ALBUM['description']] |         self.description = row_tuple[SQL_ALBUM['description']] | ||||||
|         self.group_getter = self.photodb.get_album |         self.group_getter = self.photodb.get_album | ||||||
| 
 | 
 | ||||||
|  | @ -1736,14 +1801,7 @@ class Photo(ObjectBase): | ||||||
|         special: |         special: | ||||||
|             For videos, you can provide a `timestamp` to take the thumbnail from. |             For videos, you can provide a `timestamp` to take the thumbnail from. | ||||||
|         ''' |         ''' | ||||||
|         chunked_id = chunk_sequence(self.id, 3) |         hopeful_filepath = self.make_thumbnail_filepath() | ||||||
|         basename = chunked_id[-1] |  | ||||||
|         folder = chunked_id[:-1] |  | ||||||
|         folder = os.sep.join(folder) |  | ||||||
|         folder = os.path.join(self.photodb.thumbnail_folder, folder) |  | ||||||
|         if folder: |  | ||||||
|             os.makedirs(folder, exist_ok=True) |  | ||||||
|         hopeful_filepath = os.path.join(folder, basename) + '.jpg' |  | ||||||
|         return_filepath = None |         return_filepath = None | ||||||
| 
 | 
 | ||||||
|         mime = self.mimetype() |         mime = self.mimetype() | ||||||
|  | @ -1828,6 +1886,17 @@ class Photo(ObjectBase): | ||||||
| 
 | 
 | ||||||
|         return False |         return False | ||||||
| 
 | 
 | ||||||
|  |     def make_thumbnail_filepath(self): | ||||||
|  |         chunked_id = chunk_sequence(self.id, 3) | ||||||
|  |         basename = chunked_id[-1] | ||||||
|  |         folder = chunked_id[:-1] | ||||||
|  |         folder = os.sep.join(folder) | ||||||
|  |         folder = os.path.join(self.photodb.thumbnail_folder, folder) | ||||||
|  |         if folder: | ||||||
|  |             os.makedirs(folder, exist_ok=True) | ||||||
|  |         hopeful_filepath = os.path.join(folder, basename) + '.jpg' | ||||||
|  |         return hopeful_filepath | ||||||
|  | 
 | ||||||
|     def mimetype(self): |     def mimetype(self): | ||||||
|         return get_mimetype(self.real_filepath) |         return get_mimetype(self.real_filepath) | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -6,6 +6,9 @@ | ||||||
|     <meta charset="UTF-8"> |     <meta charset="UTF-8"> | ||||||
|     <link rel="stylesheet" href="/static/common.css"> |     <link rel="stylesheet" href="/static/common.css"> | ||||||
|     <script src="/static/common.js"></script> |     <script src="/static/common.js"></script> | ||||||
|  |     {% set filename = photo["id"] + "." + photo["extension"] %} | ||||||
|  |     {% set link = "/file/" + filename %} | ||||||
|  |     {% set mimetype=photo["mimetype"] %} | ||||||
| </head> | </head> | ||||||
| <style> | <style> | ||||||
| #content_body | #content_body | ||||||
|  | @ -46,19 +49,26 @@ | ||||||
|     flex-direction: column; |     flex-direction: column; | ||||||
|     justify-content: center; |     justify-content: center; | ||||||
|     align-items: center; |     align-items: center; | ||||||
|     max-height: 100%; |  | ||||||
|     max-width: 100%; |  | ||||||
|     height: 100%; |     height: 100%; | ||||||
|     width: 100%; |     width: 100%; | ||||||
| } | } | ||||||
| .photo_object a | .photo_object a | ||||||
| { | { | ||||||
|     max-height: 100%; |     height: 100%; | ||||||
|     max-width: 100%; |     width: 100%; | ||||||
|     display: flex; |     display: flex; | ||||||
|     justify-content: center; |     justify-content: center; | ||||||
|     align-items: center; |     align-items: center; | ||||||
| } | } | ||||||
|  | #photo_img_holder | ||||||
|  | { | ||||||
|  |     height: 100%; | ||||||
|  |     width: 100%; | ||||||
|  |     display: flex; | ||||||
|  |     justify-content: center; | ||||||
|  |     align-items: center; | ||||||
|  |     background-repeat: no-repeat; | ||||||
|  | } | ||||||
| .photo_object img | .photo_object img | ||||||
| { | { | ||||||
|     max-height: 100%; |     max-height: 100%; | ||||||
|  | @ -100,12 +110,12 @@ | ||||||
|         <h4>File info</h4> |         <h4>File info</h4> | ||||||
|         <ul id="metadata"> |         <ul id="metadata"> | ||||||
|         {% if photo["width"] %} |         {% if photo["width"] %} | ||||||
|             <li>{{photo["width"]}}x{{photo["height"]}} px</li> |             <li>Dimensions: {{photo["width"]}}x{{photo["height"]}} px</li> | ||||||
|             <li>{{photo["ratio"]}} aspect ratio</li> |             <li>Aspect ratio: {{photo["ratio"]}}</li> | ||||||
|             <li>{{photo["bytestring"]}}</li> |             <li>Size: {{photo["bytestring"]}}</li> | ||||||
|         {% endif %} |         {% endif %} | ||||||
|             <li>{{photo["duration"]}}</li> |  | ||||||
|         {% if photo["duration"] %} |         {% if photo["duration"] %} | ||||||
|  |             <li>Duration: {{photo["duration"]}}</li> | ||||||
|         {% endif %} |         {% endif %} | ||||||
|             <li><a href="/file/{{photo["id"]}}.{{photo["extension"]}}?download=1">Download as {{photo["id"]}}.{{photo["extension"]}}</a></li> |             <li><a href="/file/{{photo["id"]}}.{{photo["extension"]}}?download=1">Download as {{photo["id"]}}.{{photo["extension"]}}</a></li> | ||||||
|             <li><a href="/file/{{photo["id"]}}.{{photo["extension"]}}?download=1&original_filename=1">Download as "{{photo["filename"]}}"</a></li> |             <li><a href="/file/{{photo["id"]}}.{{photo["extension"]}}?download=1&original_filename=1">Download as "{{photo["filename"]}}"</a></li> | ||||||
|  | @ -126,13 +136,11 @@ | ||||||
| </div> | </div> | ||||||
| 
 | 
 | ||||||
| <div id="right"> | <div id="right"> | ||||||
|  |     <!-- THE PHOTO ITSELF --> | ||||||
|     <div class="photo_object"> |     <div class="photo_object"> | ||||||
|         {% set filename = photo["id"] + "." + photo["extension"] %} |  | ||||||
|         {% set link = "/file/" + filename %} |  | ||||||
|         {% set mimetype=photo["mimetype"] %} |  | ||||||
|         {% if mimetype == "image" %} |         {% if mimetype == "image" %} | ||||||
|         <!-- <a target="_blank" href="{{link}}"><img src="{{link}}"></a> --> |         <div id="photo_img_holder"><img id="photo_img" src="{{link}}" onclick="toggle_hoverzoom()" onload="this.style.opacity=0.99"></div> | ||||||
|         <img src="{{link}}"> |         <!-- <img src="{{link}}"> --> | ||||||
|         {% elif mimetype == "video" %} |         {% elif mimetype == "video" %} | ||||||
|         <video src="{{link}}" controls preload=none {%if photo["has_thumbnail"]%}poster="/thumbnail/{{photo["id"]}}.jpg"{%endif%}></video> |         <video src="{{link}}" controls preload=none {%if photo["has_thumbnail"]%}poster="/thumbnail/{{photo["id"]}}.jpg"{%endif%}></video> | ||||||
|         {% elif mimetype == "audio" %} |         {% elif mimetype == "audio" %} | ||||||
|  | @ -152,6 +160,72 @@ var add_tag_button = document.getElementById('add_tag_button'); | ||||||
| var message_area = document.getElementById('message_area'); | var message_area = document.getElementById('message_area'); | ||||||
| add_tag_box.onkeydown = function(){entry_with_history_hook(add_tag_box, add_tag_button)}; | add_tag_box.onkeydown = function(){entry_with_history_hook(add_tag_box, add_tag_button)}; | ||||||
| 
 | 
 | ||||||
|  | function enable_hoverzoom() | ||||||
|  | { | ||||||
|  |     console.log("enable"); | ||||||
|  |     div = document.getElementById("photo_img_holder"); | ||||||
|  |     img = document.getElementById("photo_img"); | ||||||
|  |     if (img.naturalWidth < div.offsetWidth && img.naturalHeight < div.offsetHeight) | ||||||
|  |     { | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  |     img.style.opacity = 0; | ||||||
|  |     img.style.display = "none"; | ||||||
|  |     div.style.cursor = "zoom-out"; | ||||||
|  |     div.style.backgroundImage = "url('{{link}}')"; | ||||||
|  |     div.onmousemove = move_hoverzoom; | ||||||
|  |     setTimeout(function(){div.onclick = disable_hoverzoom;}, 100); | ||||||
|  |     return true; | ||||||
|  | } | ||||||
|  | function disable_hoverzoom() | ||||||
|  | { | ||||||
|  |     console.log("disable"); | ||||||
|  |     div = document.getElementById("photo_img_holder"); | ||||||
|  |     img = document.getElementById("photo_img"); | ||||||
|  |     img.style.opacity = 100; | ||||||
|  |     div.style.cursor = ""; | ||||||
|  |     img.style.display=""; | ||||||
|  |     div.style.backgroundImage = "none"; | ||||||
|  |     div.onmousemove = null; | ||||||
|  |     div.onclick = null; | ||||||
|  | } | ||||||
|  | function toggle_hoverzoom() | ||||||
|  | { | ||||||
|  |     img = document.getElementById("photo_img"); | ||||||
|  |     if (img.style.opacity === "0") | ||||||
|  |     { | ||||||
|  |         disable_hoverzoom(); | ||||||
|  |     } | ||||||
|  |     else | ||||||
|  |     { | ||||||
|  |         enable_hoverzoom(); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | function move_hoverzoom(event) | ||||||
|  | { | ||||||
|  |     div = document.getElementById("photo_img_holder"); | ||||||
|  |     img = document.getElementById("photo_img"); | ||||||
|  |     var x; | ||||||
|  |     var y; | ||||||
|  |     if (img.naturalWidth < div.offsetWidth) | ||||||
|  |     { | ||||||
|  |         x = (img.naturalWidth - div.offsetWidth) / 2; | ||||||
|  |     } | ||||||
|  |     else | ||||||
|  |     { | ||||||
|  |         x = (img.naturalWidth - div.offsetWidth) * (event.offsetX / div.offsetWidth); | ||||||
|  |     } | ||||||
|  |     if (img.naturalHeight < div.offsetHeight) | ||||||
|  |     { | ||||||
|  |         y = (img.naturalHeight - div.offsetHeight) / 2; | ||||||
|  |     } | ||||||
|  |     else | ||||||
|  |     { | ||||||
|  |         y = (img.naturalHeight - div.offsetHeight) * (event.offsetY / div.offsetHeight); | ||||||
|  |     } | ||||||
|  |     //console.log(x); | ||||||
|  |     div.style.backgroundPosition=(-x)+"px "+(-y)+"px"; | ||||||
|  | } | ||||||
| function receive_callback(response) | function receive_callback(response) | ||||||
| { | { | ||||||
|     var tagname = response["tagname"]; |     var tagname = response["tagname"]; | ||||||
|  |  | ||||||
|  | @ -189,6 +189,10 @@ form | ||||||
|             <br> |             <br> | ||||||
| 
 | 
 | ||||||
|             <span>Other filters</span> |             <span>Other filters</span> | ||||||
|  |             <input type="text" class="basic_param" | ||||||
|  |             value="{%if search_kwargs['filename']%}{{search_kwargs['filename']}}{%endif%}" | ||||||
|  |             name="filename" placeholder="Filename"> | ||||||
|  | 
 | ||||||
|             <input type="text" class="basic_param" |             <input type="text" class="basic_param" | ||||||
|             value="{%if search_kwargs['mimetype']%}{{search_kwargs['mimetype']}}{%endif%}" |             value="{%if search_kwargs['mimetype']%}{{search_kwargs['mimetype']}}{%endif%}" | ||||||
|             name="mimetype" placeholder="Mimetype(s)"> |             name="mimetype" placeholder="Mimetype(s)"> | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue