2013-04-26 05:30:56 +04:00
|
|
|
<html>
|
|
|
|
|
<head>
|
|
|
|
|
<title>ImageGrid.Viewer</title>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<style>
|
|
|
|
|
|
2013-05-03 02:27:54 +04:00
|
|
|
/*
|
|
|
|
|
* XXX move the CSS to a separate file...
|
|
|
|
|
* XXX split-off styling/coloring from layout...
|
|
|
|
|
*/
|
|
|
|
|
|
2013-04-26 05:30:56 +04:00
|
|
|
.viewer {
|
|
|
|
|
position: relative;
|
|
|
|
|
width: 800px;
|
|
|
|
|
height: 600px;
|
2013-04-29 01:59:59 +04:00
|
|
|
overflow: hidden;
|
2013-04-26 05:30:56 +04:00
|
|
|
|
|
|
|
|
border: solid blue 1px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.ribbon-set {
|
2013-04-29 01:59:59 +04:00
|
|
|
position: absolute;
|
2013-04-26 05:30:56 +04:00
|
|
|
}
|
|
|
|
|
.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;
|
|
|
|
|
}
|
2013-04-30 00:28:47 +04:00
|
|
|
.ribbon:empty {
|
|
|
|
|
display: none;
|
|
|
|
|
}
|
2013-04-26 05:30:56 +04:00
|
|
|
.ribbon:first-child {
|
|
|
|
|
margin-top: 0px;
|
|
|
|
|
}
|
|
|
|
|
.ribbon:last-child {
|
|
|
|
|
margin-bottom: 0px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.image {
|
|
|
|
|
position: relative;
|
|
|
|
|
display: inline-block;
|
|
|
|
|
vertical-align: middle;
|
|
|
|
|
text-align;left;
|
2013-04-29 19:12:19 +04:00
|
|
|
width: 300px;
|
|
|
|
|
height: 300px;
|
2013-04-26 05:30:56 +04:00
|
|
|
font-size: 12pt;
|
2013-04-29 23:07:47 +04:00
|
|
|
overflow: hidden;
|
2013-04-26 05:30:56 +04:00
|
|
|
|
2013-04-29 19:12:19 +04:00
|
|
|
box-sizing: border-box;
|
2013-04-26 05:30:56 +04:00
|
|
|
color: white;
|
2013-05-12 14:31:03 +04:00
|
|
|
|
|
|
|
|
background: no-repeat 50% black;
|
|
|
|
|
background-size: contain;
|
|
|
|
|
/* XXX do we need this? */
|
|
|
|
|
border: solid black 5px;
|
2013-04-26 05:30:56 +04:00
|
|
|
}
|
|
|
|
|
.current.image {
|
2013-05-12 14:31:03 +04:00
|
|
|
background: no-repeat 50% black;
|
|
|
|
|
background-size: contain;
|
|
|
|
|
|
|
|
|
|
/* XXX remove this... */
|
|
|
|
|
border: solid red 5px;
|
2013-04-26 05:30:56 +04:00
|
|
|
}
|
|
|
|
|
|
2013-04-29 23:07:47 +04:00
|
|
|
/* dot mark... */
|
2013-04-29 19:12:19 +04:00
|
|
|
.marked.image:after {
|
|
|
|
|
display: block;
|
|
|
|
|
position: absolute;
|
|
|
|
|
content: "";
|
|
|
|
|
font-size: 0pt;
|
|
|
|
|
border: none;
|
|
|
|
|
|
2013-04-29 23:07:47 +04:00
|
|
|
width: 15px;
|
|
|
|
|
height: 15px;
|
2013-04-29 19:12:19 +04:00
|
|
|
|
|
|
|
|
bottom: 5px;
|
|
|
|
|
right: 5px;
|
|
|
|
|
|
|
|
|
|
border-radius: 50%;
|
|
|
|
|
background: blue;
|
|
|
|
|
}
|
|
|
|
|
|
2013-04-29 23:07:47 +04:00
|
|
|
/* corner mark... (a-la bookmarks in PortableMag) */
|
|
|
|
|
/*
|
|
|
|
|
.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);
|
|
|
|
|
}
|
|
|
|
|
*/
|
2013-04-26 05:30:56 +04:00
|
|
|
|
2013-04-30 00:28:47 +04:00
|
|
|
|
|
|
|
|
.marked-only.viewer:after {
|
|
|
|
|
display: block;
|
|
|
|
|
position: absolute;
|
|
|
|
|
content: "Showing marked images only";
|
|
|
|
|
font-size: 14pt;
|
|
|
|
|
border: none;
|
|
|
|
|
color: blue;
|
|
|
|
|
width: auto;
|
|
|
|
|
height: auto;
|
|
|
|
|
|
|
|
|
|
top: 10px;
|
|
|
|
|
right: 10px;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
.marked-only .image:not(.marked) {
|
|
|
|
|
display: none;
|
|
|
|
|
}
|
|
|
|
|
.marked-only .marked.image:after {
|
|
|
|
|
display: none;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2013-04-30 00:54:32 +04:00
|
|
|
.up-indicator,
|
2013-05-03 19:24:06 +04:00
|
|
|
.down-indicator,
|
|
|
|
|
.start-indicator,
|
|
|
|
|
.end-indicator {
|
2013-04-30 00:54:32 +04:00
|
|
|
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;
|
|
|
|
|
|
2013-04-30 01:30:02 +04:00
|
|
|
background: yellow;
|
2013-04-30 00:54:32 +04:00
|
|
|
|
|
|
|
|
-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;
|
|
|
|
|
}
|
2013-05-03 19:24:06 +04:00
|
|
|
.start-indicator,
|
|
|
|
|
.end-indicator {
|
|
|
|
|
left: 0px;
|
|
|
|
|
width: 10px;
|
|
|
|
|
height: 100%;
|
|
|
|
|
margin: 0px;
|
|
|
|
|
|
|
|
|
|
background: yellow;
|
|
|
|
|
}
|
|
|
|
|
.end-indicator {
|
|
|
|
|
left: auto;
|
|
|
|
|
right: 0px;
|
|
|
|
|
}
|
2013-04-30 00:54:32 +04:00
|
|
|
/* default state */
|
|
|
|
|
.up-indicator,
|
2013-05-03 19:24:06 +04:00
|
|
|
.down-indicator,
|
|
|
|
|
.start-indicator,
|
|
|
|
|
.end-indicator {
|
|
|
|
|
display: none;
|
2013-04-30 00:54:32 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2013-04-26 05:30:56 +04:00
|
|
|
</style>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<script src="jquery.js"></script>
|
|
|
|
|
|
2013-04-26 23:07:07 +04:00
|
|
|
<script src="lib/jli.js"></script>
|
|
|
|
|
<script src="lib/keyboard.js"></script>
|
|
|
|
|
|
2013-05-02 19:47:04 +04:00
|
|
|
<script src="ImageGrid.js"></script>
|
2013-05-03 01:29:43 +04:00
|
|
|
<script src="keybindings3.js"></script>
|
2013-04-29 02:31:01 +04:00
|
|
|
|
2013-05-02 19:47:04 +04:00
|
|
|
<script>
|
2013-04-29 02:31:01 +04:00
|
|
|
|
2013-04-26 05:30:56 +04:00
|
|
|
// setup...
|
|
|
|
|
$(function(){
|
|
|
|
|
|
|
|
|
|
// populate the viewer...
|
|
|
|
|
var r = createRibbon()
|
|
|
|
|
var images = []
|
|
|
|
|
for(var i=0; i < 40; i++){
|
|
|
|
|
images.push(createImage().text(i)[0])
|
|
|
|
|
}
|
|
|
|
|
r.append($(images))
|
2013-05-03 04:18:47 +04:00
|
|
|
//var rr = r.clone()
|
|
|
|
|
//var rrr = r.clone()
|
2013-04-26 05:30:56 +04:00
|
|
|
|
2013-05-07 02:16:57 +04:00
|
|
|
// XXX use something like loadImages()...
|
2013-04-26 05:30:56 +04:00
|
|
|
$('.ribbon-set')
|
|
|
|
|
.append(r)
|
2013-05-03 04:18:47 +04:00
|
|
|
//.append(rr)
|
|
|
|
|
//.append(rrr)
|
2013-04-26 05:30:56 +04:00
|
|
|
|
|
|
|
|
// NOTE: this is global so as to not to add any extra complexity to
|
|
|
|
|
// the internal workings...
|
2013-05-03 17:08:59 +04:00
|
|
|
$('.viewer')
|
|
|
|
|
.click(clickHandler)
|
2013-04-26 05:30:56 +04:00
|
|
|
|
2013-05-02 23:22:43 +04:00
|
|
|
$(document)
|
|
|
|
|
.keydown(makeKeyboardHandler(
|
|
|
|
|
KEYBOARD_CONFIG,
|
|
|
|
|
function(k){console.log(k)}))
|
2013-05-03 17:08:59 +04:00
|
|
|
|
|
|
|
|
|
2013-05-07 02:16:57 +04:00
|
|
|
|
2013-05-06 02:18:36 +04:00
|
|
|
// dynamic loading...
|
2013-05-07 02:16:57 +04:00
|
|
|
DYNAMIC_LOADING = true
|
|
|
|
|
|
|
|
|
|
if(DYNAMIC_LOADING){
|
2013-05-07 00:26:35 +04:00
|
|
|
// XXX move to a setup function in the lib...
|
|
|
|
|
// XXX update this depending on zoom and navigation speed...
|
2013-05-12 14:31:03 +04:00
|
|
|
var LOAD_SCREENS = 2
|
2013-05-07 00:26:35 +04:00
|
|
|
// XXX update this depending on zoom and navigation speed...
|
2013-05-12 15:28:15 +04:00
|
|
|
var LOAD_THRESHOLD = 1
|
2013-05-07 00:26:35 +04:00
|
|
|
$('.viewer')
|
2013-05-12 15:28:15 +04:00
|
|
|
// XXX still some times does not load the needed ribbon section
|
|
|
|
|
// on the first try...
|
|
|
|
|
// Example state:
|
|
|
|
|
// 0 [50] 99
|
|
|
|
|
// .. .. .. .. .. .. ..
|
|
|
|
|
// in this case moving between the top ribbon images
|
|
|
|
|
// does not center the bottom ribbon right away, needs
|
|
|
|
|
// several clicks on the current image to get there...
|
|
|
|
|
// ...also when going down from 50 lastImage() behaves
|
|
|
|
|
// in a very odd way, going back and froth rather than
|
|
|
|
|
// reaching 98 right away...
|
2013-05-07 00:26:35 +04:00
|
|
|
.on('preCenteringRibbon', function(evt, ribbon, image){
|
|
|
|
|
// NOTE: we do not need to worry about centering the ribbon
|
|
|
|
|
// here, just ball-park-load the correct batch...
|
2013-05-12 14:31:03 +04:00
|
|
|
|
2013-05-07 00:26:35 +04:00
|
|
|
// check if we are in the right range...
|
|
|
|
|
var gid = getImageGID(image)
|
|
|
|
|
var r = getRibbonIndex(ribbon)
|
2013-05-12 15:28:15 +04:00
|
|
|
var gr = DATA.ribbons[r]
|
2013-05-07 00:26:35 +04:00
|
|
|
var img_before = getImageBefore(image, ribbon)
|
|
|
|
|
var gid_before = getGIDBefore(gid, r)
|
|
|
|
|
|
2013-05-12 14:31:03 +04:00
|
|
|
// load the head of the images...
|
2013-05-12 15:28:15 +04:00
|
|
|
if(gid_before == null){
|
2013-05-12 14:31:03 +04:00
|
|
|
// NOTE: rolling to any number of positions greater than length
|
|
|
|
|
// of the ribbon will set the ribbon to its start/end
|
|
|
|
|
// depending on the sign...
|
|
|
|
|
rollImages(-gr.length, ribbon)
|
|
|
|
|
|
2013-05-12 15:28:15 +04:00
|
|
|
// load the tail...
|
|
|
|
|
// XXX for some reason this does not work (see XXX on top of the binding)
|
|
|
|
|
} else if(gid_before == gr[gr.length-1]){
|
|
|
|
|
rollImages(gr.length, ribbon)
|
|
|
|
|
|
2013-05-12 14:31:03 +04:00
|
|
|
// load a new set of images...
|
2013-05-12 15:28:15 +04:00
|
|
|
} else if(getImageGID(img_before) != gid_before){
|
2013-05-07 00:26:35 +04:00
|
|
|
var images = ribbon.find('.image')
|
2013-05-12 15:28:15 +04:00
|
|
|
//var cur = getImageGID(images.eq(Math.round(images.length/2)))
|
|
|
|
|
var cur = getImageGID(images.first())
|
|
|
|
|
// XXX this sometimes misses...
|
2013-05-07 00:26:35 +04:00
|
|
|
rollImages(gr.indexOf(gid_before) - gr.indexOf(cur), ribbon)
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
.on('centeringRibbon', function(evt, ribbon, image){
|
|
|
|
|
// check if we are in the right range...
|
|
|
|
|
var gid = getImageGID(image)
|
|
|
|
|
var r = getRibbonIndex(ribbon)
|
|
|
|
|
var img_before = getImageBefore(image, ribbon)
|
|
|
|
|
var gid_before = getGIDBefore(gid, r)
|
|
|
|
|
|
|
|
|
|
if(img_before.length == 0){
|
|
|
|
|
img_before = ribbon.find('.image').first()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var head = img_before.prevAll('.image')
|
|
|
|
|
var tail = img_before.nextAll('.image')
|
|
|
|
|
// NOTE: these are to be used as reference for loading/populating
|
|
|
|
|
// rolled images...
|
|
|
|
|
var first = head.first()
|
|
|
|
|
var last = head.first()
|
|
|
|
|
|
2013-05-12 14:31:03 +04:00
|
|
|
// get the frame size to load...
|
|
|
|
|
var screen_size = getScreenWidthInImages()
|
|
|
|
|
// NOTE: if this is greater than the number of images currently
|
|
|
|
|
// loaded, it might lead to odd effects...
|
|
|
|
|
// XXX need to load additional images and keep track of the
|
|
|
|
|
// loaded chunk size...
|
|
|
|
|
var frame_size = screen_size * LOAD_SCREENS
|
|
|
|
|
var threshold = screen_size * LOAD_THRESHOLD
|
|
|
|
|
|
|
|
|
|
// do the loading...
|
2013-05-07 00:26:35 +04:00
|
|
|
// XXX need to expand/contract the ribbon depending on zoom and speed...
|
|
|
|
|
// XXX use extendRibbon, to both roll and expand/contract...
|
2013-05-12 14:31:03 +04:00
|
|
|
if(tail.length < threshold){
|
|
|
|
|
var rolled = rollImages(frame_size, ribbon)
|
2013-05-07 00:26:35 +04:00
|
|
|
}
|
2013-05-12 14:31:03 +04:00
|
|
|
if(head.length < threshold){
|
|
|
|
|
var rolled = rollImages(-frame_size, ribbon)
|
2013-05-07 00:26:35 +04:00
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
.on('shiftedImage', function(evt, image, from, to){
|
|
|
|
|
from = getRibbonIndex(from)
|
|
|
|
|
var ribbon = to
|
|
|
|
|
to = getRibbonIndex(to)
|
|
|
|
|
|
|
|
|
|
var gid = getImageGID(image)
|
|
|
|
|
|
|
|
|
|
var index = DATA.ribbons[from].indexOf(gid)
|
|
|
|
|
var img = DATA.ribbons[from].splice(index, 1)
|
|
|
|
|
|
|
|
|
|
// XXX a bit ugly, revise...
|
|
|
|
|
index = ribbon.find('.image')
|
|
|
|
|
.index(ribbon.find('[gid='+JSON.stringify(gid)+']'))
|
|
|
|
|
DATA.ribbons[to].splice(index, 0, gid)
|
|
|
|
|
})
|
2013-05-12 15:28:15 +04:00
|
|
|
|
2013-05-07 00:26:35 +04:00
|
|
|
.on('createdRibbon', function(evt, index){
|
|
|
|
|
index = getRibbonIndex(index)
|
|
|
|
|
|
|
|
|
|
console.log('creating ribbon...')
|
|
|
|
|
DATA.ribbons.splice(index, 0, [])
|
|
|
|
|
})
|
|
|
|
|
.on('removedRibbon', function(evt, index){
|
|
|
|
|
console.log('removing ribbon...')
|
|
|
|
|
DATA.ribbons.splice(index, 1)
|
|
|
|
|
})
|
2013-05-12 15:28:15 +04:00
|
|
|
|
2013-05-07 00:26:35 +04:00
|
|
|
.on('requestedFirstImage', function(evt, ribbon){
|
|
|
|
|
var r = getRibbonIndex(ribbon)
|
|
|
|
|
var gr = DATA.ribbons[r]
|
|
|
|
|
rollImages(-gr.length, ribbon)
|
|
|
|
|
})
|
|
|
|
|
.on('requestedLastImage', function(evt, ribbon){
|
|
|
|
|
var r = getRibbonIndex(ribbon)
|
2013-05-06 02:46:48 +04:00
|
|
|
var gr = DATA.ribbons[r]
|
2013-05-07 00:26:35 +04:00
|
|
|
rollImages(gr.length, ribbon)
|
|
|
|
|
})
|
2013-05-12 15:28:15 +04:00
|
|
|
|
2013-05-12 14:31:03 +04:00
|
|
|
// XXX do we need to make this less global?
|
|
|
|
|
.on('fittingImages', function(evt, n){
|
|
|
|
|
updateImages()
|
|
|
|
|
})
|
2013-05-07 00:26:35 +04:00
|
|
|
}
|
2013-05-05 19:53:06 +04:00
|
|
|
|
2013-05-02 23:22:43 +04:00
|
|
|
|
2013-05-03 17:08:59 +04:00
|
|
|
|
2013-05-02 23:22:43 +04:00
|
|
|
// XXX stub...
|
|
|
|
|
centerImage(focusImage($('.image').first()), 'css')
|
2013-05-12 14:31:03 +04:00
|
|
|
updateImages()
|
2013-05-02 23:22:43 +04:00
|
|
|
|
2013-04-26 05:30:56 +04:00
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
</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">
|
2013-04-30 00:54:32 +04:00
|
|
|
|
2013-04-26 05:30:56 +04:00
|
|
|
<div class="ribbon-set"></div>
|
2013-04-30 00:54:32 +04:00
|
|
|
|
|
|
|
|
|
2013-04-30 01:34:26 +04:00
|
|
|
<!-- XXX should these be here??? -->
|
2013-04-30 00:54:32 +04:00
|
|
|
<div class="up-indicator"></div>
|
|
|
|
|
<div class="down-indicator"></div>
|
2013-05-03 19:24:06 +04:00
|
|
|
<div class="start-indicator"></div>
|
|
|
|
|
<div class="end-indicator"></div>
|
2013-04-26 05:30:56 +04:00
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<!-- vim:set ts=4 sw=4 spell : -->
|
|
|
|
|
</body>
|
|
|
|
|
</html>
|