1/** 2 * @file plugins/themes/default/js/main.js 3 * 4 * Copyright (c) 2014-2017 Simon Fraser University 5 * Copyright (c) 2000-2017 John Willinsky 6 * Distributed under the GNU GPL v2. For full terms see the file docs/COPYING. 7 * 8 * @brief Handle JavaScript functionality unique to this theme. 9 */ 10(function($) { 11 12 // Update nav menu ARIA states on focus, blur and mouse over/out events 13 $('.navDropdownMenu ul').on('focus.default mouseenter.default', '[aria-haspopup="true"]', function (e) { 14 $(e.currentTarget).attr('aria-expanded', true); 15 }); 16 17 $('.navDropdownMenu ul').on('blur.default mouseleave.default', '[aria-haspopup="true"]', function (e) { 18 $(e.currentTarget).attr('aria-expanded', false) 19 .attr('pkp-touch-state', ''); 20 }); 21 22 // Taps on nav menu items with submenus should expand on first tap 23 $('.navDropdownMenu a').on('touchstart', function(e) { 24 var target = $(e.target), 25 li = target.parent('li'); 26 if (li.length && li.attr('aria-haspopup')) { 27 var state = li.attr('pkp-touch-state') || ''; 28 if (state != 'open') { 29 target.trigger('focus.default'); 30 li.attr('pkp-touch-state', 'open'); 31 e.preventDefault(); 32 } 33 } 34 }) 35 36 // Register click handlers for the search panel 37 var headerSearchPanelIsClosing = false, 38 headerSearchForm = $('#headerNavigationContainer .pkp_search'), 39 headerSearchPrompt = $('.headerSearchPrompt', headerSearchForm), 40 headerSearchCancel = $('.headerSearchCancel', headerSearchForm), 41 headerSearchInput = $('input[name="query"]', headerSearchForm); 42 43 // Register events 44 headerSearchPrompt.on('click', triggerSearchPanel); 45 headerSearchCancel.on('click', closeSearchPanel); 46 headerSearchInput.on('blur', function() { 47 if(!headerSearchInput.val() && headerSearchForm.hasClass('is_open')) { 48 closeSearchPanel(); 49 } 50 }); 51 headerSearchForm.on('submit', function() { 52 if(headerSearchForm.hasClass('is_searching')) { 53 return; 54 } 55 headerSearchForm.addClass('is_searching'); 56 }); 57 headerSearchForm.on('keyup', function(e) { 58 if(headerSearchForm.hasClass('is_open') && e.keyCode == 27) { 59 closeSearchPanel(); 60 } 61 }); 62 63 /** 64 * Open or submit search form 65 * 66 * @param Event e Optional event handler 67 */ 68 function triggerSearchPanel(e) { 69 70 if (headerSearchPanelIsClosing) { 71 return; 72 } 73 74 if (typeof e !== 'undefined') { 75 e.preventDefault(); 76 e.stopPropagation(); 77 } 78 79 if (headerSearchForm.hasClass('is_open')) { 80 headerSearchForm.submit(); 81 return; 82 } 83 84 headerSearchForm.addClass('is_open'); 85 setTimeout(function() { 86 headerSearchForm.find('input[type="text"]').focus(); 87 },200); 88 } 89 90 /** 91 * Close the search panel 92 * 93 * @param Event e Optional event handler 94 */ 95 function closeSearchPanel(e) { 96 97 if (headerSearchPanelIsClosing) { 98 return; 99 } 100 101 if (typeof e !== 'undefined') { 102 e.preventDefault(); 103 e.stopPropagation(); 104 } 105 106 headerSearchPanelIsClosing = true; 107 headerSearchForm.removeClass('is_open'); 108 109 setTimeout(function() { 110 headerSearchPanelIsClosing = false; 111 headerSearchInput.val(''); 112 },300) 113 } 114 115 // Modify the Chart.js display options used by UsageStats plugin 116 document.addEventListener('usageStatsChartOptions.pkp', function(e) { 117 e.chartOptions.elements.line.backgroundColor = 'rgba(0, 122, 178, 0.6)'; 118 e.chartOptions.elements.rectangle.backgroundColor = 'rgba(0, 122, 178, 0.6)'; 119 }); 120 121 // Initialize tag-it components 122 // 123 // The tag-it component is used during registration for the user to enter 124 // their review interests. See: /templates/frontend/pages/userRegister.tpl 125 if (typeof $.fn.tagit !== 'undefined') { 126 $('.tag-it').each(function() { 127 var autocomplete_url = $(this).data('autocomplete-url'); 128 $(this).tagit({ 129 fieldName: $(this).data('field-name'), 130 allowSpaces: true, 131 autocomplete: { 132 source: function(request, response) { 133 $.ajax({ 134 url: autocomplete_url, 135 data: {term: request.term}, 136 dataType: 'json', 137 success: function(jsonData) { 138 if (jsonData.status == true) { 139 response(jsonData.content); 140 } 141 } 142 }); 143 }, 144 }, 145 }); 146 }); 147 148 /** 149 * Determine if the user has opted to register as a reviewer 150 * 151 * @see: /templates/frontend/pages/userRegister.tpl 152 */ 153 function isReviewerSelected() { 154 var group = $('#reviewerOptinGroup').find('input'); 155 var is_checked = false;
156 group.each(function() { 157 if ($(this).is(':checked')) { 158 is_checked = true; 159 return false; 160 } 161 }); 162 163 return is_checked; 164 } 165 166 /** 167 * Reveal the reviewer interests field on the registration form when a 168 * user has opted to register as a reviewer 169 * 170 * @see: /templates/frontend/pages/userRegister.tpl 171 */ 172 function reviewerInterestsToggle() { 173 var is_checked = isReviewerSelected(); 174 if (is_checked) { 175 $('#reviewerInterests').addClass('is_visible'); 176 } else { 177 $('#reviewerInterests').removeClass('is_visible'); 178 } 179 } 180 181 // Update interests on page load and when the toggled is toggled 182 reviewerInterestsToggle(); 183 $('#reviewerOptinGroup input').click(reviewerInterestsToggle); 184 } 185 186})(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.