docs: function (val) {
              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;
              this.updateScrollPosition(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);
  
              // 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));
          }