text: /**
   * @file js/controllers/ExtrasOnDemandHandler.js
   *
   * Copyright (c) 2014-2021 Simon Fraser University
   * Copyright (c) 2000-2021 John Willinsky
   * Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
   *
   * @class ExtrasOnDemandHandler
   * @ingroup js_controllers
   *
   * @brief A basic handler for extras on demand UI pattern.
   */
  (function($) {
  
  
  	/**
  	 * @constructor
  	 *
  	 * @extends $.pkp.classes.Handler
  	 *
  	 * @param {jQueryObject} $widgetWrapper An HTML element that contains the
  	 *   widget.
  	 * @param {Object} options Handler options.
  	 */
  	$.pkp.controllers.ExtrasOnDemandHandler = function($widgetWrapper, options) {
  		this.parent($widgetWrapper, options);
  
  		$('.toggleExtras', $widgetWrapper).click(
  				this.callbackWrapper(this.toggleExtras));
  	};
  	$.pkp.classes.Helper.inherits(
  			$.pkp.controllers.ExtrasOnDemandHandler, $.pkp.classes.Handler);
  
  
  	//
  	// Public methods
  	//
  	/**
  	 * Event handler that is called when toggle extras div is clicked.
  	 *
  	 * @param {HTMLElement} toggleExtras The div that is clicked to toggle extras.
  	 * @param {Event} event The triggering event.
  	 */
  	$.pkp.controllers.ExtrasOnDemandHandler.prototype.toggleExtras =
  			function(toggleExtras, event) {
  		var $widgetWrapper = this.getHtmlElement(),
  				$scrollable;
  
  		event.preventDefault();
  
  		$widgetWrapper.toggleClass('active');
  
  		if ($widgetWrapper.hasClass('active')) {
  			// Identify if there is a scrollable parent.
  			$scrollable = $widgetWrapper.closest('.scrollable');
  			if ($scrollable.length > 0) {
  				// Scroll the parent so that all extra content in
  				// extras container is visible.
  				this.scrollToMakeVisible_($widgetWrapper, $scrollable);
  			}
  		}
  	};
  
  
  	//
  	// Private methods
  	//
  	/**
  	 * Scroll a scrollable element to make the
  	 * given content element visible. The content element
  	 * must be a descendant of a scrollable
  	 * element (needs to have class "scrollable").
  	 *
  	 * NB: This method depends on the position() method
  	 * to refer to the same parent element for both the
  	 * content element and the scrollable element.
  	 *
  	 * @private
  	 *
  	 * @param {jQueryObject} $widgetWrapper The element to be made visible.
  	 * @param {Array|jQueryObject} $scrollable The parent scrollable element.
  	 */
  	$.pkp.controllers.ExtrasOnDemandHandler.prototype.scrollToMakeVisible_ =
  			function($widgetWrapper, $scrollable) {
  		var extrasWidgetTop, scrollingWidgetTop, currentScrollingTop,
  				hiddenPixels, newScrollingTop;
  
  		extrasWidgetTop = $widgetWrapper.position().top;
  		scrollingWidgetTop = $scrollable.position().top;
  		currentScrollingTop = parseInt($scrollable.scrollTop(), 10);
  
  		// Do we have to scroll down or scroll up?
  		if (extrasWidgetTop > scrollingWidgetTop) {
  			// Consider scrolling down...
  
  			// Calculate the number of hidden pixels of the child
  			// element within the scrollable element.
  			hiddenPixels = Math.ceil(extrasWidgetTop +
  					$widgetWrapper.height() - $scrollable.height());
  
  			// Scroll down if parts or all of this widget are hidden.
  			if (hiddenPixels > 0) {
  				$scrollable.scrollTop(currentScrollingTop + hiddenPixels);
  			}
  		} else {
  			// Scroll up...
  
  			// Calculate the new scrolling top.
  			newScrollingTop = Math.max(Math.floor(
  					currentScrollingTop + extrasWidgetTop - scrollingWidgetTop), 0);
  
  			// Set the new scrolling top.
  			$scrollable.scrollTop(newScrollingTop);
  		}
  	};
  
  
  }(jQuery));
  