mirror of
				https://github.com/flynx/PortableMag.git
				synced 2025-10-30 19:40:12 +00:00 
			
		
		
		
	added modes and page scaling in different views...
Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
		
							parent
							
								
									8b89de93c8
								
							
						
					
					
						commit
						c9a34f74a6
					
				
							
								
								
									
										351
									
								
								index.html
									
									
									
									
									
								
							
							
						
						
									
										351
									
								
								index.html
									
									
									
									
									
								
							| @ -8,6 +8,7 @@ | |||||||
| 
 | 
 | ||||||
| /* this is needed only for live resize... */ | /* this is needed only for live resize... */ | ||||||
| var PAGES_VISIBLE = 1 | var PAGES_VISIBLE = 1 | ||||||
|  | var PAGES_IN_RIBBON = 6 | ||||||
| 
 | 
 | ||||||
| $(document).ready(function(){ | $(document).ready(function(){ | ||||||
| 	$(window).resize(function() { | 	$(window).resize(function() { | ||||||
| @ -19,17 +20,11 @@ $(document).ready(function(){ | |||||||
| 			swipeStatus: swipeUpdate, | 			swipeStatus: swipeUpdate, | ||||||
| 			// XXX change this to pinch... | 			// XXX change this to pinch... | ||||||
| 			swipeUp: function(){ | 			swipeUp: function(){ | ||||||
| 				PAGES_VISIBLE = 6 | 				togglePageView('off') | ||||||
| 				fitNPages(PAGES_VISIBLE) |  | ||||||
| 			}, | 			}, | ||||||
| 			// XXX change this to pinch... | 			// XXX change this to pinch... | ||||||
| 			swipeDown: function(){ | 			swipeDown: function(){ | ||||||
| 				PAGES_VISIBLE = 1 | 				togglePageView('on') | ||||||
| 				fitNPages(PAGES_VISIBLE) |  | ||||||
| 				// to prevent drag while zooming to affect |  | ||||||
| 				// the resulting position set it to current  |  | ||||||
| 				// page... |  | ||||||
| 				setCurrentPage() |  | ||||||
| 			}, | 			}, | ||||||
| 			click: function(evt, elem){ | 			click: function(evt, elem){ | ||||||
| 				if($(elem).hasClass('page')){ | 				if($(elem).hasClass('page')){ | ||||||
| @ -40,45 +35,74 @@ $(document).ready(function(){ | |||||||
| 		}) | 		}) | ||||||
| 
 | 
 | ||||||
| 	// XXX add splash screen... | 	// XXX add splash screen... | ||||||
|  | 	// XXX | ||||||
| 
 | 
 | ||||||
| 	fitNPages(PAGES_VISIBLE) | 	togglePageView('on') | ||||||
| 
 |  | ||||||
| }) | }) | ||||||
| 
 | 
 | ||||||
| function swipeUpdate(evt, phase, direction, distance){ |  | ||||||
| 	var pages = $('.page') |  | ||||||
| 	var cur = $('.current.page') |  | ||||||
| 	var n = pages.index(cur) |  | ||||||
| 	var scale = getElementScale($('.scaler')) |  | ||||||
| 	var mag = $('.magazine') |  | ||||||
| 
 | 
 | ||||||
| 	if( phase=='move' && (direction=='left' || direction=='right') ){ | /*********************************************************************/ | ||||||
| 		mag.addClass('unanimated') | // XXX move to generic lib... | ||||||
| 		if (direction == 'left'){ | 
 | ||||||
| 			//$('.magazine').css({left: -n*cur.width()-distance/scale}) | // this will create a function that will add/remove a css_class to elem  | ||||||
| 			$('.magazine').css({left: -n*800-distance/scale}) | // calling the optional callbacks before and/or after. | ||||||
| 		} else if (direction == 'right') { | // | ||||||
| 			//$('.magazine').css({left: -n*cur.width()+distance/scale}) | // elem is a jquery compatible object; default use-case: a css selector. | ||||||
| 			$('.magazine').css({left: -n*800+distance/scale}) | // | ||||||
|  | // the resulting function understands the folowing arguments: | ||||||
|  | // 	- 'on'			: switch mode on | ||||||
|  | // 	- 'off'			: switch mode off | ||||||
|  | // 	- '?'			: return current state ('on'|'off') | ||||||
|  | // 	- no arguments	: toggle the state | ||||||
|  | // | ||||||
|  | // NOTE: of only one callback is given then it will be called after the  | ||||||
|  | // 		 class change... | ||||||
|  | // 		 a way around this is to pass an empty function as callback_b | ||||||
|  | // | ||||||
|  | function createCSSClassToggler(elem, css_class, callback_a, callback_b){ | ||||||
|  | 	// prepare the pre/post callbacks... | ||||||
|  | 	if(callback_b == null){ | ||||||
|  | 		var callback_pre = null | ||||||
|  | 		var callback_post = callback_a | ||||||
|  | 	} else { | ||||||
|  | 		var callback_pre = callback_a | ||||||
|  | 		var callback_post = callback_b | ||||||
| 	} | 	} | ||||||
| 		setTimeout(function(){mag.removeClass('unanimated')}, 5) | 	// build the acual toggler function... | ||||||
| 
 | 	var func = function(action){ | ||||||
| 	} else if ( phase == 'cancel') { | 		if(action == null || action == '?'){ | ||||||
| 		setCurrentPage() | 			var getter = action == '?' ? true : false | ||||||
| 
 | 			action = 'on' | ||||||
| 	} else if ( phase =='end' ) { | 			// get current state... | ||||||
| 		// see which page is closer to the middle of the screen and set it... | 			if( $(elem).hasClass(css_class) ){ | ||||||
| 		// do this based on how much we dragged... | 				action = 'off' | ||||||
| 		var p = Math.ceil((distance/scale)/cur.width()) | 			} | ||||||
| 
 | 			if(getter){ | ||||||
| 		// prev page... | 				// as the above actions indicate intent and not state,  | ||||||
| 		if(direction == 'right') { | 				// we'll need to swap the values... | ||||||
| 			setCurrentPage(Math.max(n-p, 0)) | 				return action == 'on' ? 'off' : 'on' | ||||||
| 		// next page... |  | ||||||
| 		} else if (direction == 'left'){ |  | ||||||
| 			setCurrentPage(Math.min(n+p, pages.length-1)) |  | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  | 		if(callback_pre != null){ | ||||||
|  | 			callback_pre(action) | ||||||
|  | 		} | ||||||
|  | 		// play with the class... | ||||||
|  | 		if(action == 'on'){ | ||||||
|  | 			$(elem).addClass(css_class) | ||||||
|  | 		} else { | ||||||
|  | 			$(elem).removeClass(css_class) | ||||||
|  | 		} | ||||||
|  | 		if(callback_post != null){ | ||||||
|  | 			callback_post(action) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	func.doc = 'With no arguments this will toggle between "on" and '+ | ||||||
|  | 		'"off".\n'+ | ||||||
|  | 		'If either "on" or "off" are given then this will switch '+ | ||||||
|  | 		'to that mode.\n'+ | ||||||
|  | 		'If "?" is given, this will return either "on" or "off" '+ | ||||||
|  | 		'depending on the current state.' | ||||||
|  | 	return func | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| @ -105,9 +129,194 @@ function unanimated(obj, func, time){ | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | // Return a scale value for the given element(s). | ||||||
|  | // NOTE: this will only return a single scale value... | ||||||
|  | function getElementScale(elem){ | ||||||
|  | 	//var transform = elem.css('transform') | ||||||
|  | 	var vendors = ['o', 'moz', 'ms', 'webkit'] | ||||||
|  | 	var transform = elem.css('transform') | ||||||
|  | 	var res | ||||||
|  | 
 | ||||||
|  | 	// go through vendor prefixes... (hate this!) | ||||||
|  | 	if(!transform || transform == 'none'){ | ||||||
|  | 		for(var i in vendors){ | ||||||
|  | 			transform = elem.css('-' + vendors[i] + '-transform') | ||||||
|  | 			if(transform && transform != 'none'){ | ||||||
|  | 				break | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	// no transform is set... | ||||||
|  | 	if(!transform || transform == 'none'){ | ||||||
|  | 		return 1 | ||||||
|  | 	} | ||||||
|  | 	// get the scale value -- first argument of scale/matrix... | ||||||
|  | 	return parseFloat((/(scale|matrix)\(([^,]*),.*\)/).exec(transform)[2]) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function setElementScale(elem, scale){ | ||||||
|  | 	return elem.css({ | ||||||
|  | 		'transform': 'scale('+scale+')', | ||||||
|  | 		'-moz-transform': 'scale('+scale+')', | ||||||
|  | 		'-o-transform': 'scale('+scale+')', | ||||||
|  | 		'-ms-transform': 'scale('+scale+')', | ||||||
|  | 		'-webkit-transform': 'scale('+scale+')', | ||||||
|  | 	}) | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| function setCurrentPage(n){ | 
 | ||||||
|  | 
 | ||||||
|  | /*********************************************************************/ | ||||||
|  | 
 | ||||||
|  | togglePageView = createCSSClassToggler( | ||||||
|  | 	'.viewer',  | ||||||
|  | 	'page-view-mode', | ||||||
|  | 	null, | ||||||
|  | 	// post-change callback... | ||||||
|  | 	function(){ | ||||||
|  | 		if(togglePageView('?') == 'on'){ | ||||||
|  | 			PAGES_VISIBLE = 1 | ||||||
|  | 			fitPagesToViewer(PAGES_VISIBLE) | ||||||
|  | 			//fitNPages(PAGES_VISIBLE) | ||||||
|  | 			// to prevent drag while zooming to affect | ||||||
|  | 			// the resulting position set it to current  | ||||||
|  | 			// page... | ||||||
|  | 			// XXX now this is done by fitNPages | ||||||
|  | 			//setCurrentPage() | ||||||
|  | 		} else { | ||||||
|  | 			PAGES_VISIBLE = PAGES_IN_RIBBON | ||||||
|  | 			// XXX this needs to be done before transitions... | ||||||
|  | 			fitPagesToContent(PAGES_VISIBLE) | ||||||
|  | 			//fitNPages(PAGES_VISIBLE) | ||||||
|  | 		} | ||||||
|  | 	}) | ||||||
|  | 
 | ||||||
|  | function getPageScale(){ | ||||||
|  | 	return getElementScale($('.scaler')) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function fitNPages(n){ | ||||||
|  | 	/* | ||||||
|  | 	if(n==null){ | ||||||
|  | 		n = 1 | ||||||
|  | 	} | ||||||
|  | 	var pages = $('.page') | ||||||
|  | 	var view = $('.viewer') | ||||||
|  | 	var W = view.width() | ||||||
|  | 	var H = view.height() | ||||||
|  | 	var w = pages.width() | ||||||
|  | 	var h = pages.height() | ||||||
|  | 
 | ||||||
|  | 	var scale = W/(w*n) | ||||||
|  | 
 | ||||||
|  | 	// fit vertically if needed... | ||||||
|  | 	if(h*scale > H){ | ||||||
|  | 		scale = H/h | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	setElementScale($('.scaler'), scale) | ||||||
|  | 	*/ | ||||||
|  | 
 | ||||||
|  | 	fitPagesTo(null, n) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // XXX this is a single big function because we need to thread data  | ||||||
|  | //		through to avoid sampling while animating... | ||||||
|  | function fitPagesTo(elem, n){ | ||||||
|  | 	if(n==null){ | ||||||
|  | 		n = 1 | ||||||
|  | 	} | ||||||
|  | 	var pages = $('.page') | ||||||
|  | 	var view = $('.viewer') | ||||||
|  | 	if(elem == null){ | ||||||
|  | 		elem = view | ||||||
|  | 	} else { | ||||||
|  | 		elem = $(elem) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// sample data... | ||||||
|  | 	var vW = view.width() | ||||||
|  | 	var vH = view.height() | ||||||
|  | 	var W = elem.width() | ||||||
|  | 	var H = elem.height() | ||||||
|  | 	var w = pages.width() | ||||||
|  | 	var h = pages.height() | ||||||
|  | 	var rW = w | ||||||
|  | 
 | ||||||
|  | 	// NOTE: there must be no data sampling after this point... | ||||||
|  | 	//		this is due to the fact that we will start changing stuff next | ||||||
|  | 	//		and if CSS transitions are at play new samples will be off... | ||||||
|  | 
 | ||||||
|  | 	// do the fitting... | ||||||
|  | 	if(W-w/H-h > 1){ | ||||||
|  | 		rW = W * (h/H)  | ||||||
|  | 		pages.width(rW) | ||||||
|  | 		$('.magazine').css({ | ||||||
|  | 			// NOTE: we can't use direct .width() here because of the transitions... | ||||||
|  | 			'margin-left': -rW/2 | ||||||
|  | 		}) | ||||||
|  | 	} | ||||||
|  | 	if(W-w/H-h < 1){ | ||||||
|  | 		pages.height(H * (w/W)) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// scale horizontally... | ||||||
|  | 	var scale = vW/(rW*n) | ||||||
|  | 	// or scale vertically if needed... | ||||||
|  | 	if(h*scale > vH){ | ||||||
|  | 		scale = vH/h | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	setElementScale($('.scaler'), scale) | ||||||
|  | 	// update position using the new width... | ||||||
|  | 	setCurrentPage(null, rW) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function fitPagesToViewer(n){ | ||||||
|  | 	fitPagesTo('.viewer', n) | ||||||
|  | } | ||||||
|  | function fitPagesToContent(n){ | ||||||
|  | 	fitPagesTo('.page .content', n) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | function swipeUpdate(evt, phase, direction, distance){ | ||||||
|  | 	var pages = $('.page') | ||||||
|  | 	var cur = $('.current.page') | ||||||
|  | 	var n = pages.index(cur) | ||||||
|  | 	var scale = getPageScale() | ||||||
|  | 	var mag = $('.magazine') | ||||||
|  | 
 | ||||||
|  | 	if( phase=='move' && (direction=='left' || direction=='right') ){ | ||||||
|  | 		mag.addClass('unanimated') | ||||||
|  | 		if (direction == 'left'){ | ||||||
|  | 			$('.magazine').css({left: -n*cur.width()-distance/scale}) | ||||||
|  | 		} else if (direction == 'right') { | ||||||
|  | 			$('.magazine').css({left: -n*cur.width()+distance/scale}) | ||||||
|  | 		} | ||||||
|  | 		setTimeout(function(){mag.removeClass('unanimated')}, 5) | ||||||
|  | 
 | ||||||
|  | 	} else if ( phase == 'cancel') { | ||||||
|  | 		setCurrentPage() | ||||||
|  | 
 | ||||||
|  | 	} else if ( phase =='end' ) { | ||||||
|  | 		// see which page is closer to the middle of the screen and set it... | ||||||
|  | 		// do this based on how much we dragged... | ||||||
|  | 		var p = Math.ceil((distance/scale)/cur.width()) | ||||||
|  | 
 | ||||||
|  | 		// prev page... | ||||||
|  | 		if(direction == 'right') { | ||||||
|  | 			setCurrentPage(Math.max(n-p, 0)) | ||||||
|  | 		// next page... | ||||||
|  | 		} else if (direction == 'left'){ | ||||||
|  | 			setCurrentPage(Math.min(n+p, pages.length-1)) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | function setCurrentPage(n, W){ | ||||||
| 	if(n == null){ | 	if(n == null){ | ||||||
| 		var cur = $('.current.page') | 		var cur = $('.current.page') | ||||||
| 		n = $('.page').index(cur)  | 		n = $('.page').index(cur)  | ||||||
| @ -122,7 +331,8 @@ function setCurrentPage(n){ | |||||||
| 	cur.addClass('current') | 	cur.addClass('current') | ||||||
| 
 | 
 | ||||||
| 	var mag = $('.magazine') | 	var mag = $('.magazine') | ||||||
| 	mag.css({left: -n*cur.width()}) | 	var W = W == null ? cur.width() : W | ||||||
|  | 	mag.css({left: -n*W}) | ||||||
| 
 | 
 | ||||||
| 	return cur | 	return cur | ||||||
| } | } | ||||||
| @ -183,61 +393,6 @@ function prevArticle(){ | |||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| // Return a scale value for the given element(s). |  | ||||||
| // NOTE: this will only return a single scale value... |  | ||||||
| function getElementScale(elem){ |  | ||||||
| 	//var transform = elem.css('transform') |  | ||||||
| 	var vendors = ['o', 'moz', 'ms', 'webkit'] |  | ||||||
| 	var transform = elem.css('transform') |  | ||||||
| 	var res |  | ||||||
| 
 |  | ||||||
| 	// go through vendor prefixes... (hate this!) |  | ||||||
| 	if(!transform || transform == 'none'){ |  | ||||||
| 		for(var i in vendors){ |  | ||||||
| 			transform = elem.css('-' + vendors[i] + '-transform') |  | ||||||
| 			if(transform && transform != 'none'){ |  | ||||||
| 				break |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	// no transform is set... |  | ||||||
| 	if(!transform || transform == 'none'){ |  | ||||||
| 		return 1 |  | ||||||
| 	} |  | ||||||
| 	// get the scale value -- first argument of scale/matrix... |  | ||||||
| 	return parseFloat((/(scale|matrix)\(([^,]*),.*\)/).exec(transform)[2]) |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| function setElementScale(elem, scale){ |  | ||||||
| 	return elem.css({ |  | ||||||
| 		'transform': 'scale('+scale+')', |  | ||||||
| 		'-moz-transform': 'scale('+scale+')', |  | ||||||
| 		'-o-transform': 'scale('+scale+')', |  | ||||||
| 		'-ms-transform': 'scale('+scale+')', |  | ||||||
| 		'-webkit-transform': 'scale('+scale+')', |  | ||||||
| 	}) |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| function fitNPages(n){ |  | ||||||
| 	if(n==null){ |  | ||||||
| 		n = 1 |  | ||||||
| 	} |  | ||||||
| 	var pages = $('.page') |  | ||||||
| 	var scale = $('.viewer').width()/(pages.width()*n) |  | ||||||
| 
 |  | ||||||
| 	// fit vertically if needed... |  | ||||||
| 	if(pages.height()*scale > $('.viewer').height()){ |  | ||||||
| 		scale = $('.viewer').height()/pages.height() |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	setElementScale($('.scaler'), scale) |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| // XXX create magazine... | // XXX create magazine... | ||||||
| function createMagazine(){ | function createMagazine(){ | ||||||
| } | } | ||||||
| @ -268,9 +423,11 @@ function createPage(article, template){ | |||||||
| 
 | 
 | ||||||
| 		<div class="article"> | 		<div class="article"> | ||||||
| 			<div class="cover page"> | 			<div class="cover page"> | ||||||
|  | 				<div class="content"> | ||||||
| 					Article Cover<br> | 					Article Cover<br> | ||||||
| 					some more text... | 					some more text... | ||||||
| 				</div> | 				</div> | ||||||
|  | 			</div> | ||||||
| 
 | 
 | ||||||
| 			<!-- XXX do we need an Article Credits page??? --> | 			<!-- XXX do we need an Article Credits page??? --> | ||||||
| 
 | 
 | ||||||
|  | |||||||
							
								
								
									
										33
									
								
								magazine.css
									
									
									
									
									
								
							
							
						
						
									
										33
									
								
								magazine.css
									
									
									
									
									
								
							| @ -9,8 +9,7 @@ body { | |||||||
| 	/* XXX make this browser-sized... */ | 	/* XXX make this browser-sized... */ | ||||||
| 	display: inline-block; | 	display: inline-block; | ||||||
| 	vertical-align: bottom; | 	vertical-align: bottom; | ||||||
| 
 | 	text-align: center; | ||||||
| 	overflow: auto; |  | ||||||
| 
 | 
 | ||||||
| 	/* XXX need these to be the same as the magazine, for some reason does not work... | 	/* XXX need these to be the same as the magazine, for some reason does not work... | ||||||
| 	 *	one way to go is to use a fixed page layout and scale things manually. | 	 *	one way to go is to use a fixed page layout and scale things manually. | ||||||
| @ -22,15 +21,30 @@ body { | |||||||
| 	margin-top: -300px; | 	margin-top: -300px; | ||||||
| 
 | 
 | ||||||
| 	font-size: 12px; | 	font-size: 12px; | ||||||
|  | 
 | ||||||
|  | 	-webkit-transition: all 0.2s ease; | ||||||
|  | 	-moz-transition: all 0.2s ease; | ||||||
|  | 	-o-transition: all 0.2s ease; | ||||||
|  | 	-ms-transition: all 0.2s ease;	 | ||||||
|  | 	transition: all 0.2s ease; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| .current.page { | .page .content { | ||||||
| } | 	display: inline-block; | ||||||
|  | 	text-align: left; | ||||||
|  | 	position: relative; | ||||||
| 
 | 
 | ||||||
|  | 	/* these set the "safe" marks for page content */ | ||||||
|  | 	width: 800px; | ||||||
|  | 	height: 600px; | ||||||
|  | 
 | ||||||
|  | 	border: solid red 1px; | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| /* general layout */ | /* general layout */ | ||||||
| 
 | 
 | ||||||
| .viewer { | .viewer { | ||||||
|  | 	position: relative; | ||||||
| 	/* this makes the magazine behave like a ribbon */ | 	/* this makes the magazine behave like a ribbon */ | ||||||
| 	width: 100%; | 	width: 100%; | ||||||
| 	height: 100%; | 	height: 100%; | ||||||
| @ -104,7 +118,18 @@ body { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | /* modes */ | ||||||
|  | .page-view-mode .viewer { | ||||||
|  | } | ||||||
|  | .page-view-mode .page { | ||||||
|  | } | ||||||
|  | .page-view-mode .current.page { | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /* keep this at the end... */ | ||||||
| .unanimated { | .unanimated { | ||||||
| 	-webkit-transition: none; | 	-webkit-transition: none; | ||||||
| 	-moz-transition: none; | 	-moz-transition: none; | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user