mirror of
				https://github.com/flynx/ImageGrid.git
				synced 2025-10-31 03:10:07 +00:00 
			
		
		
		
	split gallery.html into separate blocks...
Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
		
							parent
							
								
									11f8be4a2a
								
							
						
					
					
						commit
						c9a9259d59
					
				
							
								
								
									
										47
									
								
								ui/TODO.otl
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										47
									
								
								ui/TODO.otl
									
									
									
									
									
										Executable file
									
								
							| @ -0,0 +1,47 @@ | ||||
| basic structure | ||||
| 	ribbons					DONE | ||||
| 	images					DONE | ||||
| 	indicators | ||||
| basic control elements | ||||
| 	touch zones / buttons | ||||
| 		next				DONE | ||||
| 		prev				DONE | ||||
| 		shift up			DONE | ||||
| 		shift down			DONE | ||||
| 		promote				DONE | ||||
| 		demote				DONE | ||||
| 		zoom in				~		need real zooming... | ||||
| 		zoom out			~		need real zooming... | ||||
| 		toggle single image	DONE | ||||
| image sorting | ||||
| 	will affect: | ||||
| 		promote | ||||
| 		demote | ||||
| 		shift up | ||||
| 		shift down | ||||
| 		ribbon merging | ||||
| add promote/demote events (to attach structure editors)... | ||||
| add real images... | ||||
| make all the code relative to the current selection (multiple instances on a page support) | ||||
| make this into a jquery plugin... | ||||
| add dynamic loading and unloading for very large sets... | ||||
| gesture support... | ||||
| add basic actions: | ||||
| 	rotate left | ||||
| 	rotate right | ||||
| 	... | ||||
| add info: | ||||
| 	number of images in ribbon | ||||
| 	position in ribbon | ||||
| 
 | ||||
| 
 | ||||
| first stage refactoring: | ||||
| 	merge almost identical functions... | ||||
| 
 | ||||
| multiple groups to promote/demote | ||||
| 	ways to go: | ||||
| 		promote/demote and tag | ||||
| 
 | ||||
| ISSUES: | ||||
| 	jumping on focus up/down... | ||||
| 	demoting a first element (a ribbon is created) positions the field incorrectly (see demoteImage() for details)... | ||||
							
								
								
									
										356
									
								
								ui/gallery-prototype.js
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										356
									
								
								ui/gallery-prototype.js
									
									
									
									
									
										Executable file
									
								
							| @ -0,0 +1,356 @@ | ||||
| $(document).ready(function() { | ||||
| 	// current state...
 | ||||
| 	if($('.current-ribbon').length == 0){ | ||||
| 		$('.ribbon').first().addClass('current-ribbon') | ||||
| 	} | ||||
| 	if($('.current-image').length == 0){ | ||||
| 		$('.current-ribbon').children('.image').first().addClass('current-image') | ||||
| 	} | ||||
| 
 | ||||
| 	// setup event handlers...
 | ||||
| 	$(document) | ||||
| 		.keydown(handleKeys) | ||||
| 	$('.viewer') | ||||
| 		// XXX does not work on android... (might need to add tap event handling)
 | ||||
| 		.gestures({eventHandler: handleGestures}) | ||||
| 		// XXX this is flaky and breaks some of my code...
 | ||||
| 		/*.wipetouch({ | ||||
| 			wipeLeft: nextImage, | ||||
| 			wipeRight: prevImage, | ||||
| 			wipeUp: demoteImage, | ||||
| 			wipeDown: promoteImage, | ||||
| 
 | ||||
| 			tapToClick: true | ||||
| 		})*/ | ||||
| 		/* XXX jquery.mobile handlers... (with this I'm getting way too much bling) | ||||
| 		.bind('swipeleft', function(e){ | ||||
| 			nextImage() | ||||
| 			e.preventDefault() | ||||
| 			return false | ||||
| 		}) | ||||
| 		.bind('swiperight', function(e){ | ||||
| 			prevImage() | ||||
| 			e.preventDefault() | ||||
| 			return false | ||||
| 		}) | ||||
| 		*/ | ||||
| 	$(".image").click(handleClick) | ||||
| 
 | ||||
| 	// control elements...
 | ||||
| 	$('.next-image').click(nextImage) | ||||
| 	$('.prev-image').click(prevImage) | ||||
| 	$('.demote').click(demoteImage) | ||||
| 	$('.promote').click(promoteImage) | ||||
| 	$('.toggle-wide').click(toggleWideView) | ||||
| 	$('.toggle-single').click(toggleRibbonView) | ||||
| 
 | ||||
| 	// load images...
 | ||||
| 	// XXX not allowed...
 | ||||
| 	//$.getJSON('images.js', loadImages})
 | ||||
| 	// XXX STUB
 | ||||
| 	loadImages(image_list) | ||||
| 
 | ||||
| 	// set the default position and init...
 | ||||
| 	$('.current-image').click() | ||||
| 
 | ||||
| }); | ||||
| 
 | ||||
| function loadImages(json){ | ||||
| 	var images = json.images | ||||
| 	var ribbon = $('.ribbon').last() | ||||
| 
 | ||||
| 	$('.image').remove() | ||||
| 
 | ||||
| 	for(var i = 0; i < images.length; i++){ | ||||
| 		$('<div class="image"></div>') | ||||
| 			.css({ 'background-image': 'url('+images[i]+')' }) | ||||
| 			.click(handleClick) | ||||
| 			.appendTo(ribbon) | ||||
| 	} | ||||
| 	ribbon.children().first().click() | ||||
| } | ||||
| 
 | ||||
| // XXX jquery.gestures handler...
 | ||||
| function handleGestures(e){ | ||||
| 	switch (e){ | ||||
| 		case 'N': | ||||
| 			demoteImage() | ||||
| 			break | ||||
| 		case 'S': | ||||
| 			promoteImage() | ||||
| 			break | ||||
| 		case 'E': | ||||
| 			prevImage() | ||||
| 			break | ||||
| 		case 'W': | ||||
| 			nextImage() | ||||
| 			break | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| function handleClick(e) { | ||||
| 
 | ||||
| 	var cur = $(this) | ||||
| 
 | ||||
| 	// switch classes...
 | ||||
| 	cur.parents().siblings().children(".image").removeClass("current-image") | ||||
| 	cur.siblings(".image").removeClass("current-image") | ||||
| 
 | ||||
| 	cur.siblings().children(".image").removeClass("current-image") | ||||
| 	cur.parents().siblings(".ribbon").removeClass("current-ribbon") | ||||
| 
 | ||||
| 	cur.addClass("current-image") | ||||
| 	cur.parents(".ribbon").addClass("current-ribbon") | ||||
| 
 | ||||
| 
 | ||||
| 	var container = cur.parents('.container') | ||||
| 	var field = cur.parents(".field") | ||||
| 
 | ||||
| 	var image_offset = cur.offset() | ||||
| 	var field_offset = field.offset() | ||||
| 
 | ||||
| 	// center the current image...
 | ||||
| 	field.css({ | ||||
| 		left: field_offset.left - image_offset.left + (container.innerWidth() - cur.innerWidth())/2,  | ||||
| 		top: field_offset.top - image_offset.top + (container.innerHeight() - cur.innerHeight())/2  | ||||
| 	}) | ||||
| 
 | ||||
| 
 | ||||
| 	// XXX do I need this???
 | ||||
| 	e.preventDefault(); | ||||
| } | ||||
| 
 | ||||
| var keys = { | ||||
| 	toggleHelpKeys: [72], | ||||
| 	toggleRibbonView: [32], | ||||
| 	closeKeys: [27, 88, 67], | ||||
| 
 | ||||
| 	firstKeys: [36], | ||||
| 	lastKeys: [35], | ||||
| 	previousKeys: [37, 80], | ||||
| 	nextKeys: [39, 78], | ||||
| 	promoteKeys: [40], | ||||
| 	// XXX add del (46) to demote...
 | ||||
| 	demoteKeys: [38], | ||||
| 
 | ||||
| 	ignoreKeys: [16, 17, 18], | ||||
| 
 | ||||
| 	helpShowOnUnknownKey: true | ||||
| } | ||||
| 
 | ||||
| function handleKeys(event){ | ||||
| 	var code = event.keyCode, fn = $.inArray; | ||||
| 	var _ = (fn(code, keys.closeKeys) >= 0) ? function(){}() | ||||
| 		: (fn(code, keys.firstKeys) >= 0) ? firstImage() | ||||
| 		: (fn(code, keys.nextKeys) >= 0) ? nextImage() | ||||
| 		: (fn(code, keys.previousKeys) >= 0) ? prevImage() | ||||
| 		: (fn(code, keys.lastKeys) >= 0) ? lastImage() | ||||
| 		: (fn(code, keys.promoteKeys) >= 0) ? function(){ | ||||
| 			if(event.shiftKey){ | ||||
| 				if(event.ctrlKey){ | ||||
| 					createRibbonBelow() | ||||
| 				} | ||||
| 				promoteImage() | ||||
| 			} else { | ||||
| 				focusBelowRibbon() | ||||
| 			} | ||||
| 		}() | ||||
| 		: (fn(code, keys.demoteKeys) >= 0) ? function(){ | ||||
| 			if(event.shiftKey){ | ||||
| 				if(event.ctrlKey){ | ||||
| 					createRibbonAbove() | ||||
| 				} | ||||
| 				demoteImage() | ||||
| 			} else { | ||||
| 				focusAboveRibbon() | ||||
| 			} | ||||
| 		}() | ||||
| 		: (fn(code, keys.toggleRibbonView) >= 0) ? toggleRibbonView() | ||||
| 		: (fn(code, keys.ignoreKeys) >= 0) ? false | ||||
| 		// XXX
 | ||||
| 		: (keys.helpShowOnUnknownKey) ? function(){alert(code)}() | ||||
| 		: false; | ||||
| 	return false; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| // modes...
 | ||||
| function showRibbon(){ | ||||
| 	$('.single-image-mode').removeClass('single-image-mode') | ||||
| } | ||||
| function showSingle(){ | ||||
| 	$('.viewer').not('.single-image-mode').addClass('single-image-mode') | ||||
| } | ||||
| function toggleRibbonView(){ | ||||
| 	if($('.single-image-mode').length > 0){ | ||||
| 		showRibbon() | ||||
| 	} else { | ||||
| 		showSingle() | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // XXX need to reposition the whole thing correctly...
 | ||||
| function toggleWideView(){ | ||||
| 	if($('.wide-view-mode').length > 0){ | ||||
| 		$('.wide-view-mode') | ||||
| 			.removeClass('wide-view-mode') | ||||
| 			.one("webkitTransitionEnd oTransitionEnd msTransitionEnd transitionend", function(){ | ||||
| 				$('.current-image').click() | ||||
| 				return true | ||||
| 			}); | ||||
| 		 | ||||
| 	} else { | ||||
| 		showRibbon() | ||||
| 		//$('.container')
 | ||||
| 		$('.viewer') | ||||
| 			.not('.wide-view-mode') | ||||
| 				.addClass('wide-view-mode') | ||||
| 				.one("webkitTransitionEnd oTransitionEnd msTransitionEnd transitionend", function(){ | ||||
| 					$('.current-image').click() | ||||
| 					return true | ||||
| 				}); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // basic navigation...
 | ||||
| function firstImage(){ | ||||
| 	$('.current-ribbon').children('.image').first().click() | ||||
| } | ||||
| 
 | ||||
| function prevImage(){ | ||||
| 	$('.current-image').prev('.image').click() | ||||
| } | ||||
| 
 | ||||
| function nextImage(){ | ||||
| 	$('.current-image').next('.image').click() | ||||
| } | ||||
| 
 | ||||
| function lastImage(){ | ||||
| 	$('.current-ribbon').children('.image').last().click() | ||||
| } | ||||
| 
 | ||||
| // XXX select appropriate image...
 | ||||
| function focusAboveRibbon(){ | ||||
| 	$('.current-ribbon').prev('.ribbon').children('.image').first().click() | ||||
| } | ||||
| 
 | ||||
| // XXX select appropriate image...
 | ||||
| function focusBelowRibbon(){ | ||||
| 	$('.current-ribbon').next('.ribbon').children('.image').first().click() | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| // create ribbon above/below helpers...
 | ||||
| // XXX NOTE: this will shift the content downwards...
 | ||||
| function createRibbonAbove(){ | ||||
| 	var res = $('<div class="new-ribbon"></div>') | ||||
| 		.insertBefore('.current-ribbon') | ||||
| 		// HACK: without this, the class change below will not animate...
 | ||||
| 		.show() | ||||
| 		.addClass('ribbon') | ||||
| 		.removeClass('new-ribbon') | ||||
| 	// XXX find a better way to do this...
 | ||||
| 	$('.field').css({ | ||||
| 		top: $('.field').position().top - $('.current-ribbon').outerHeight() | ||||
| 	}) | ||||
| 	return res | ||||
| } | ||||
| 
 | ||||
| function createRibbonBelow(){ | ||||
| 	return $('<div class="new-ribbon"></div>') | ||||
| 		.insertAfter('.current-ribbon') | ||||
| 		// HACK: without this, the class change below will not animate...
 | ||||
| 		.show() | ||||
| 		.addClass('ribbon') | ||||
| 		.removeClass('new-ribbon') | ||||
| } | ||||
| 
 | ||||
| // Modifiers...
 | ||||
| 
 | ||||
| // XXX sort elements correctly...
 | ||||
| function mergeRibbonsUp(){ | ||||
| 	$('.current-ribbon') | ||||
| 		.prev('.ribbon') | ||||
| 			.children() | ||||
| 				.detach() | ||||
| 				.insertAfter('.current-image') | ||||
| 	$('.current-ribbon') | ||||
| 		.prev('.ribbon') | ||||
| 			.slideUp(function(){ | ||||
| 				$(this).remove() | ||||
| 				$('.current-image').click() | ||||
| 			}) | ||||
| } | ||||
| 
 | ||||
| // XXX sort elements correctly...
 | ||||
| function mergeRibbonsDown(){ | ||||
| 	$('.current-ribbon') | ||||
| 		.next('.ribbon') | ||||
| 			.children() | ||||
| 				.detach() | ||||
| 				.insertAfter('.current-image') | ||||
| 	$('.current-ribbon') | ||||
| 		.next('.ribbon') | ||||
| 			.slideUp(function(){ | ||||
| 				$(this).remove() | ||||
| 				$('.current-image').click() | ||||
| 			}) | ||||
| } | ||||
| 
 | ||||
| // XXX sort elements correctly...
 | ||||
| // XXX do animations...
 | ||||
| function promoteImage(){ | ||||
| 	if($('.current-ribbon').next('.ribbon').length == 0){ | ||||
| 		createRibbonBelow() | ||||
| 	} | ||||
| 	// XXX sort elements correctly...
 | ||||
| 	if($('.current-ribbon').children('.image').length == 1){ | ||||
| 		// XXX this adds image to the head while the below portion adds it to the tail...
 | ||||
| 		mergeRibbonsDown() | ||||
| 	} else { | ||||
| 		img = $('.current-image') | ||||
| 		if(img.next('.image').length == 0){ | ||||
| 			prevImage() | ||||
| 		} else { | ||||
| 			nextImage() | ||||
| 		} | ||||
| 		img | ||||
| 			.detach() | ||||
| 			.appendTo($('.current-ribbon').next('.ribbon')) | ||||
| 	} | ||||
| 	$('.current-image').click() | ||||
| } | ||||
| 
 | ||||
| // XXX sort elements correctly...
 | ||||
| // XXX do animations...
 | ||||
| // XXX BUG: when demoting first image (new ribbon created) it gets focused...
 | ||||
| //		REASON: .click() gets called in several places BEFORE the animation is done...
 | ||||
| //		NOTE: this bog does not affect promoteImage -- adding a lower element does not affect current positioning...
 | ||||
| function demoteImage(){ | ||||
| 	if($('.current-ribbon').prev('.ribbon').length == 0){ | ||||
| 		var new_ribbon = createRibbonAbove() | ||||
| 	} | ||||
| 	// XXX sort elements correctly...
 | ||||
| 	if($('.current-ribbon').children('.image').length == 1){ | ||||
| 		// XXX this adds image to the head while the below portion adds it to the tail...
 | ||||
| 		mergeRibbonsUp() | ||||
| 	} else { | ||||
| 		img = $('.current-image') | ||||
| 		if(img.next('.image').length == 0){ | ||||
| 			// XXX in case when we've just created an empty ribbon, the click in this fires BEFORE it is fully expanded...
 | ||||
| 			prevImage() | ||||
| 		} else { | ||||
| 			// XXX in case when we've just created an empty ribbon, the click in this fires BEFORE it is fully expanded...
 | ||||
| 			nextImage() | ||||
| 		} | ||||
| 		img | ||||
| 			.detach() | ||||
| 			.appendTo($('.current-ribbon').prev('.ribbon')) | ||||
| 	} | ||||
| 	// XXX in case when we've just created an empty ribbon, the click in this fires BEFORE it is fully expanded...
 | ||||
| 	$('.current-image').click() | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| // vim:set ts=4 sw=4 nowrap :
 | ||||
							
								
								
									
										199
									
								
								ui/gallery.css
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							
							
						
						
									
										199
									
								
								ui/gallery.css
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							| @ -0,0 +1,199 @@ | ||||
| .image { | ||||
| 	position: relative; | ||||
| 
 | ||||
| 	width: 350px; | ||||
| 	height: 350px; | ||||
| 
 | ||||
| 	display: inline-block; | ||||
| 	background: no-repeat 50% black; | ||||
| 	background-size: contain; | ||||
| 
 | ||||
| 	opacity: 0.3; | ||||
| 
 | ||||
| 	-webkit-transition: all 0.5s ease; | ||||
| 	-moz-transition: all 0.5s ease; | ||||
| 	-o-transition: all 0.5s ease; | ||||
| 	-ms-transition: all 0.5s ease;	 | ||||
| 	transition: all 0.5s ease; | ||||
| 
 | ||||
| 	cursor: hand; | ||||
| } | ||||
| 
 | ||||
| .mock-image { | ||||
| 	background: blue; | ||||
| } | ||||
| 
 | ||||
| .demo-buttons { | ||||
| 	margin: 15px | ||||
| 	border: groove 2px; | ||||
| 	 | ||||
| 	opacity: 0.2; | ||||
| 
 | ||||
| 	-webkit-transition: all 0.5s ease; | ||||
| 	-moz-transition: all 0.5s ease; | ||||
| 	-o-transition: all 0.5s ease; | ||||
| 	-ms-transition: all 0.5s ease;	 | ||||
| 	transition: all 0.5s ease; | ||||
| } | ||||
| .demo-buttons:hover { | ||||
| 	opacity: 1; | ||||
| } | ||||
| 
 | ||||
| .viewer { | ||||
| 	width: 900px; | ||||
| 	height: 500px; | ||||
| 	border: solid blue 5px; | ||||
| 	margin: 20px;  | ||||
| } | ||||
| .controller { | ||||
| 	height: 500px; | ||||
| 	width: 50px; | ||||
| 	background: silver; | ||||
| 	float: left; | ||||
| 
 | ||||
| 	-webkit-transition: all 0.5s ease; | ||||
| 	-moz-transition: all 0.5s ease; | ||||
| 	-o-transition: all 0.5s ease; | ||||
| 	-ms-transition: all 0.5s ease;	 | ||||
| 	transition: all 0.5s ease; | ||||
| } | ||||
| .single-image-mode .controller { | ||||
| 	opacity: 0.2; | ||||
| } | ||||
| .promote, .next-image, .prev-image, .demote, .toggle-wide, .toggle-single { | ||||
| 	text-align: center; | ||||
| 	vertical-align: middle; | ||||
| 	width: 100%; | ||||
| 	height: 150px;  | ||||
| 	background: gray; | ||||
| 
 | ||||
|    -moz-user-select: none; | ||||
|    -webkit-user-select: none; | ||||
|    -o-user-select: none; | ||||
|    -ms-user-select: none; | ||||
|    user-select: none; | ||||
| } | ||||
| .next-image, .prev-image, .toggle-wide, .toggle-single { | ||||
| 	background: silver; | ||||
| } | ||||
| .toggle-wide, .toggle-single { | ||||
| 	height:50px | ||||
| } | ||||
| .promote { | ||||
| } | ||||
| .next-image { | ||||
| } | ||||
| .prev-image { | ||||
| } | ||||
| .demote { | ||||
| } | ||||
| .toggle-wide { | ||||
| } | ||||
| .toggle-single { | ||||
| } | ||||
| 
 | ||||
| .container { | ||||
| 	float: left; | ||||
| 	overflow: hidden; | ||||
| 	width: 800px; | ||||
| 	height: 500px; | ||||
| } | ||||
| 
 | ||||
| .field { | ||||
| 	position: relative; | ||||
| 	overflow: visible; | ||||
| 	top: 0px; | ||||
| 	left: -100px; | ||||
| 
 | ||||
| 	-webkit-transition: all 0.5s ease; | ||||
| 	-moz-transition: all 0.5s ease; | ||||
| 	-o-transition: all 0.5s ease; | ||||
| 	-ms-transition: all 0.5s ease;	 | ||||
| 	transition: all 0.5s ease; | ||||
| } | ||||
| 
 | ||||
| .ribbon { | ||||
| 	height: 360px; | ||||
| 	/* XXX make this expand dynamically */ | ||||
| 	width: 100000px; | ||||
| 	overflow: visible; | ||||
| 	padding-top: 2px; | ||||
| 	padding-bottom: 2px; | ||||
| 	text-align: center; | ||||
| 	opacity: 0.2; | ||||
| 
 | ||||
| 	-webkit-transition: all 0.5s ease; | ||||
| 	-moz-transition: all 0.5s ease; | ||||
| 	-o-transition: all 0.5s ease; | ||||
| 	-ms-transition: all 0.5s ease;	 | ||||
| 	transition: all 0.5s ease; | ||||
| 
 | ||||
| } | ||||
| .new-ribbon { | ||||
| 	height: 0px; | ||||
| 
 | ||||
| 	-webkit-transition: all 0.5s ease; | ||||
| 	-moz-transition: all 0.5s ease; | ||||
| 	-o-transition: all 0.5s ease; | ||||
| 	-ms-transition: all 0.5s ease;	 | ||||
| 	transition: all 0.5s ease; | ||||
| } | ||||
| 
 | ||||
| .current-image { | ||||
| 	opacity: 1.0; | ||||
| } | ||||
| 
 | ||||
| .current-ribbon { | ||||
| 	padding-top: 20px; | ||||
| 	padding-bottom: 20px; | ||||
| 
 | ||||
| 	opacity: 1.0; | ||||
| 
 | ||||
| 	-webkit-transition: all 0.5s ease; | ||||
| 	-moz-transition: all 0.5s ease; | ||||
| 	-o-transition: all 0.5s ease; | ||||
| 	-ms-transition: all 0.5s ease;	 | ||||
| 	transition: all 0.5s ease; | ||||
| } | ||||
| 
 | ||||
| .current-ribbon .image { | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /* single image theme (start everything with .single-image-mode)  | ||||
|  * | ||||
|  * XXX need to make this touch friendly... | ||||
|  */ | ||||
| .single-image-mode .image { | ||||
| 	opacity: 0.0; | ||||
| } | ||||
| 
 | ||||
| .single-image-mode .image:hover { | ||||
| 	opacity: 0.5; | ||||
| } | ||||
| 
 | ||||
| .single-image-mode .current-image:hover, .single-image-mode .current-image { | ||||
| 	opacity: 1.0; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /* wide view mode */ | ||||
| 
 | ||||
| /* XXX not yet working correctly... | ||||
| .wide-view-mode { | ||||
| 	transform: scale(0.2,0.2); | ||||
| 	-ms-transform: scale(0.2,0.2); | ||||
| 	-webkit-transform: scale(0.2,0.2); | ||||
| 	-o-transform: scale(0.2,0.2); | ||||
| 	-moz-transform: scale(0.2,0.2); | ||||
| } | ||||
| */ | ||||
| .wide-view-mode .image { | ||||
| 	width: 50px; | ||||
| 	height: 50px; | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| .wide-view-mode .ribbon { | ||||
| 	height: 60px; | ||||
| } | ||||
							
								
								
									
										619
									
								
								ui/gallery.html
									
									
									
									
									
								
							
							
						
						
									
										619
									
								
								ui/gallery.html
									
									
									
									
									
								
							| @ -1,635 +1,28 @@ | ||||
| 
 | ||||
| <!-- | ||||
| TODO: | ||||
| - basic structure | ||||
| 	ribbons					DONE | ||||
| 	images					DONE | ||||
| 	indicators | ||||
| - basic control elements | ||||
| 	touch zones / buttons | ||||
| 		next				DONE | ||||
| 		prev				DONE | ||||
| 		shift up			DONE | ||||
| 		shift down			DONE | ||||
| 		promote				DONE | ||||
| 		demote				DONE | ||||
| 		zoom in				~		need real zooming... | ||||
| 		zoom out			~		need real zooming... | ||||
| 		toggle single image	DONE | ||||
| - image sorting | ||||
| 	- will affect: | ||||
| 		- promote | ||||
| 		- demote | ||||
| 		- shift up | ||||
| 		- shift down | ||||
| 		- ribbon merging | ||||
| - add promote/demote events (to attach structure editors)... | ||||
| - add real images... | ||||
| - make all the code relative to the current selection (multiple instances on a page support) | ||||
| - make this into a jquery plugin... | ||||
| - add dynamic loading and unloading for very large sets... | ||||
| - gesture support... | ||||
| - add basic actions: | ||||
| 	- rotate left | ||||
| 	- rotate right | ||||
| 	- ... | ||||
| - add info: | ||||
| 	- number of images in ribbon | ||||
| 	- position in ribbon | ||||
| 
 | ||||
| 
 | ||||
| - first stage refactoring: | ||||
| 	- merge almost identical functions... | ||||
| 
 | ||||
| - multiple groups to promote/demote | ||||
| 	ways to go: | ||||
| 		- promote/demote and tag | ||||
| 
 | ||||
| ISSUES: | ||||
| 	- jumping on focus up/down... | ||||
| 	- demoting a first element (a ribbon is created) positions the field incorrectly (see demoteImage() for details)... | ||||
| --> | ||||
| 
 | ||||
| <link rel="stylesheet" href="gallery.css"> | ||||
| <script src="jquery.js"></script> | ||||
| 
 | ||||
| <!-- script src="jquery.wipetouch.js"></script--> | ||||
| 
 | ||||
| <!-- XXX this does not work on android... -->  | ||||
| <script src="jquery.gestures.js"></script> | ||||
| <!-- XXX need to figure out how to disable all the bling --> | ||||
| <!-- script src="jquery.mobile.js"></script--> | ||||
| 
 | ||||
| <!-- XXX STUB --> | ||||
| <script src="images.js"></script> | ||||
| <script src="gallery-prototype.js"></script> | ||||
| 
 | ||||
| <!--script src="gallery.js"></script--> | ||||
| 
 | ||||
| <!-- XXX need to figure out how to disable all the bling --> | ||||
| <!-- script src="jquery.mobile.js"></script--> | ||||
| <script> | ||||
| 
 | ||||
| $(document).ready(function() { | ||||
| 	// current state... | ||||
| 	if($('.current-ribbon').length == 0){ | ||||
| 		$('.ribbon').first().addClass('current-ribbon') | ||||
| 	} | ||||
| 	if($('.current-image').length == 0){ | ||||
| 		$('.current-ribbon').children('.image').first().addClass('current-image') | ||||
| 	} | ||||
| 
 | ||||
| 	// setup event handlers... | ||||
| 	$(document) | ||||
| 		.keydown(handleKeys) | ||||
| 	$('.viewer') | ||||
| 		// XXX this is flaky and breaks some of my code... | ||||
| 		/*.wipetouch({ | ||||
| 			wipeLeft: nextImage, | ||||
| 			wipeRight: prevImage, | ||||
| 			wipeUp: demoteImage, | ||||
| 			wipeDown: promoteImage, | ||||
| 
 | ||||
| 			tapToClick: true | ||||
| 		})*/ | ||||
| 		// XXX does not work on android... | ||||
| 		.gestures({eventHandler: handleGestures}) | ||||
| 		/* XXX jquery.mobile handlers... (with this I'm getting way too much bling) | ||||
| 		.bind('swipeleft', function(e){ | ||||
| 			nextImage() | ||||
| 			e.preventDefault() | ||||
| 			return false | ||||
| 		}) | ||||
| 		.bind('swiperight', function(e){ | ||||
| 			prevImage() | ||||
| 			e.preventDefault() | ||||
| 			return false | ||||
| 		}) | ||||
| 		*/ | ||||
| 	$(".image").click(handleClick) | ||||
| 
 | ||||
| 	// control elements... | ||||
| 	$('.next-image').click(nextImage) | ||||
| 	$('.prev-image').click(prevImage) | ||||
| 	$('.demote').click(demoteImage) | ||||
| 	$('.promote').click(promoteImage) | ||||
| 	$('.toggle-wide').click(toggleWideView) | ||||
| 	$('.toggle-single').click(toggleRibbonView) | ||||
| 
 | ||||
| 	// load images... | ||||
| 	// XXX not allowed... | ||||
| 	//$.getJSON('images.js', loadImages}) | ||||
| 	// XXX STUB | ||||
| 	loadImages(image_list) | ||||
| 
 | ||||
| 	// set the default position and init... | ||||
| 	$('.current-image').click() | ||||
| 
 | ||||
| }); | ||||
| 
 | ||||
| function loadImages(json){ | ||||
| 	var images = json.images | ||||
| 	var ribbon = $('.ribbon').last() | ||||
| 
 | ||||
| 	$('.image').remove() | ||||
| 
 | ||||
| 	for(var i = 0; i < images.length; i++){ | ||||
| 		$('<div class="image"></div>') | ||||
| 			.css({ | ||||
| 				'background-image': 'url('+images[i]+')' | ||||
| 			}) | ||||
| 			.click(handleClick) | ||||
| 			.appendTo(ribbon) | ||||
| 	} | ||||
| 	ribbon.children().first().click() | ||||
| } | ||||
| 
 | ||||
| // XXX jquery.gestures handler... | ||||
| function handleGestures(e){ | ||||
| 	switch (e){ | ||||
| 		case 'N': | ||||
| 			demoteImage() | ||||
| 			break | ||||
| 		case 'S': | ||||
| 			promoteImage() | ||||
| 			break | ||||
| 		case 'E': | ||||
| 			prevImage() | ||||
| 			break | ||||
| 		case 'W': | ||||
| 			nextImage() | ||||
| 			break | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| function handleClick(e) { | ||||
| 
 | ||||
| 	var cur = $(this) | ||||
| 
 | ||||
| 	// switch classes... | ||||
| 	cur.parents().siblings().children(".image").removeClass("current-image") | ||||
| 	cur.siblings(".image").removeClass("current-image") | ||||
| 
 | ||||
| 	cur.siblings().children(".image").removeClass("current-image") | ||||
| 	cur.parents().siblings(".ribbon").removeClass("current-ribbon") | ||||
| 
 | ||||
| 	cur.addClass("current-image") | ||||
| 	cur.parents(".ribbon").addClass("current-ribbon") | ||||
| 
 | ||||
| 
 | ||||
| 	var container = cur.parents('.container') | ||||
| 	var field = cur.parents(".field") | ||||
| 
 | ||||
| 	var image_offset = cur.offset() | ||||
| 	var field_offset = field.offset() | ||||
| 
 | ||||
| 	// center the current image... | ||||
| 	field.css({ | ||||
| 		left: field_offset.left - image_offset.left + (container.innerWidth() - cur.innerWidth())/2,  | ||||
| 		top: field_offset.top - image_offset.top + (container.innerHeight() - cur.innerHeight())/2  | ||||
| 	}) | ||||
| 
 | ||||
| 
 | ||||
| 	// XXX do I need this??? | ||||
| 	e.preventDefault(); | ||||
| } | ||||
| 
 | ||||
| var keys = { | ||||
| 	toggleHelpKeys: [72], | ||||
| 	toggleRibbonView: [32], | ||||
| 	closeKeys: [27, 88, 67], | ||||
| 
 | ||||
| 	firstKeys: [36], | ||||
| 	lastKeys: [35], | ||||
| 	previousKeys: [37, 80], | ||||
| 	nextKeys: [39, 78], | ||||
| 	promoteKeys: [40], | ||||
| 	// XXX add del (46) to demote... | ||||
| 	demoteKeys: [38], | ||||
| 
 | ||||
| 	ignoreKeys: [16, 17, 18], | ||||
| 
 | ||||
| 	helpShowOnUnknownKey: true | ||||
| } | ||||
| 
 | ||||
| function handleKeys(event){ | ||||
| 	var code = event.keyCode, fn = $.inArray; | ||||
| 	var _ = (fn(code, keys.closeKeys) >= 0) ? function(){}() | ||||
| 		: (fn(code, keys.firstKeys) >= 0) ? firstImage() | ||||
| 		: (fn(code, keys.nextKeys) >= 0) ? nextImage() | ||||
| 		: (fn(code, keys.previousKeys) >= 0) ? prevImage() | ||||
| 		: (fn(code, keys.lastKeys) >= 0) ? lastImage() | ||||
| 		: (fn(code, keys.promoteKeys) >= 0) ? function(){ | ||||
| 			if(event.shiftKey){ | ||||
| 				if(event.ctrlKey){ | ||||
| 					createRibbonBelow() | ||||
| 				} | ||||
| 				promoteImage() | ||||
| 			} else { | ||||
| 				focusBelowRibbon() | ||||
| 			} | ||||
| 		}() | ||||
| 		: (fn(code, keys.demoteKeys) >= 0) ? function(){ | ||||
| 			if(event.shiftKey){ | ||||
| 				if(event.ctrlKey){ | ||||
| 					createRibbonAbove() | ||||
| 				} | ||||
| 				demoteImage() | ||||
| 			} else { | ||||
| 				focusAboveRibbon() | ||||
| 			} | ||||
| 		}() | ||||
| 		: (fn(code, keys.toggleRibbonView) >= 0) ? toggleRibbonView() | ||||
| 		: (fn(code, keys.ignoreKeys) >= 0) ? false | ||||
| 		// XXX | ||||
| 		: (keys.helpShowOnUnknownKey) ? function(){alert(code)}() | ||||
| 		: false; | ||||
| 	return false; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| // modes... | ||||
| function showRibbon(){ | ||||
| 	$('.single-image-mode').removeClass('single-image-mode') | ||||
| } | ||||
| function showSingle(){ | ||||
| 	$('.viewer').not('.single-image-mode').addClass('single-image-mode') | ||||
| } | ||||
| function toggleRibbonView(){ | ||||
| 	if($('.single-image-mode').length > 0){ | ||||
| 		showRibbon() | ||||
| 	} else { | ||||
| 		showSingle() | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // XXX need to reposition the whole thing correctly... | ||||
| function toggleWideView(){ | ||||
| 	if($('.wide-view-mode').length > 0){ | ||||
| 		$('.wide-view-mode') | ||||
| 			.removeClass('wide-view-mode') | ||||
| 			.one("webkitTransitionEnd oTransitionEnd msTransitionEnd transitionend", function(){ | ||||
| 				$('.current-image').click() | ||||
| 				return true | ||||
| 			}); | ||||
| 		 | ||||
| 	} else { | ||||
| 		showRibbon() | ||||
| 		//$('.container') | ||||
| 		$('.viewer') | ||||
| 			.not('.wide-view-mode') | ||||
| 				.addClass('wide-view-mode') | ||||
| 				.one("webkitTransitionEnd oTransitionEnd msTransitionEnd transitionend", function(){ | ||||
| 					$('.current-image').click() | ||||
| 					return true | ||||
| 				}); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // basic navigation... | ||||
| function firstImage(){ | ||||
| 	$('.current-ribbon').children('.image').first().click() | ||||
| } | ||||
| 
 | ||||
| function prevImage(){ | ||||
| 	$('.current-image').prev('.image').click() | ||||
| } | ||||
| 
 | ||||
| function nextImage(){ | ||||
| 	$('.current-image').next('.image').click() | ||||
| } | ||||
| 
 | ||||
| function lastImage(){ | ||||
| 	$('.current-ribbon').children('.image').last().click() | ||||
| } | ||||
| 
 | ||||
| // XXX select appropriate image... | ||||
| function focusAboveRibbon(){ | ||||
| 	$('.current-ribbon').prev('.ribbon').children('.image').first().click() | ||||
| } | ||||
| 
 | ||||
| // XXX select appropriate image... | ||||
| function focusBelowRibbon(){ | ||||
| 	$('.current-ribbon').next('.ribbon').children('.image').first().click() | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| // create ribbon above/below helpers... | ||||
| // XXX NOTE: this will shift the content downwards... | ||||
| function createRibbonAbove(){ | ||||
| 	var res = $('<div class="new-ribbon"></div>') | ||||
| 		.insertBefore('.current-ribbon') | ||||
| 		// HACK: without this, the class change below will not animate... | ||||
| 		.show() | ||||
| 		.addClass('ribbon') | ||||
| 		.removeClass('new-ribbon') | ||||
| 	// XXX find a better way to do this... | ||||
| 	$('.field').css({ | ||||
| 		top: $('.field').position().top - $('.current-ribbon').outerHeight() | ||||
| 	}) | ||||
| 	return res | ||||
| } | ||||
| 
 | ||||
| function createRibbonBelow(){ | ||||
| 	return $('<div class="new-ribbon"></div>') | ||||
| 		.insertAfter('.current-ribbon') | ||||
| 		// HACK: without this, the class change below will not animate... | ||||
| 		.show() | ||||
| 		.addClass('ribbon') | ||||
| 		.removeClass('new-ribbon') | ||||
| } | ||||
| 
 | ||||
| // Modifiers... | ||||
| 
 | ||||
| // XXX sort elements correctly... | ||||
| function mergeRibbonsUp(){ | ||||
| 	$('.current-ribbon') | ||||
| 		.prev('.ribbon') | ||||
| 			.children() | ||||
| 				.detach() | ||||
| 				.insertAfter('.current-image') | ||||
| 	$('.current-ribbon') | ||||
| 		.prev('.ribbon') | ||||
| 			.slideUp(function(){ | ||||
| 				$(this).remove() | ||||
| 				$('.current-image').click() | ||||
| 			}) | ||||
| } | ||||
| 
 | ||||
| // XXX sort elements correctly... | ||||
| function mergeRibbonsDown(){ | ||||
| 	$('.current-ribbon') | ||||
| 		.next('.ribbon') | ||||
| 			.children() | ||||
| 				.detach() | ||||
| 				.insertAfter('.current-image') | ||||
| 	$('.current-ribbon') | ||||
| 		.next('.ribbon') | ||||
| 			.slideUp(function(){ | ||||
| 				$(this).remove() | ||||
| 				$('.current-image').click() | ||||
| 			}) | ||||
| } | ||||
| 
 | ||||
| // XXX sort elements correctly... | ||||
| // XXX do animations... | ||||
| function promoteImage(){ | ||||
| 	if($('.current-ribbon').next('.ribbon').length == 0){ | ||||
| 		createRibbonBelow() | ||||
| 	} | ||||
| 	// XXX sort elements correctly... | ||||
| 	if($('.current-ribbon').children('.image').length == 1){ | ||||
| 		// XXX this adds image to the head while the below portion adds it to the tail... | ||||
| 		mergeRibbonsDown() | ||||
| 	} else { | ||||
| 		img = $('.current-image') | ||||
| 		if(img.next('.image').length == 0){ | ||||
| 			prevImage() | ||||
| 		} else { | ||||
| 			nextImage() | ||||
| 		} | ||||
| 		img | ||||
| 			.detach() | ||||
| 			.appendTo($('.current-ribbon').next('.ribbon')) | ||||
| 	} | ||||
| 	$('.current-image').click() | ||||
| } | ||||
| 
 | ||||
| // XXX sort elements correctly... | ||||
| // XXX do animations... | ||||
| // XXX BUG: when demoting first image (new ribbon created) it gets focused... | ||||
| //		REASON: .click() gets called in several places BEFORE the animation is done... | ||||
| //		NOTE: this bog does not affect promoteImage -- adding a lower element does not affect current positioning... | ||||
| function demoteImage(){ | ||||
| 	if($('.current-ribbon').prev('.ribbon').length == 0){ | ||||
| 		var new_ribbon = createRibbonAbove() | ||||
| 	} | ||||
| 	// XXX sort elements correctly... | ||||
| 	if($('.current-ribbon').children('.image').length == 1){ | ||||
| 		// XXX this adds image to the head while the below portion adds it to the tail... | ||||
| 		mergeRibbonsUp() | ||||
| 	} else { | ||||
| 		img = $('.current-image') | ||||
| 		if(img.next('.image').length == 0){ | ||||
| 			// XXX in case when we've just created an empty ribbon, the click in this fires BEFORE it is fully expanded... | ||||
| 			prevImage() | ||||
| 		} else { | ||||
| 			// XXX in case when we've just created an empty ribbon, the click in this fires BEFORE it is fully expanded... | ||||
| 			nextImage() | ||||
| 		} | ||||
| 		img | ||||
| 			.detach() | ||||
| 			.appendTo($('.current-ribbon').prev('.ribbon')) | ||||
| 	} | ||||
| 	// XXX in case when we've just created an empty ribbon, the click in this fires BEFORE it is fully expanded... | ||||
| 	$('.current-image').click() | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| </script> | ||||
| 
 | ||||
| <style> | ||||
| 	.image { | ||||
| 		position: relative; | ||||
| 
 | ||||
| 		width: 350px; | ||||
| 		height: 350px; | ||||
| 
 | ||||
| 		display: inline-block; | ||||
| 		background: no-repeat 50% black; | ||||
| 		background-size: contain; | ||||
| 
 | ||||
| 		opacity: 0.3; | ||||
| 
 | ||||
| 		-webkit-transition: all 0.5s ease; | ||||
| 		-moz-transition: all 0.5s ease; | ||||
| 		-o-transition: all 0.5s ease; | ||||
| 		-ms-transition: all 0.5s ease;	 | ||||
| 		transition: all 0.5s ease; | ||||
| 
 | ||||
| 		cursor: hand; | ||||
| 	} | ||||
| 
 | ||||
| 	.mock-image { | ||||
| 		background: blue; | ||||
| 	} | ||||
| 
 | ||||
| 	.demo-buttons { | ||||
| 		margin: 15px | ||||
| 		border: groove 2px; | ||||
| 		 | ||||
| 		opacity: 0.2; | ||||
| 
 | ||||
| 		-webkit-transition: all 0.5s ease; | ||||
| 		-moz-transition: all 0.5s ease; | ||||
| 		-o-transition: all 0.5s ease; | ||||
| 		-ms-transition: all 0.5s ease;	 | ||||
| 		transition: all 0.5s ease; | ||||
| 	} | ||||
| 	.demo-buttons:hover { | ||||
| 		opacity: 1; | ||||
| 	} | ||||
| 
 | ||||
| 	.viewer { | ||||
| 		width: 900px; | ||||
| 		height: 500px; | ||||
| 		border: solid blue 5px; | ||||
| 		margin: 20px;  | ||||
| 	} | ||||
| 	.controller { | ||||
| 		height: 500px; | ||||
| 		width: 50px; | ||||
| 		background: silver; | ||||
| 		float: left; | ||||
| 
 | ||||
| 		-webkit-transition: all 0.5s ease; | ||||
| 		-moz-transition: all 0.5s ease; | ||||
| 		-o-transition: all 0.5s ease; | ||||
| 		-ms-transition: all 0.5s ease;	 | ||||
| 		transition: all 0.5s ease; | ||||
| 	} | ||||
| 	.single-image-mode .controller { | ||||
| 		opacity: 0.2; | ||||
| 	} | ||||
| 	.promote, .next-image, .prev-image, .demote, .toggle-wide, .toggle-single { | ||||
| 		text-align: center; | ||||
| 		vertical-align: middle; | ||||
| 		width: 100%; | ||||
| 		height: 150px;  | ||||
| 		background: gray; | ||||
| 
 | ||||
| 	   -moz-user-select: none; | ||||
| 	   -webkit-user-select: none; | ||||
| 	   -o-user-select: none; | ||||
| 	   -ms-user-select: none; | ||||
| 	   user-select: none; | ||||
| 	} | ||||
| 	.next-image, .prev-image, .toggle-wide, .toggle-single { | ||||
| 		background: silver; | ||||
| 	} | ||||
| 	.toggle-wide, .toggle-single { | ||||
| 		height:50px | ||||
| 	} | ||||
| 	.promote { | ||||
| 	} | ||||
| 	.next-image { | ||||
| 	} | ||||
| 	.prev-image { | ||||
| 	} | ||||
| 	.demote { | ||||
| 	} | ||||
| 	.toggle-wide { | ||||
| 	} | ||||
| 	.toggle-single { | ||||
| 	} | ||||
| 
 | ||||
| 	.container { | ||||
| 		float: left; | ||||
| 		overflow: hidden; | ||||
| 		width: 800px; | ||||
| 		height: 500px; | ||||
| 	} | ||||
| 
 | ||||
| 	.field { | ||||
| 		position: relative; | ||||
| 		overflow: visible; | ||||
| 		top: 0px; | ||||
| 		left: -100px; | ||||
| 
 | ||||
| 		-webkit-transition: all 0.5s ease; | ||||
| 		-moz-transition: all 0.5s ease; | ||||
| 		-o-transition: all 0.5s ease; | ||||
| 		-ms-transition: all 0.5s ease;	 | ||||
| 		transition: all 0.5s ease; | ||||
| 	} | ||||
| 
 | ||||
| 	.ribbon { | ||||
| 		height: 360px; | ||||
| 		/* XXX make this expand dynamically */ | ||||
| 		width: 100000px; | ||||
| 		overflow: visible; | ||||
| 		padding-top: 2px; | ||||
| 		padding-bottom: 2px; | ||||
| 		text-align: center; | ||||
| 		opacity: 0.2; | ||||
| 
 | ||||
| 		-webkit-transition: all 0.5s ease; | ||||
| 		-moz-transition: all 0.5s ease; | ||||
| 		-o-transition: all 0.5s ease; | ||||
| 		-ms-transition: all 0.5s ease;	 | ||||
| 		transition: all 0.5s ease; | ||||
| 
 | ||||
| 	} | ||||
| 	.new-ribbon { | ||||
| 		height: 0px; | ||||
| 
 | ||||
| 		-webkit-transition: all 0.5s ease; | ||||
| 		-moz-transition: all 0.5s ease; | ||||
| 		-o-transition: all 0.5s ease; | ||||
| 		-ms-transition: all 0.5s ease;	 | ||||
| 		transition: all 0.5s ease; | ||||
| 	} | ||||
| 
 | ||||
| 	.current-image { | ||||
| 		opacity: 1.0; | ||||
| 	} | ||||
| 
 | ||||
| 	.current-ribbon { | ||||
| 		padding-top: 20px; | ||||
| 		padding-bottom: 20px; | ||||
| 
 | ||||
| 		opacity: 1.0; | ||||
| 
 | ||||
| 		-webkit-transition: all 0.5s ease; | ||||
| 		-moz-transition: all 0.5s ease; | ||||
| 		-o-transition: all 0.5s ease; | ||||
| 		-ms-transition: all 0.5s ease;	 | ||||
| 		transition: all 0.5s ease; | ||||
| 	} | ||||
| 
 | ||||
| 	.current-ribbon .image { | ||||
| 	} | ||||
| 
 | ||||
| 
 | ||||
| 	/* single image theme (start everything with .single-image-mode)  | ||||
| 	 * | ||||
| 	 * XXX need to make this touch friendly... | ||||
| 	 */ | ||||
| 	.single-image-mode .image { | ||||
| 		opacity: 0.0; | ||||
| 	} | ||||
| 
 | ||||
| 	.single-image-mode .image:hover { | ||||
| 		opacity: 0.5; | ||||
| 	} | ||||
| 
 | ||||
| 	.single-image-mode .current-image:hover, .single-image-mode .current-image { | ||||
| 		opacity: 1.0; | ||||
| 	} | ||||
| 
 | ||||
| 
 | ||||
| 	/* wide view mode */ | ||||
| 
 | ||||
| 	/* XXX not yet working correctly... | ||||
| 	.wide-view-mode { | ||||
| 		transform: scale(0.2,0.2); | ||||
| 		-ms-transform: scale(0.2,0.2); | ||||
| 		-webkit-transform: scale(0.2,0.2); | ||||
| 		-o-transform: scale(0.2,0.2); | ||||
| 		-moz-transform: scale(0.2,0.2); | ||||
| 	} | ||||
| 	*/ | ||||
| 	.wide-view-mode .image { | ||||
| 		width: 50px; | ||||
| 		height: 50px; | ||||
| 
 | ||||
| 	} | ||||
| 
 | ||||
| 	.wide-view-mode .ribbon { | ||||
| 		height: 60px; | ||||
| 	} | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| </style> | ||||
| 
 | ||||
| 
 | ||||
| <div class="viewer"> | ||||
| 	<div class="controller"> | ||||
| 		<div class="demote">^</div> | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user