mirror of
https://github.com/flynx/ImageGrid.git
synced 2025-10-28 18:00:09 +00:00
258 lines
4.4 KiB
HTML
Executable File
258 lines
4.4 KiB
HTML
Executable File
<!DOCTYPE html>
|
|
<html>
|
|
<style>
|
|
|
|
.ribbon {
|
|
position: relative;
|
|
display: block;
|
|
float: left;
|
|
clear: left;
|
|
|
|
white-space: nowrap;
|
|
overflow: visible;
|
|
|
|
margin: 5px 0px;
|
|
|
|
width: auto;
|
|
}
|
|
.base.ribbon {
|
|
border-bottom: solid 5px red;
|
|
}
|
|
|
|
.mark,
|
|
.image {
|
|
position: relative;
|
|
display: inline-block;
|
|
|
|
width: 100px;
|
|
height: 100px;
|
|
|
|
outline: solid 1px blue;
|
|
background: silver;
|
|
|
|
vertical-align: middle;
|
|
}
|
|
.image:after {
|
|
content: attr(gid);
|
|
}
|
|
.current.image {
|
|
background: gray;
|
|
}
|
|
|
|
.mark {
|
|
margin-left: -100px;
|
|
background: none;
|
|
|
|
pointer-events: none;
|
|
}
|
|
.mark:after {
|
|
position: absolute;
|
|
content: "";
|
|
top: 0;
|
|
right: 0;
|
|
|
|
width: 0;
|
|
height: 0;
|
|
border: solid 10px red;
|
|
border-bottom-color: transparent;
|
|
border-left-color: transparent;
|
|
|
|
pointer-events: auto;
|
|
}
|
|
|
|
|
|
</style>
|
|
|
|
<script src="../ext-lib/jquery.js"></script>
|
|
<script src="../ext-lib/jquery-ui.js"></script>
|
|
|
|
<!-- preact.js -->
|
|
<script src="../node_modules/preact/dist/preact.min.js"></script>
|
|
|
|
|
|
<script src="../lib/jli.js"></script>
|
|
|
|
<script>
|
|
|
|
var h = preact.h
|
|
|
|
|
|
var stub_data = {
|
|
ribbon_order: ['ra', 'rb', 'rc'],
|
|
ribbons: {
|
|
ra: [].slice.call('abcde'),
|
|
rb: [].slice.call('fghijklm'),
|
|
rc: [].slice.call('opqrstuvwxyz'),
|
|
},
|
|
order: [].slice.call('abcdefghijklmopqrstuvwxyz'),
|
|
|
|
tags: {
|
|
selected: [].slice.call('ahdtu'),
|
|
b: [].slice.call('adxz'),
|
|
},
|
|
|
|
current: 'a',
|
|
base: 'rb',
|
|
}
|
|
|
|
|
|
// XXX needs vertical align...
|
|
class IGRibbonSet extends preact.Component {
|
|
render(props, state){
|
|
var data = props.data
|
|
var ribbons = data.ribbon_order.map(function(gid){
|
|
return h(IGRibbon, {
|
|
gid: gid,
|
|
current: data.current,
|
|
base: data.base,
|
|
data: data
|
|
}) })
|
|
var s = props.scale || 1
|
|
|
|
return h('div',
|
|
{
|
|
className: 'ribbon-set',
|
|
style: {
|
|
transform: 'scale('+ s +', '+ s +')',
|
|
},
|
|
}, [
|
|
h('div', {className: 'current-marker'}),
|
|
h('div', {className: 'ribbon-locator'}, ribbons),
|
|
])
|
|
}
|
|
}
|
|
|
|
// render:
|
|
// - ribbon
|
|
// - images
|
|
// - image marks
|
|
//
|
|
// XXX needs horizontal align...
|
|
class IGRibbon extends preact.Component {
|
|
render(props, state){
|
|
var data = props.data
|
|
var ribbon = props.gid
|
|
|
|
var images = data.ribbons[ribbon]
|
|
.map(function(gid){
|
|
var marks = data.tags.selected.indexOf(gid) >= 0 ?
|
|
h(IGImageMark, {
|
|
gid: gid,
|
|
type: 'selected',
|
|
data: data,
|
|
})
|
|
: []
|
|
return [
|
|
h(IGImage, {
|
|
gid: gid,
|
|
data: data,
|
|
})].concat(marks)
|
|
})
|
|
.reduce(function(a, b){ return a.concat(b) })
|
|
.filter(function(a){ return !!a })
|
|
|
|
var base = data.base == ribbon ? ['base'] : []
|
|
|
|
return h('div',
|
|
{
|
|
classList: ['ribbon'].concat(base).join(' '),
|
|
|
|
gid: props.gid,
|
|
style: {
|
|
// XXX offset...
|
|
},
|
|
}, images)
|
|
}
|
|
}
|
|
|
|
// render:
|
|
// - image
|
|
class IGImage extends preact.Component {
|
|
render(props, state){
|
|
var data = props.data
|
|
var gid = props.gid
|
|
|
|
return h('div',
|
|
{
|
|
classList: ['image']
|
|
.concat(data.current == gid ? ['current'] : [])
|
|
.join(' '),
|
|
gid: gid || '',
|
|
style: {
|
|
// XXX background-image...
|
|
},
|
|
|
|
// XXX STUB
|
|
onClick: function(evt){
|
|
// toggle tag...
|
|
if(data.current == gid){
|
|
var selected = data.tags.selected = data.tags.selected || []
|
|
selected.indexOf(gid) < 0 ?
|
|
selected.push(gid)
|
|
: selected.splice(selected.indexOf(gid), 1)
|
|
}
|
|
|
|
// set current...
|
|
data.current = gid
|
|
|
|
render()
|
|
},
|
|
})
|
|
}
|
|
}
|
|
|
|
// render:
|
|
// - image mark
|
|
class IGImageMark extends preact.Component {
|
|
render(props, state){
|
|
var gid = props.gid
|
|
var type = props.type
|
|
var data = props.data
|
|
|
|
return h('div',
|
|
{
|
|
classList: ['mark'].concat([type]).join(' '),
|
|
gid: gid,
|
|
|
|
// XXX STUB...
|
|
// ...and there is no way to add the mark back...
|
|
onClick: function(evt){
|
|
data.tags[type].splice(data.tags[type].indexOf(gid), 1)
|
|
|
|
render()
|
|
},
|
|
})
|
|
}
|
|
}
|
|
|
|
|
|
// XXX HACK...
|
|
var ribbon_set_dom
|
|
|
|
function render(data, images, scale){
|
|
//preact.render(ribbon_set, document.body)
|
|
ribbon_set_dom = preact.render(
|
|
h(IGRibbonSet, {
|
|
data: data || stub_data,
|
|
images: images || {},
|
|
scale: scale || 1,
|
|
}),
|
|
document.getElementById('viewer'),
|
|
ribbon_set_dom)
|
|
}
|
|
|
|
|
|
|
|
$(function(){ render() })
|
|
|
|
|
|
</script>
|
|
|
|
<body>
|
|
|
|
<div id="viewer"/>
|
|
|
|
</body>
|
|
</html>
|
|
<!-- vim:set ts=4 sw=4 : -->
|