1/** 2 * @file js/controllers/ExtrasOnDemandHandler.js 3 * 4 * Copyright (c) 2013-2019 Simon Fraser University 5 * Copyright (c) 2000-2019 John Willinsky 6 * Distributed under the GNU GPL v2. For full terms see the file docs/COPYING. 7 * 8 * @class ExtrasOnDemandHandler 9 * @ingroup js_controllers 10 * 11 * @brief A basic handler for extras on demand UI pattern. 12 */ 13(function($) { 14 15 16 /** 17 * @constructor 18 * 19 * @extends $.pkp.classes.Handler 20 * 21 * @param {jQueryObject} $widgetWrapper An HTML element that contains the 22 * widget. 23 * @param {Object} options Handler options. 24 */ 25 $.pkp.controllers.ExtrasOnDemandHandler = function($widgetWrapper, options) { 26 this.parent($widgetWrapper, options); 27 28 // Show the toggle button and attach click event 29 // to it. We hide this by default to provide a graceful 30 // fallback in case JS is switched off. 31 $('.toggleExtras', $widgetWrapper).show().click( 32 this.callbackWrapper(this.toggleExtras)); 33 34 // Hide extras (default initial widget state). 35 this.deactivateExtraContent_(); 36 }; 37 $.pkp.classes.Helper.inherits( 38 $.pkp.controllers.ExtrasOnDemandHandler, $.pkp.classes.Handler); 39 40 41 // 42 // Public methods 43 // 44 /** 45 * Event handler that is called when toggle extras div is clicked. 46 * 47 * @param {HTMLElement} toggleExtras The div that is clicked to toggle extras. 48 */ 49 $.pkp.controllers.ExtrasOnDemandHandler.prototype.toggleExtras = 50 function(toggleExtras) { 51 52 var $widgetWrapper = this.getHtmlElement(); 53 54 if ($(toggleExtras, $widgetWrapper).hasClass('active')) { 55 this.deactivateExtraContent_('slow'); 56 } else { 57 this.activateExtraContent_('slow'); 58 } 59 }; 60 61 62 // 63 // Private methods 64 // 65 /** 66 * Activate extra content. 67 * @private 68 * @param {string=} opt_duration The effect duration. 69 */ 70 $.pkp.controllers.ExtrasOnDemandHandler.prototype.activateExtraContent_ = 71 function(opt_duration) { 72 var $widgetWrapper, $scrollable; 73 74 $widgetWrapper = this.getHtmlElement(); 75 76 // Hide the inactive version of the toggle extras span. 77 $('.toggleExtras .toggleExtras-inactive', $widgetWrapper).hide(); 78 79 // Show the active version of the toggle extras span and the extras container. 80 $('.extrasContainer', $widgetWrapper).show(opt_duration); 81 $('.toggleExtras .toggleExtras-active', $widgetWrapper).show(); 82 83 // Adapt styling of the toggle extras div. 84 $('.toggleExtras', $widgetWrapper).removeClass('inactive').addClass('active'); 85 86 // Change the toggle icon into a triangle pointing downwards. 87 $('.ui-icon', $widgetWrapper) 88 .removeClass('ui-icon-triangle-1-e') 89 .addClass('ui-icon-triangle-1-s'); 90 91 // Identify if there is a scrollable parent. 92 $scrollable = $widgetWrapper.closest('.scrollable'); 93 if ($scrollable.size() > 0) { 94 95 // Scroll the parent so that all extra content in 96 // extras container is visible. 97 if ($.browser.msie && parseInt( 98 $.browser.version.substring(0, 1), 10) <= 7) { 99 100 // IE7 is old and slow and returns before repainting everything, 101 // so wait half a second for the page to repaint before going on. 102 setTimeout(function() {this.scrollToMakeVisible_( 103 $widgetWrapper, $scrollable);}, 500); 104 } else { 105 106 // Other browsers can proceed immediately. 107 this.scrollToMakeVisible_($widgetWrapper, $scrollable); 108 } 109 } 110 }; 111 112 113 /** 114 * Deactivate extra content. 115 * @private 116 * @param {string=} opt_duration The effect duration. 117 */ 118 $.pkp.controllers.ExtrasOnDemandHandler.prototype.deactivateExtraContent_ = 119 function(opt_duration) { 120 121 var $widgetWrapper = this.getHtmlElement(); 122 123 // Hide the active version of the toggle extras span and the extras container. 124 $('.extrasContainer', $widgetWrapper).hide(opt_duration); 125 $('.toggleExtras .toggleExtras-active', $widgetWrapper).hide(); 126 127 // Show the inactive version of the toggle extras span. 128 $('.toggleExtras .toggleExtras-inactive', $widgetWrapper).show(); 129 130 // Adapt styling of the toggle extras div. 131 $('.toggleExtras', $widgetWrapper).removeClass('active').addClass('inactive'); 132 133 // Change the toggle icon into a triangle pointing to the right. 134 $('.ui-icon', $widgetWrapper).removeClass('ui-icon-triangle-1-s') 135 .addClass('ui-icon-triangle-1-e'); 136 }; 137 138 139 /** 140 * Scroll a scrollable element to make the 141 * given content element visible. The content element 142 * must be a descendant of a scrollable 143 * element (needs to have class "scrollable"). 144 *
145 * NB: This method depends on the position() method 146 * to refer to the same parent element for both the 147 * content element and the scrollable element. 148 * 149 * @private 150 * 151 * @param {jQueryObject} $widgetWrapper The element to be made visible. 152 * @param {Array|jQueryObject} $scrollable The parent scrollable element. 153 */ 154 $.pkp.controllers.ExtrasOnDemandHandler.prototype.scrollToMakeVisible_ = 155 function($widgetWrapper, $scrollable) { 156 var extrasWidgetTop, scrollingWidgetTop, currentScrollingTop, 157 hiddenPixels, newScrollingTop; 158 159 extrasWidgetTop = $widgetWrapper.position().top; 160 scrollingWidgetTop = $scrollable.position().top; 161 currentScrollingTop = parseInt($scrollable.scrollTop(), 10); 162 163 // Do we have to scroll down or scroll up? 164 if (extrasWidgetTop > scrollingWidgetTop) { 165 // Consider scrolling down... 166 167 // Calculate the number of hidden pixels of the child 168 // element within the scrollable element. 169 hiddenPixels = Math.ceil(extrasWidgetTop + 170 $widgetWrapper.height() - $scrollable.height()); 171 172 // Scroll down if parts or all of this widget are hidden. 173 if (hiddenPixels > 0) { 174 $scrollable.scrollTop(currentScrollingTop + hiddenPixels); 175 } 176 } else { 177 // Scroll up... 178 179 // Calculate the new scrolling top. 180 newScrollingTop = Math.max(Math.floor( 181 currentScrollingTop + extrasWidgetTop - scrollingWidgetTop), 0); 182 183 // Set the new scrolling top. 184 $scrollable.scrollTop(newScrollingTop); 185 } 186 }; 187 188 189/** @param {jQuery} $ jQuery closure. */ 190}(jQuery));
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.