ImageGrid/ui/index.html

731 lines
14 KiB
HTML
Raw Normal View History

<html>
<head>
<title>ImageGrid.Viewer</title>
<style>
/*
* XXX move the CSS to a separate file...
* XXX split-off styling/coloring from layout...
*/
body {
font-family: sans-serif;
padding: 0px;
margin: 0px;
}
.viewer {
position: relative;
width: 100%;
height: 100%;
overflow: hidden;
/*border: solid blue 1px;*/
box-sizing: border-box;
-moz-user-select: none;
-webkit-user-select: none;
-o-user-select: none;
-ms-user-select: none;
user-select: none;
}
.ribbon-set {
position: absolute;
display: block;
/* NOTE: this needs for scaling/zooming to behave correctly and not
shift the element, when its dimensions change...
...this is because .ribbon-set will both be used for scaling
and aligning... */
transform-origin: top left;
-ms-transform-origin: top left;
-webkit-transform-origin: top left; /* Safari and Chrome */
}
.ribbon-set:empty:after {
display: block;
top: 0px;
left: 0px;
width: 100%;
height: 100%;
content: "Empty";
text-align: center;
}
.ribbon {
position: relative;
display: block;
height: auto;
min-width: 0px;
overflow: visible;
white-space: nowrap;
font-size: 0;
margin-top: 20px;
margin-bottom: 20px;
}
.ribbon:empty {
display: none;
}
.ribbon:first-child {
margin-top: 0px;
}
.ribbon:last-child {
margin-bottom: 0px;
}
.image {
position: relative;
display: inline-block;
vertical-align: middle;
text-align:left;
width: 300px;
height: 300px;
font-size: 12pt;
overflow: hidden;
box-sizing: border-box;
color: white;
text-shadow: black 0.1em 0.1em 0.4em, black 0.1em 0.1em;
background: no-repeat 50% black;
background-size: contain;
/* XXX do we need this? */
border: solid black 5px;
}
.current.image {
background: no-repeat 50% black;
background-size: contain;
/* XXX remove this... */
border: solid red 5px;
}
/* image turning... */
/* NOTE: need to account for proportions after turning... */
.image[orientation="90"] {
-webkit-transform: rotate(90deg);
-moz-transform: rotate(90deg);
-o-transform: rotate(90deg);
-ms-transform: rotate(90deg);
transform: rotate(90deg);
}
.image[orientation="180"] {
-webkit-transform: rotate(180deg);
-moz-transform: rotate(180deg);
-o-transform: rotate(180deg);
-ms-transform: rotate(180deg);
transform: rotate(180deg);
}
.image[orientation="270"] {
-webkit-transform: rotate(270deg);
-moz-transform: rotate(270deg);
-o-transform: rotate(270deg);
-ms-transform: rotate(270deg);
transform: rotate(270deg);
}
/* dot mark... */
.marks-visible.viewer .marked.image:after {
display: block;
position: absolute;
content: "";
font-size: 0pt;
border: none;
width: 15px;
height: 15px;
bottom: 5px;
right: 5px;
border-radius: 50%;
background: blue;
}
.marks-visible.viewer .marked.image[orientation="90"]:after {
top: 5px;
right: 5px;
}
.marks-visible.viewer .marked.image[orientation="180"]:after {
top: 5px;
left: 5px;
}
.marks-visible.viewer .marked.image[orientation="270"]:after {
bottom: 5px;
left: 5px;
}
/* corner mark... (a-la bookmarks in PortableMag) */
/*
.marks-visible.viewer .marked.image:after {
display: block;
position: absolute;
content: "";
font-size: 0pt;
border: none;
width: 30px;
height: 30px;
top: -15px;
right: -15px;
background: blue;
-webkit-transform: rotate(45deg);
-moz-transform: rotate(45deg);
-o-transform: rotate(45deg);
-ms-transform: rotate(45deg);
transform: rotate(45deg);
}
.marks-visible.viewer .marked.image[orientation="90"]:after {
top: -15px;
left: -15px;
}
.marks-visible.viewer .marked.image[orientation="180"]:after {
bottom: -15px;
left: -15px;
}
.marks-visible.viewer .marked.image[orientation="270"]:after {
bottom: -15px;
right: -15px;
}
*/
.marks-visible.viewer:after {
display: block;
position: absolute;
content: "";
font-size: 0pt;
top: 10px;
right: 10px;
width: 10px;
height: 10px;
border: solid 2px blue;
border-radius: 50%;
background: blue;
}
.marked-only-view.viewer:after {
display: block;
position: absolute;
content: "";
font-size: 0pt;
top: 10px;
right: 10px;
width: 10px;
height: 10px;
border: solid 2px blue;
border-radius: 50%;
background: transparent;
}
.marked-only-view.marks-visible.viewer:after {
background: blue;
}
/* XXX should we use opacity??? */
.marked-only-view.viewer:not(.marks-visible) .image:not(.marked) {
opacity: 0.3;
}
/* Image info */
.image .inline-image-info {
display: none;
position: absolute;
bottom: 0px;
width: 100%;
background: black;
opacity: 0.7;
-moz-user-select: auto;
-webkit-user-select: auto;
-o-user-select: auto;
-ms-user-select: auto;
user-select: auto;
}
.image .inline-image-info::selection {
color: white;
background: red;
}
.image-info-visible.viewer .global-image-info,
.image-info-visible.viewer .image:hover .inline-image-info {
display: block;
}
.single-image-mode.viewer .image:hover .inline-image-info {
display: none;
}
.image[orientation="90"] .inline-image-info {
top: auto;
left: 100%;
-ms-transform-origin: bottom left;
-webkit-transform-origin: bottom left;
transform-origin: bottom left;
-webkit-transform: rotate(-90deg);
-moz-transform: rotate(-90deg);
-o-transform: rotate(-90deg);
-ms-transform: rotate(-90deg);
transform: rotate(-90deg);
}
.image[orientation="180"] .inline-image-info {
top: 0px;
bottom: auto;
-webkit-transform: rotate(180deg);
-moz-transform: rotate(180deg);
-o-transform: rotate(180deg);
-ms-transform: rotate(180deg);
transform: rotate(180deg);
}
.image[orientation="270"] .inline-image-info {
top: auto;
left: auto;
right: 100%;
-ms-transform-origin: bottom right;
-webkit-transform-origin: bottom right;
transform-origin: bottom right;
-webkit-transform: rotate(90deg);
-moz-transform: rotate(90deg);
-o-transform: rotate(90deg);
-ms-transform: rotate(90deg);
transform: rotate(90deg);
}
.overlay-info {
display: none;
position: absolute;
bottom: 0px;
left: 0px;
width: 100%;
padding: 2px;
padding-left: 10px;
padding-right: 10px;
box-sizing: border-box;
background: black;
color: white;
opacity: 0.6;
-moz-user-select: auto;
-webkit-user-select: auto;
-o-user-select: auto;
-ms-user-select: auto;
user-select: auto;
}
.overlay-info .float-right {
float: right;
}
.overlay-info .secondary {
font-style: italic;
font-size: small;
color: silver;
}
.overlay-info::selection,
.overlay-info ::selection {
color: white;
background: red;
}
.up-indicator,
.down-indicator,
.start-indicator,
.end-indicator {
display: block;
position: absolute;
content: "";
top: 0px;
left: 50%;
height: 50px;
width: 100px;
margin-left: -50px;
overflow: hidden;
cursor: hand;
}
.up-indicator:after,
.down-indicator:after {
display: inline-block;
position: absolute;
content: "";
width: 50px;
height: 50px;
bottom: -25px;
left: 25px;
background: yellow;
-webkit-transform: rotate(45deg);
-moz-transform: rotate(45deg);
-o-transform: rotate(45deg);
-ms-transform: rotate(45deg);
transform: rotate(45deg);
}
.down-indicator {
top: auto;
bottom: 0px;
}
.down-indicator:after {
top: -25px;
bottom: auto;
}
.start-indicator,
.end-indicator {
left: 0px;
width: 10px;
height: 100%;
margin: 0px;
background: yellow;
}
.end-indicator {
left: auto;
right: 0px;
}
/* default state */
.up-indicator,
.down-indicator,
.start-indicator,
.end-indicator {
display: none;
}
.single-image-mode.viewer .image {
background-color: transparent;
/* NOTE: need to keep a distance from screen borders... */
border: solid transparent 2px;
}
.single-image-mode.viewer .image:not(.current) {
/* XXX for some reason this breaks the alignment on large magnifications...
display: none;
*/
/* XXX this makes images pass through the :visible filter...
opacity: 0;
*/
visibility: hidden;
}
/* XXX this is by no means final... */
.viewer,
.light.viewer,
.light.viewer .overlay-block .background {
background: white;
}
.gray.viewer,
.gray.viewer .overlay-block .background {
background: #333;
}
.dark.viewer,
.dark.viewer .overlay-block .background {
background: #0a0a0a;
}
/* Overlay */
.overlay-block {
display: none;
position: absolute:
top: 0px;
left: 0px;
height: 100%;
width: 100%;
}
.viewer.overlay .overlay-block {
display: block;
}
.overlay-block .content {
}
.overlay-block .background {
position: absolute:
top: 0px;
left: 0px;
height: 100%;
width: 100%;
opacity: 0.7;
}
/* this is for sliding stuff */
.viewer.help-mode {
box-shadow: 0px 0px 50px 0px silver;
}
/* help */
.keyboard-help {
width: 80%;
margin-top: 20px;
margin-left: 15%;
margin-right: 5%;
margin-bottom: 100px;
}
.keyboard-help .section-doc {
font-size: small;
vertical-align: top;
font-style: italic;
}
.keyboard-help th {
text-align: left;
height: 50px;
vertical-align: bottom;
border-bottom: solid gray 1px;
}
.keyboard-help tr:hover {
background: #eee;
vertical-align: top;
}
.keyboard-help tr td:first-child {
color: gray;
font-style: italic;
padding-right: 20px;
padding-left: 10px;
}
.keyboard-help .section-doc td:only-child {
padding-right: 0px;
padding-left: 0px;
}
/* utility */
.expanding-text .hidden {
display: none;
}
.expanding-text:hover .shown {
display: none;
}
.expanding-text:hover .hidden {
display: inline;
}
</style>
<script src="ext-lib/jquery.js"></script>
<script src="lib/jli.js"></script>
<script src="lib/keyboard.js"></script>
<script src="base.js"></script>
<script src="modes.js"></script>
<script src="marks.js"></script>
<script src="data.js"></script>
<script src="ui.js"></script>
<script src="keybindings.js"></script>
<!-- XXX STUB -->
<script src="images.js"></script>
<script>
//DEBUG = true
// setup...
$(function(){
toggleTheme('gray')
// NOTE: this is global so as to not to add any extra complexity to
// the internal workings...
$('.viewer')
.click(clickHandler)
// XXX for some reason this messes up alignment on initial view...
//.dblclick(dblClickHandler)
$(window)
.resize(function() {
// XXX should this be animated or not?
centerView()
})
$(document)
.keydown(makeKeyboardHandler(
KEYBOARD_CONFIG,
function(k){
window.DEBUG && console.log(k)
}))
.on('mouseover', function(evt){
var img = $(evt.target).closest('.image')
if(img.length > 0){
if(IMAGE_INFO){
if(img.find('.inline-image-info:visible').length == 0){
updateInlineImageInfo(img)
}
} else {
img.find('.inline-image-info').remove()
}
}
})
setupDataBindings()
/* XXX drag/drop
$(document)
.bind('dragover', function(e){
e.stopPropagation()
e.preventDefault()
// XXX is there a jQuery way out of this??
e.originalEvent.dataTransfer.dropEffect = 'copy' // Explicitly show this is a copy.
})
.bind('drop', function(e){
e.stopPropagation()
e.preventDefault()
// XXX is there a jQuery way out of this??
var files = e.originalEvent.dataTransfer.files
// XXX should we be using the loadJSON here???
// XXX desperatly need image caching and preview generation...
for (var i = 0, f; f = files[i]; i++) {
if (!f.type.match('image.*')) {
continue
}
console.log('FILE:', f)
var reader = new FileReader()
reader.onload = function(i){
return function(e){
// XXX need to avoid data URLs here and use plain old paths...
//ribbon.append(makeImage(e.target.result, i))
console.log('DROPPED')//, e.target.result)
}
}(i)
reader.readAsDataURL(f)
//reader.readAsText(f)
}
})
*/
//setElementOrigin($('.ribbon-set'), 'top', 'left')
// we have an image file...
if((DATA_ATTR + '_BASE_URL') in localStorage){
BASE_URL = localStorage[DATA_ATTR + '_BASE_URL']
var loading = loadDir(BASE_URL)
} else {
// everything is in localStorage...
if('DATA' in localStorage){
loadLocalStorage()
// legacy default data...
} else {
DATA = convertDataGen1(image_list)
DATA = DATA.data
IMAGES = DATA.images
loadData()
}
var loading = $.Deferred().resolve()
}
loading
.done(function(){
console.log('Loading settings...')
loadLocalStorageSettings()
// XXX this will reload everything...
if('MARKED' in localStorage){
loadLocalStorageMarks()
}
updateImages()
})
})
</script>
</head>
<body>
<!-- This is the basic viewer structure...
Unpopulated
NOTE: there can be only .ribbon-set element.
<div class="viewer">
<div class="ribbon-set"></div>
</div>
Populated
<div class="viewer">
<div class="ribbon-set">
<div class="ribbon">
<div class="image"></div>
<div class="image"></div>
</div>
<div class="ribbon">
<div class="image"></div>
<div class="current image"></div>
<div class="image"></div>
<div class="image"></div>
</div>
</div>
</div>
-->
<div class="viewer">
<div class="ribbon-set"></div>
<!-- XXX should these be here??? -->
<div class="up-indicator"></div>
<div class="down-indicator"></div>
<div class="start-indicator"></div>
<div class="end-indicator"></div>
<div class="overlay-block">
<div class="background"></div>
<div class="content"></div>
</div>
</div>
<!-- vim:set ts=4 sw=4 spell : -->
</body>
</html>