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; | ||||
| } | ||||
| 
 | ||||
| .photo_card | ||||
| { | ||||
|     background-color: #ffffd4; | ||||
| } | ||||
| .photo_card_list | ||||
| { | ||||
|     display: grid; | ||||
|     grid-template-columns: 1fr auto; | ||||
|     grid-template-columns: auto 1fr auto; | ||||
|     grid-template-rows: auto; | ||||
|     grid-template-areas: | ||||
|         "filename metadata"; | ||||
|         "checkbox filename metadata"; | ||||
| 
 | ||||
|     max-width: 800px; | ||||
|     margin: 8px; | ||||
|     padding: 4px; | ||||
| 
 | ||||
|     background-color: #ffffd4; | ||||
| } | ||||
| .photo_card_list:hover | ||||
| { | ||||
|     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 | ||||
| { | ||||
|     position: relative; | ||||
|     display: inline-grid; | ||||
|     grid-template-columns: auto auto; | ||||
|     grid-template-rows: auto 1fr auto; | ||||
|  | @ -165,8 +172,12 @@ is hovered over. | |||
| 
 | ||||
|     border-radius: 8px; | ||||
|     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 | ||||
| { | ||||
|  | @ -187,7 +198,6 @@ is hovered over. | |||
|     The min-width:100% + width:0 prevent the info div from controlling | ||||
|     card size, so we can prioritize the thumbnail instead. | ||||
|     */ | ||||
|     align-self: start; | ||||
|     justify-self: start; | ||||
|     grid-area: filename; | ||||
| 
 | ||||
|  | @ -202,6 +212,14 @@ is hovered over. | |||
| 
 | ||||
|     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 | ||||
| { | ||||
|     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"/> | ||||
|     <link rel="stylesheet" href="/static/common.css"> | ||||
|     <script src="/static/common.js"></script> | ||||
|     <script src="/static/photoclipboard.js"></script> | ||||
| 
 | ||||
| <style> | ||||
| p | ||||
|  |  | |||
|  | @ -17,12 +17,13 @@ | |||
| {% macro create_photo_card(photo, view="grid") %} | ||||
| 
 | ||||
| {% 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> | ||||
|     <a class="photo_card_metadata" target="_blank" href="/file/{{photo.id}}.{{photo.extension}}">{{photo.bytestring()}}</a> | ||||
| </div> | ||||
| 
 | ||||
| {% else %} | ||||
| 
 | ||||
| {% if photo.thumbnail %} | ||||
|     {% set thumbnail_src = "/thumbnail/" + photo.id + ".jpg" %} | ||||
| {% else %} | ||||
|  | @ -39,6 +40,7 @@ | |||
| {% for tag in photo.tags() %} | ||||
|     {% do tag_names_title.append(tag.name) %} | ||||
| {% endfor %} | ||||
| 
 | ||||
| {% set tag_names_title = ", ".join(tag_names_title) %} | ||||
| {% if tag_names_title %} | ||||
|     {% set tag_names_inner = "T" %} | ||||
|  | @ -54,7 +56,7 @@ | |||
|     {% set metadata_inner = "{m}{d}, ".format(m=metadata_inner, d=photo.duration_string) %} | ||||
| {% 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}}"> | ||||
|         <img height="150" src="{{thumbnail_src}}"> | ||||
|     </a> | ||||
|  | @ -69,6 +71,8 @@ | |||
|     {{- metadata_inner|safe -}} | ||||
|     <a target="_blank" href="/file/{{photo.id}}.{{photo.extension}}">{{photo.bytestring()}}</a> | ||||
|     </span> | ||||
| 
 | ||||
|     <input type="checkbox" class="photo_card_selector_checkbox" onclick="on_photo_select(event)"/> | ||||
| </div> | ||||
| {% endif %} | ||||
| {% endmacro %} | ||||
|  |  | |||
|  | @ -9,6 +9,7 @@ | |||
|     <meta name="viewport" content="width=device-width, initial-scale=1.0"/> | ||||
|     <link rel="stylesheet" href="/static/common.css"> | ||||
|     <script src="/static/common.js"></script> | ||||
|     <script src="/static/photoclipboard.js"></script> | ||||
| 
 | ||||
| <style> | ||||
| form | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue