1/** 2 * @file plugins/themes/default/js/main.js 3 * 4 * Copyright (c) 2014-2020 Simon Fraser University 5 * Copyright (c) 2000-2020 John Willinsky 6 * Distributed under the GNU GPL v3. For full terms see the file docs/COPYING. 7 * 8 * @brief Handle JavaScript functionality unique to this theme. 9 */ 10(function($) { 11 12 // Initialize dropdown navigation menus on large screens 13 // See bootstrap dropdowns: https://getbootstrap.com/docs/4.0/components/dropdowns/ 14 if (typeof $.fn.dropdown !== 'undefined') { 15 var $nav = $('#navigationPrimary, #navigationUser'), 16 $submenus = $('ul', $nav); 17 function toggleDropdowns() { 18 if (window.innerWidth > 992) { 19 $submenus.each(function(i) { 20 var id = 'pkpDropdown' + i; 21 $(this) 22 .addClass('dropdown-menu') 23 .attr('aria-labelledby', id); 24 $(this).siblings('a') 25 .attr('data-toggle', 'dropdown') 26 .attr('aria-haspopup', true) 27 .attr('aria-expanded', false) 28 .attr('id', id) 29 .attr('href', '#'); 30 }); 31 $('[data-toggle="dropdown"]').dropdown(); 32 33 } else { 34 $('[data-toggle="dropdown"]').dropdown('dispose'); 35 $submenus.each(function(i) { 36 $(this) 37 .removeClass('dropdown-menu') 38 .removeAttr('aria-labelledby'); 39 $(this).siblings('a') 40 .removeAttr('data-toggle') 41 .removeAttr('aria-haspopup') 42 .removeAttr('aria-expanded',) 43 .removeAttr('id') 44 .attr('href', '#'); 45 }); 46 } 47 } 48 window.onresize = toggleDropdowns; 49 $().ready(function() { 50 toggleDropdowns(); 51 }); 52 } 53 54 // Toggle nav menu on small screens 55 $('.pkp_site_nav_toggle').click(function(e) { 56 $('.pkp_site_nav_menu').toggleClass('pkp_site_nav_menu--isOpen'); 57 $('.pkp_site_nav_toggle').toggleClass('pkp_site_nav_toggle--transform'); 58 }); 59 60 61 // Register click handlers for the search panel 62 var headerSearchPanelIsClosing = false, 63 headerSearchForm = $('#headerNavigationContainer .pkp_search'), 64 headerSearchPrompt = $('.headerSearchPrompt', headerSearchForm), 65 headerSearchCancel = $('.headerSearchCancel', headerSearchForm), 66 headerSearchInput = $('input[name="query"]', headerSearchForm); 67 68 // Register events 69 headerSearchPrompt.on('click', triggerSearchPanel); 70 headerSearchCancel.on('click', closeSearchPanel); 71 headerSearchInput.on('blur', function() { 72 if(!headerSearchInput.val() && headerSearchForm.hasClass('is_open')) { 73 closeSearchPanel(); 74 } 75 }); 76 headerSearchForm.on('submit', function() { 77 if(headerSearchForm.hasClass('is_searching')) { 78 return; 79 } 80 headerSearchForm.addClass('is_searching'); 81 }); 82 headerSearchForm.on('keyup', function(e) { 83 if(headerSearchForm.hasClass('is_open') && e.keyCode == 27) { 84 closeSearchPanel(); 85 } 86 }); 87 88 /** 89 * Open or submit search form 90 * 91 * @param Event e Optional event handler 92 */ 93 function triggerSearchPanel(e) { 94 95 if (headerSearchPanelIsClosing) { 96 return; 97 } 98 99 if (typeof e !== 'undefined') { 100 e.preventDefault(); 101 e.stopPropagation(); 102 } 103 104 if (headerSearchForm.hasClass('is_open')) { 105 headerSearchForm.submit(); 106 return; 107 } 108 109 headerSearchForm.addClass('is_open'); 110 setTimeout(function() { 111 headerSearchForm.find('input[type="text"]').focus(); 112 },200); 113 } 114 115 /** 116 * Close the search panel 117 * 118 * @param Event e Optional event handler 119 */ 120 function closeSearchPanel(e) { 121 122 if (headerSearchPanelIsClosing) { 123 return; 124 } 125 126 if (typeof e !== 'undefined') { 127 e.preventDefault(); 128 e.stopPropagation(); 129 } 130 131 headerSearchPanelIsClosing = true; 132 headerSearchForm.removeClass('is_open'); 133 134 setTimeout(function() { 135 headerSearchPanelIsClosing = false; 136 headerSearchInput.val(''); 137 },300) 138 } 139 140 // Modify the Chart.js display options used by UsageStats plugin 141 document.addEventListener('usageStatsChartOptions.pkp', function(e) { 142 e.chartOptions.elements.line.backgroundColor = 'rgba(0, 122, 178, 0.6)'; 143 e.chartOptions.elements.rectangle.backgroundColor = 'rgba(0, 122, 178, 0.6)'; 144 }); 145 146 // Toggle display of consent checkboxes in site-wide registration 147 var $contextOptinGroup = $('#contextOptinGroup'); 148 if ($contextOptinGroup.length) { 149 var $roles = $contextOptinGroup.find('.roles :checkbox'); 150 $roles.change(function() { 151 var $thisRoles = $(this).closest('.roles'); 152 if ($thisRoles.find(':checked').length) { 153 $thisRoles.siblings('.context_privacy').addClass('context_privacy_visible'); 154 } else { 155 $thisRoles.siblings('.context_privacy').removeClass('context_privacy_visible'); 156 } 157 }); 158 } 159 160 // Initialize tag-it components 161 // 162 // The tag-it component is used during registration for the user to enter 163 // their review interests. See: /templates/frontend/pages/userRegister.tpl 164 if (typeof $.fn.tagit !== 'undefined') { 165 $('.tag-it').each(function() { 166 var autocomplete_url = $(this).data('autocomplete-url'); 167 $(this).tagit({ 168 fieldName: $(this).data('field-name'), 169 allowSpaces: true, 170 autocomplete: { 171 source: function(request, response) { 172 $.ajax({ 173 url: autocomplete_url, 174 data: {term: request.term}, 175 dataType: 'json', 176 success: function(jsonData) { 177 if (jsonData.status == true) { 178 response(jsonData.content); 179 } 180 } 181 }); 182 }, 183 }, 184 }); 185 }); 186 187 /** 188 * Determine if the user has opted to register as a reviewer 189 * 190 * @see: /templates/frontend/pages/userRegister.tpl 191 */ 192 function isReviewerSelected() { 193 var group = $('#reviewerOptinGroup').find('input'); 194 var is_checked = false;
195 group.each(function() { 196 if ($(this).is(':checked')) { 197 is_checked = true; 198 return false; 199 } 200 }); 201 202 return is_checked; 203 } 204 205 /** 206 * Reveal the reviewer interests field on the registration form when a 207 * user has opted to register as a reviewer 208 * 209 * @see: /templates/frontend/pages/userRegister.tpl 210 */ 211 function reviewerInterestsToggle() { 212 var is_checked = isReviewerSelected(); 213 if (is_checked) { 214 $('#reviewerInterests').addClass('is_visible'); 215 } else { 216 $('#reviewerInterests').removeClass('is_visible'); 217 } 218 } 219 220 // Update interests on page load and when the toggled is toggled 221 reviewerInterestsToggle(); 222 $('#reviewerOptinGroup input').click(reviewerInterestsToggle); 223 } 224 225})(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.