Skip to content

Instantly share code, notes, and snippets.

@zajca
Last active August 29, 2015 14:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zajca/f10668cce4ebc5979dbb to your computer and use it in GitHub Desktop.
Save zajca/f10668cce4ebc5979dbb to your computer and use it in GitHub Desktop.
Crocodoc.addComponent('layout-zoom', ['layout-presentation'], function (scope, presentation) {
'use strict';
//--------------------------------------------------------------------------
// Private
//--------------------------------------------------------------------------
var util = scope.getUtility('common');
//--------------------------------------------------------------------------
// Public
//--------------------------------------------------------------------------
return presentation.extend({
/**
* Initialize the presentation layout component
* @returns {void}
*/
init: function () {
presentation.init.call(this);
},
/**
* Set the zoom level for the layout
* @param {float|string} val The zoom level (float or one of the zoom constants)
* @param {int} offsetX mouse position relative to viewport
* @param {int} offsetY mouse position relative to viewport
*/
setZoom: function (val,offsetX,offsetY) {
var state = this.state,
zoom = this.parseZoomValue(val),
zoomState = state.zoomState,
currentZoom = zoomState.zoom,
zoomMode,
shouldNotCenter;
// update the zoom mode if we landed on a named mode
zoomMode = this.calculateZoomMode(val, zoom);
//respect zoom constraints
zoom = util.clamp(zoom, state.minZoom, state.maxZoom);
scope.broadcast('beforezoom', util.extend({
page: state.currentPage,
visiblePages: util.extend([], state.visiblePages),
fullyVisiblePages: util.extend([], state.fullyVisiblePages)
}, zoomState));
// update the zoom state
zoomState.prevZoom = currentZoom;
zoomState.zoom = zoom;
zoomState.zoomMode = zoomMode;
// apply the zoom to the actual DOM element(s)
this.applyZoom(zoom);
// can the document be zoomed in/out further?
zoomState.canZoomIn = this.calculateNextZoomLevel(Crocodoc.ZOOM_IN) !== false;
zoomState.canZoomOut = this.calculateNextZoomLevel(Crocodoc.ZOOM_OUT) !== false;
// update page states, because they will have changed after zooming
this.updatePageStates();
// layout mode specific stuff
this.updateLayout();
// update scroll position for the new zoom
// @NOTE: updateScrollPosition() must be called AFTER updateLayout(),
// because the scrollable space may change in updateLayout
// @NOTE: shouldNotCenter is true when using a named zoom level
// so that resizing the browser zooms to the current page offset
// rather than to the center like when zooming in/out
shouldNotCenter = val === Crocodoc.ZOOM_AUTO ||
val === Crocodoc.ZOOM_FIT_WIDTH ||
val === Crocodoc.ZOOM_FIT_HEIGHT ||
offsetX === undefined ||
offsetY === undefined;
this.updateScrollPositionAfterClickZoom(offsetX,offsetY,shouldNotCenter);
// update again, because updateLayout could have changed page positions
this.updatePageStates();
// make sure the visible pages are accurate (also update css classes)
this.updateVisiblePages(true);
console.log('zoom broadcast');
// broadcast zoom event with new zoom state
scope.broadcast('zoom', util.extend({
page: state.currentPage,
visiblePages: util.extend([], state.visiblePages),
fullyVisiblePages: util.extend([], state.fullyVisiblePages),
isDraggable: this.isDraggable()
}, zoomState));
},
/**
* Update the scroll position after a zoom on specific position
* @param {bool} shouldNotCenter Whether or not the scroll position
* should be updated to center the new
* zoom level
* @param {int} offsetX mouse position relative to viewport
* @param {int} offsetY mouse position relative to viewport
* @returns {void}
*/
updateScrollPositionAfterClickZoom: function (offsetX,offsetY,shouldNotCenter) {
var state = this.state,
zoomState = state.zoomState,
ratio = zoomState.zoom / zoomState.prevZoom,
newScrollLeft, newScrollTop,
page = state.pages[state.visiblePages[0]];
// update scroll position
newScrollLeft = state.scrollLeft * ratio;
newScrollTop = state.scrollTop * ratio;
if (shouldNotCenter !== true) {
newScrollLeft = (offsetX-page.paddingTop) * ratio;
newScrollTop = (offsetY-page.paddingLeft) * ratio;
}
// scroll!
this.scrollToOffset(newScrollLeft, newScrollTop);
}
});
});
/**
* Touch component definition
* this plugin can handle doubletap singletap and swipe actions
* dependency - some lib that creates doubletap, singletap and swipe event like jquery.mobile-events
*/
Crocodoc.addPlugin('touch', function (scope) {
'use strict';
var $el,api,pluginConfig,$viewport,
zoomActive = false;
function createEventData(){
return {
zoomActive: zoomActive
}
}
function handleDoubletap(event,touch) {
api.fire('doubletap',createEventData());
if(zoomActive){
zoomActive = false;
api.zoom(Crocodoc.ZOOM_FIT_WIDTH);
return
}
scope.getConfig().currentLayout.setZoom(3,touch.secondTap.offset.y,touch.secondTap.offset.x);
zoomActive = true;
event.preventDefault();
}
/**
* Handle single tap events
* @param {Event} event The event object
* @returns {void}
*/
function handleSingletap(event) {
api.fire('singletap',createEventData());
( pluginConfig.onsingletap || $.noop )();
event.preventDefault();
}
/**
* Handle swipe left events
* @param {Event} event The event object
* @returns {void}
*/
function handleSwipeLeft(event) {
api.fire('swipeleft',createEventData());
if( ! zoomActive ){
presentation.scrollTo(Crocodoc.SCROLL_NEXT);
}
event.preventDefault();
}
/**
* Handle swipe right events
* @param {Event} event The event object
* @returns {void}
*/
function handleSwipeRight(event) {
api.fire('swiperight',createEventData());
if( ! zoomActive ){
presentation.scrollTo(Crocodoc.SCROLL_PREVIOUS);
}
event.preventDefault();
}
/**
* Handle zoom events
* @param {Object} data The event object
* @returns {void}
*/
function handleZoom(data) {
//zoomActive = data.zoomMode !== Crocodoc.ZOOM_FIT_WIDTH;
//
//if( ! data.canZoomIn || ! data.canZoomOut ){
// zoomActive = false;
// api.zoom(Crocodoc.ZOOM_FIT_WIDTH);
//}
}
//--------------------------------------------------------------------------
// Public
//--------------------------------------------------------------------------
return {
messages: ['zoom','pagefocus'],
onmessage: function(name,data){
switch (name) {
case 'zoom':
handleZoom(data);
break;
case 'pagefocus':
api.zoom(Crocodoc.ZOOM_FIT_WIDTH);
break;
}
},
/**
* Initialize the zoom component
* @param {Object} config
* @returns {void}
*/
init: function (config) {
pluginConfig = config;
config = scope.getConfig();
$el = config.$el;
api = config.api;
$viewport = config.$viewport;
$el.on('doubletap', handleDoubletap);
$el.on('singletap', handleSingletap);
$el.on('swipeleft',handleSwipeLeft);
$el.on('swiperight',handleSwipeRight);
},
/**
* Destroy the scroller component
* @returns {void}
*/
destroy: function () {
$el.off('doubletap', handleDoubletap);
$el.off('singletap', handleSingletap);
}
};
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment