mirror of
				https://github.com/flynx/ImageGrid.git
				synced 2025-10-31 19:30:07 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			421 lines
		
	
	
		
			8.4 KiB
		
	
	
	
		
			HTML
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			421 lines
		
	
	
		
			8.4 KiB
		
	
	
	
		
			HTML
		
	
	
		
			Executable File
		
	
	
	
	
| <html>
 | |
| <head>
 | |
| <title>ImageGrid.Viewer</title>
 | |
| 
 | |
| 
 | |
| <style>
 | |
| 
 | |
| /* 
 | |
| * XXX move the CSS to a separate file...
 | |
| * XXX split-off styling/coloring from layout...
 | |
| */
 | |
| 
 | |
| .viewer {
 | |
| 	position: relative;
 | |
| 	width: 800px;
 | |
| 	height: 600px;
 | |
| 	overflow: hidden;
 | |
| 
 | |
| 	border: solid blue 1px;
 | |
| }
 | |
| 
 | |
| 
 | |
| .ribbon-set {
 | |
| 	position: absolute;
 | |
| }
 | |
| .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;
 | |
| 
 | |
| 	background: black;
 | |
| 	box-sizing: border-box;
 | |
| 	border: solid gray 1px;
 | |
| 	color: white;
 | |
| }
 | |
| .current.image {
 | |
| 	background: red;
 | |
| }
 | |
| 
 | |
| /* dot mark... */
 | |
| .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;
 | |
| }
 | |
| 
 | |
| /* 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);
 | |
| }
 | |
| */
 | |
| 
 | |
| 
 | |
| .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;
 | |
| }
 | |
| 
 | |
| 
 | |
| .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;
 | |
| }
 | |
| 
 | |
| 
 | |
| </style>
 | |
| 
 | |
| 
 | |
| 
 | |
| <script src="jquery.js"></script>
 | |
| 
 | |
| <script src="lib/jli.js"></script>
 | |
| <script src="lib/keyboard.js"></script>
 | |
| 
 | |
| <script src="ImageGrid.js"></script>
 | |
| <script src="keybindings3.js"></script>
 | |
| 
 | |
| <script>
 | |
| 
 | |
| // 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))
 | |
| 	//var rr = r.clone()
 | |
| 	//var rrr = r.clone()
 | |
| 
 | |
| 	// XXX use something like loadImages()...
 | |
| 	$('.ribbon-set')
 | |
| 		.append(r)
 | |
| 		//.append(rr)
 | |
| 		//.append(rrr)
 | |
| 
 | |
| 	// NOTE: this is global so as to not to add any extra complexity to 
 | |
| 	//		the internal workings...
 | |
| 	$('.viewer')
 | |
| 		.click(clickHandler)
 | |
| 
 | |
| 	$(document)
 | |
| 		.keydown(makeKeyboardHandler(
 | |
| 			KEYBOARD_CONFIG,
 | |
| 			function(k){console.log(k)}))
 | |
| 
 | |
| 
 | |
| 
 | |
| 	// dynamic loading...
 | |
| 	DYNAMIC_LOADING = true
 | |
| 
 | |
| 	if(DYNAMIC_LOADING){
 | |
| 		// XXX move to a setup function in the lib...
 | |
| 		// XXX update this depending on zoom and navigation speed...
 | |
| 		var LOADER_THRESHOLD = 2
 | |
| 		// XXX update this depending on zoom and navigation speed...
 | |
| 		var LOADER_CHUNK = LOADER_THRESHOLD * 2
 | |
| 		$('.viewer')
 | |
| 			.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...
 | |
| 				// 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)
 | |
| 
 | |
| 				// need to load a new set of images...
 | |
| 				if((img_before.length == 0 && gid_before != null) 
 | |
| 						|| (getImageGID(img_before) 
 | |
| 								&& getImageGID(img_before) != gid_before)){
 | |
| 					// get the distance...
 | |
| 					var images = ribbon.find('.image')
 | |
| 					var cur = getImageGID(images.eq(Math.round(images.length/2)))
 | |
| 					var gr = DATA.ribbons[r]
 | |
| 					//console.log('>>>', gr.indexOf(gid_before) - gr.indexOf(cur))
 | |
| 					rollImages(gr.indexOf(gid_before) - gr.indexOf(cur), ribbon)
 | |
| 				}
 | |
| 			})
 | |
| 			// XXX it takes several steps for adjacent ribbons to catch up...
 | |
| 			.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()
 | |
| 
 | |
| 				// XXX need to expand/contract the ribbon depending on zoom and speed...
 | |
| 				// XXX use extendRibbon, to both roll and expand/contract...
 | |
| 				if(tail.length < LOADER_THRESHOLD){
 | |
| 					var rolled = rollImages(LOADER_CHUNK, ribbon)
 | |
| 				}
 | |
| 				if(head.length < LOADER_THRESHOLD){
 | |
| 					var rolled = rollImages(-LOADER_CHUNK, ribbon)
 | |
| 				}
 | |
| 			})
 | |
| 			.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)
 | |
| 			})
 | |
| 			.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)
 | |
| 			})
 | |
| 			.on('requestedFirstImage', function(evt, ribbon){
 | |
| 				var r = getRibbonIndex(ribbon)
 | |
| 
 | |
| 				// XXX this result in an infinite loop somewhere...
 | |
| 				//var target = DATA.ribbons[r][0]
 | |
| 				//
 | |
| 				//loadImages(target, 30, ribbon)	
 | |
| 
 | |
| 				var gr = DATA.ribbons[r]
 | |
| 				rollImages(-gr.length, ribbon)
 | |
| 			})
 | |
| 			.on('requestedLastImage', function(evt, ribbon){
 | |
| 				var r = getRibbonIndex(ribbon)
 | |
| 
 | |
| 				// XXX this result in an infinite loop somewhere...
 | |
| 				//var target = DATA.ribbons[r][DATA.ribbons[r].length-1]
 | |
| 				//
 | |
| 				//loadImages(target, 30, ribbon)	
 | |
| 
 | |
| 				var gr = DATA.ribbons[r]
 | |
| 				rollImages(gr.length, ribbon)
 | |
| 			})
 | |
| 	}
 | |
| 
 | |
| 
 | |
| 
 | |
| 	// XXX stub...
 | |
| 	centerImage(focusImage($('.image').first()), 'css')
 | |
| 
 | |
| 
 | |
| })
 | |
| 
 | |
| 
 | |
| </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>
 | |
| 
 | |
| 
 | |
| <!-- vim:set ts=4 sw=4 spell : -->
 | |
| </body>
 | |
| </html>
 |