Last active
August 29, 2015 14:23
-
-
Save zajca/f10668cce4ebc5979dbb to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | |
} | |
}); | |
}); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* 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