Add the photo_clipboard feature with localStorage.
photo_card objects now have a checkbox which adds them to the clipboard. No pasting or other operations yet.
This commit is contained in:
		
							parent
							
								
									f69d9d409d
								
							
						
					
					
						commit
						55f7da7bb2
					
				
					 5 changed files with 138 additions and 11 deletions
				
			
		|  | @ -130,26 +130,33 @@ is hovered over. | ||||||
|     display:inline; |     display:inline; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | .photo_card | ||||||
|  | { | ||||||
|  |     background-color: #ffffd4; | ||||||
|  | } | ||||||
| .photo_card_list | .photo_card_list | ||||||
| { | { | ||||||
|     display: grid; |     display: grid; | ||||||
|     grid-template-columns: 1fr auto; |     grid-template-columns: auto 1fr auto; | ||||||
|     grid-template-rows: auto; |     grid-template-rows: auto; | ||||||
|     grid-template-areas: |     grid-template-areas: | ||||||
|         "filename metadata"; |         "checkbox filename metadata"; | ||||||
| 
 | 
 | ||||||
|     max-width: 800px; |     max-width: 800px; | ||||||
|     margin: 8px; |     margin: 8px; | ||||||
|     padding: 4px; |     padding: 4px; | ||||||
| 
 |  | ||||||
|     background-color: #ffffd4; |  | ||||||
| } | } | ||||||
| .photo_card_list:hover | .photo_card_list:hover | ||||||
| { | { | ||||||
|     box-shadow: 2px 2px 5px 0px rgba(0,0,0,0.25); |     box-shadow: 2px 2px 5px 0px rgba(0,0,0,0.25); | ||||||
| } | } | ||||||
|  | .photo_card_list .photo_card_selector_checkbox | ||||||
|  | { | ||||||
|  |     grid-area: checkbox; | ||||||
|  | } | ||||||
| .photo_card_grid | .photo_card_grid | ||||||
| { | { | ||||||
|  |     position: relative; | ||||||
|     display: inline-grid; |     display: inline-grid; | ||||||
|     grid-template-columns: auto auto; |     grid-template-columns: auto auto; | ||||||
|     grid-template-rows: auto 1fr auto; |     grid-template-rows: auto 1fr auto; | ||||||
|  | @ -165,8 +172,12 @@ is hovered over. | ||||||
| 
 | 
 | ||||||
|     border-radius: 8px; |     border-radius: 8px; | ||||||
|     box-shadow: 2px 2px 5px 0px rgba(0,0,0,0.25); |     box-shadow: 2px 2px 5px 0px rgba(0,0,0,0.25); | ||||||
| 
 | } | ||||||
|     background-color: #ffffd4; | .photo_card_grid .photo_card_selector_checkbox | ||||||
|  | { | ||||||
|  |     position:absolute; | ||||||
|  |     left:5px; | ||||||
|  |     top:5px; | ||||||
| } | } | ||||||
| .photo_card_thumbnail | .photo_card_thumbnail | ||||||
| { | { | ||||||
|  | @ -187,7 +198,6 @@ is hovered over. | ||||||
|     The min-width:100% + width:0 prevent the info div from controlling |     The min-width:100% + width:0 prevent the info div from controlling | ||||||
|     card size, so we can prioritize the thumbnail instead. |     card size, so we can prioritize the thumbnail instead. | ||||||
|     */ |     */ | ||||||
|     align-self: start; |  | ||||||
|     justify-self: start; |     justify-self: start; | ||||||
|     grid-area: filename; |     grid-area: filename; | ||||||
| 
 | 
 | ||||||
|  | @ -202,6 +212,14 @@ is hovered over. | ||||||
| 
 | 
 | ||||||
|     font-size: 12.8px; |     font-size: 12.8px; | ||||||
| } | } | ||||||
|  | .photo_card_grid .photo_card_filename | ||||||
|  | { | ||||||
|  |     align-self: start; | ||||||
|  | } | ||||||
|  | .photo_card_list .photo_card_filename | ||||||
|  | { | ||||||
|  |     align-self: center; | ||||||
|  | } | ||||||
| .photo_card_filename:hover | .photo_card_filename:hover | ||||||
| { | { | ||||||
|     overflow: visible; |     overflow: visible; | ||||||
|  |  | ||||||
							
								
								
									
										103
									
								
								frontends/etiquette_flask/static/photoclipboard.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										103
									
								
								frontends/etiquette_flask/static/photoclipboard.js
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,103 @@ | ||||||
|  | var photo_clipboard = new Set(); | ||||||
|  | 
 | ||||||
|  | function load_photo_clipboard(event) | ||||||
|  | { | ||||||
|  |     console.log("Loading photo clipboard"); | ||||||
|  |     var stored = localStorage.getItem("photo_clipboard"); | ||||||
|  |     if (stored === null) | ||||||
|  |     { | ||||||
|  |         if (photo_clipboard.size != 0) | ||||||
|  |         { | ||||||
|  |             photo_clipboard = new Set(); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     else | ||||||
|  |     { | ||||||
|  |         photo_clipboard = new Set(JSON.parse(stored)); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     var photo_divs = Array.from(document.getElementsByClassName("photo_card")); | ||||||
|  |     photo_divs.forEach(apply_check); | ||||||
|  |     return photo_clipboard; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function save_photo_clipboard() | ||||||
|  | { | ||||||
|  |     console.log("Saving photo clipboard"); | ||||||
|  |     var serialized = JSON.stringify(Array.from(photo_clipboard)); | ||||||
|  |     localStorage.setItem("photo_clipboard", serialized); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function apply_check(photo_div) | ||||||
|  | { | ||||||
|  |     var checkbox = photo_div.getElementsByClassName("photo_card_selector_checkbox")[0]; | ||||||
|  |     if (photo_clipboard.has(photo_div.dataset.id)) | ||||||
|  |     { | ||||||
|  |         checkbox.checked = true; | ||||||
|  |     } | ||||||
|  |     else | ||||||
|  |     { | ||||||
|  |         checkbox.checked = false; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | var previous_photo_select; | ||||||
|  | function on_photo_select(event) | ||||||
|  | { | ||||||
|  |     if (event.target.checked) | ||||||
|  |     { | ||||||
|  |         action = function(photo_div) | ||||||
|  |         { | ||||||
|  |             photo_div.getElementsByClassName("photo_card_selector_checkbox")[0].checked = true; | ||||||
|  |             photo_clipboard.add(photo_div.dataset.id); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     else | ||||||
|  |     { | ||||||
|  |         action = function(photo_div) | ||||||
|  |         { | ||||||
|  |             photo_div.getElementsByClassName("photo_card_selector_checkbox")[0].checked = false; | ||||||
|  |             photo_clipboard.delete(photo_div.dataset.id); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     if (event.shiftKey && previous_photo_select !== undefined) | ||||||
|  |     { | ||||||
|  |         var current_photo_div = event.target.parentElement; | ||||||
|  |         var previous_photo_div = previous_photo_select.target.parentElement; | ||||||
|  |         var photo_divs = Array.from(current_photo_div.parentElement.children); | ||||||
|  | 
 | ||||||
|  |         var current_index = photo_divs.indexOf(current_photo_div); | ||||||
|  |         var previous_index = photo_divs.indexOf(previous_photo_div); | ||||||
|  | 
 | ||||||
|  |         var slice; | ||||||
|  |         if (current_index == previous_index) | ||||||
|  |         { | ||||||
|  |             slice = [current_photo_div]; | ||||||
|  |         } | ||||||
|  |         else if (previous_index < current_index) | ||||||
|  |         { | ||||||
|  |             slice = photo_divs.slice(previous_index, current_index + 1); | ||||||
|  |         } | ||||||
|  |         else | ||||||
|  |         { | ||||||
|  |             slice = photo_divs.slice(current_index, previous_index + 1); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         slice.forEach(action); | ||||||
|  |     } | ||||||
|  |     else | ||||||
|  |     { | ||||||
|  |         var photo_div = event.target.parentElement; | ||||||
|  |         action(photo_div); | ||||||
|  |     } | ||||||
|  |     previous_photo_select = event; | ||||||
|  |     save_photo_clipboard(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function onpageload() | ||||||
|  | { | ||||||
|  |     window.addEventListener("storage", load_photo_clipboard, false); | ||||||
|  |     load_photo_clipboard(); | ||||||
|  | } | ||||||
|  | document.addEventListener("DOMContentLoaded", onpageload); | ||||||
|  | @ -8,6 +8,7 @@ | ||||||
|     <meta name="viewport" content="width=device-width, initial-scale=1.0"/> |     <meta name="viewport" content="width=device-width, initial-scale=1.0"/> | ||||||
|     <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> | ||||||
|  |     <script src="/static/photoclipboard.js"></script> | ||||||
| 
 | 
 | ||||||
| <style> | <style> | ||||||
| p | p | ||||||
|  |  | ||||||
|  | @ -17,12 +17,13 @@ | ||||||
| {% macro create_photo_card(photo, view="grid") %} | {% macro create_photo_card(photo, view="grid") %} | ||||||
| 
 | 
 | ||||||
| {% if view == "list" %} | {% if view == "list" %} | ||||||
| <div class="photo_card_list"> | <div class="photo_card photo_card_list" data-id="{{photo.id}}"> | ||||||
|  |     <input type="checkbox" class="photo_card_selector_checkbox" onclick="on_photo_select(event)"/> | ||||||
|     <span class="photo_card_filename"><a target="_blank" href="/photo/{{photo.id}}">{{photo.basename}}</a></span> |     <span class="photo_card_filename"><a target="_blank" href="/photo/{{photo.id}}">{{photo.basename}}</a></span> | ||||||
|     <a class="photo_card_metadata" target="_blank" href="/file/{{photo.id}}.{{photo.extension}}">{{photo.bytestring()}}</a> |     <a class="photo_card_metadata" target="_blank" href="/file/{{photo.id}}.{{photo.extension}}">{{photo.bytestring()}}</a> | ||||||
| </div> | </div> | ||||||
| 
 |  | ||||||
| {% else %} | {% else %} | ||||||
|  | 
 | ||||||
| {% if photo.thumbnail %} | {% if photo.thumbnail %} | ||||||
|     {% set thumbnail_src = "/thumbnail/" + photo.id + ".jpg" %} |     {% set thumbnail_src = "/thumbnail/" + photo.id + ".jpg" %} | ||||||
| {% else %} | {% else %} | ||||||
|  | @ -39,6 +40,7 @@ | ||||||
| {% for tag in photo.tags() %} | {% for tag in photo.tags() %} | ||||||
|     {% do tag_names_title.append(tag.name) %} |     {% do tag_names_title.append(tag.name) %} | ||||||
| {% endfor %} | {% endfor %} | ||||||
|  | 
 | ||||||
| {% set tag_names_title = ", ".join(tag_names_title) %} | {% set tag_names_title = ", ".join(tag_names_title) %} | ||||||
| {% if tag_names_title %} | {% if tag_names_title %} | ||||||
|     {% set tag_names_inner = "T" %} |     {% set tag_names_inner = "T" %} | ||||||
|  | @ -54,7 +56,7 @@ | ||||||
|     {% set metadata_inner = "{m}{d}, ".format(m=metadata_inner, d=photo.duration_string) %} |     {% set metadata_inner = "{m}{d}, ".format(m=metadata_inner, d=photo.duration_string) %} | ||||||
| {% endif %} | {% endif %} | ||||||
| 
 | 
 | ||||||
| <div class="photo_card_grid"> | <div class="photo_card photo_card_grid" data-id="{{photo.id}}"> | ||||||
|     <a class="photo_card_thumbnail" target="_blank" href="/photo/{{photo.id}}"> |     <a class="photo_card_thumbnail" target="_blank" href="/photo/{{photo.id}}"> | ||||||
|         <img height="150" src="{{thumbnail_src}}"> |         <img height="150" src="{{thumbnail_src}}"> | ||||||
|     </a> |     </a> | ||||||
|  | @ -69,6 +71,8 @@ | ||||||
|     {{- metadata_inner|safe -}} |     {{- metadata_inner|safe -}} | ||||||
|     <a target="_blank" href="/file/{{photo.id}}.{{photo.extension}}">{{photo.bytestring()}}</a> |     <a target="_blank" href="/file/{{photo.id}}.{{photo.extension}}">{{photo.bytestring()}}</a> | ||||||
|     </span> |     </span> | ||||||
|  | 
 | ||||||
|  |     <input type="checkbox" class="photo_card_selector_checkbox" onclick="on_photo_select(event)"/> | ||||||
| </div> | </div> | ||||||
| {% endif %} | {% endif %} | ||||||
| {% endmacro %} | {% endmacro %} | ||||||
|  |  | ||||||
|  | @ -9,6 +9,7 @@ | ||||||
|     <meta name="viewport" content="width=device-width, initial-scale=1.0"/> |     <meta name="viewport" content="width=device-width, initial-scale=1.0"/> | ||||||
|     <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> | ||||||
|  |     <script src="/static/photoclipboard.js"></script> | ||||||
| 
 | 
 | ||||||
| <style> | <style> | ||||||
| form | form | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue