xref: /template/writr/script.js (revision a4ff460312082e5543c3b264d467682eb9ea836a)
1/* DOKUWIKI:include js/skip-link-focus-fix.js */
2
3jQuery(document).ready(function() {
4    /*
5     * Click to toggle sidebar.
6     */
7    function toggleSidebar() {
8        jQuery( '#writr__sidebar' ).on( 'click', '#writr__sidebar-toggle', function( e ) {
9            e.preventDefault();
10            jQuery( 'html, body' ).scrollTop( 0 );
11            jQuery( this ).toggleClass( 'open' );
12            jQuery( 'body' ).toggleClass( 'sidebar-closed' );
13            jQuery( '#writr__secondary' ).resize();
14        } );
15    }
16
17    /**
18     * Handles toggling the navigation menu for small screens.
19     */
20    function toggleNavigation() {
21        var $container = jQuery('#writr__site-navigation');
22        if (!$container.length) return;
23        var $button = jQuery('.menu-toggle', $container);
24        if (!$button.length) return;
25        var $menu = jQuery('ul', $container);
26        if (!$menu.length) {
27            $menu.hide();
28            return;
29        }
30        $button.click(function(){
31            $container.toggleClass('toggled');
32        });
33    }
34
35    /*
36     * A function to enable/disable a dropdown submenu.
37     */
38    function toggleSubmenu() {
39        jQuery( '.main-navigation .node > div > a' ).append( '<span class="dropdown-icon" />' );
40        jQuery( '#writr__site-navigation' ).on( 'click', '.dropdown-icon', function( e ) {
41            e.preventDefault();
42            jQuery( this ).toggleClass( 'open' );
43            if ( jQuery( this ).hasClass( 'open' ) ) {
44                jQuery( this ).parent().parent().next( 'ul' ).show();
45            } else {
46                jQuery( this ).parent().parent().next( 'ul' ).hide();
47            }
48        } );
49    }
50
51    /*
52     * Close TOC by default
53     */
54    function closeToc() {
55        var $toc = jQuery('#dw__toc .toggle');
56        if($toc.length) {
57            $toc[0].setState(-1);
58        }
59    }
60
61    /*
62     * Change search submit input to submit button to make it easier to style
63     * @deprecated since Detritus
64     */
65    function changeSearchInput() {
66        var $searchForm = jQuery('.search-form > form > div');
67        var $searchButton = jQuery('input[type="submit"]', $searchForm).detach();
68        var title = $searchButton.attr('title');
69        var value = $searchButton.val();
70        $searchForm.append('<button type="submit" title="'+title+'">'+value+'</button>');
71    }
72
73    /*
74     * Enable add new page dropdown
75     */
76    function enableAddNewPage() {
77        jQuery('.action.AddNewPage').click(function(event) {
78            event.preventDefault();
79            const button = jQuery(this);
80            jQuery('.addnewpage').toggle(0,function(){
81                // set aria-expanded attribute based on visibility
82                button.attr('aria-expanded', jQuery(this).is(':visible'));
83            });
84        });
85
86        jQuery(document).click(function(event) {
87            if (!jQuery(event.target).closest('.action.AddNewPage, .addnewpage').length) {
88                jQuery('.addnewpage').hide();
89            }
90        });
91    }
92
93    /*
94     * Enable translation dropdown
95     */
96    function enableTranslation() {
97        jQuery('.action.Translation').click(function(event) {
98            event.preventDefault();
99            const button = jQuery(this);
100            jQuery('.plugin_translation').toggle(0,function(){
101                // set aria-expanded attribute based on visibility
102                button.attr('aria-expanded', jQuery(this).is(':visible'));
103            });
104        });
105
106        jQuery(document).click(function(event) {
107            if (!jQuery(event.target).closest('.action.Translation, .plugin_translation').length) {
108                jQuery('.plugin_translation').hide();
109            }
110        });
111    }
112
113    /*
114     * Enable Toolbar Dropdowns
115     */
116    function enableToolbarDropdowns() {
117        jQuery('#writr__toolbar .hook .node').each(function() {
118            const dropdown = jQuery(this);
119            dropdown.find('div.li').click(function(event) {
120                const trigger = jQuery(this);
121                dropdown.find('> ul').toggle(0,function(){
122                    trigger.attr('aria-expanded', jQuery(this).is(':visible'));
123                });
124
125                // Close dropdown when clicking outside
126                jQuery(document).on('click.dropdown', function(e) {
127                    if (!dropdown.is(e.target) && dropdown.has(e.target).length === 0) {
128                        dropdown.find('> ul').hide();
129                        trigger.attr('aria-expanded', 'false');
130                        jQuery(document).off('click.dropdown');
131                    }
132                });
133            });
134        });
135    }
136
137    /*
138     * Enable Collapse
139     */
140    function enableCollapse() {
141        jQuery('[data-toggle="collapse"]').click(function(event){
142            event.preventDefault();
143            const trigger = jQuery(this);
144            const target = jQuery(trigger.attr('data-target'));
145            target.slideToggle('fast',function(){
146                // set aria-expanded attribute based on visibility
147                trigger.attr('aria-expanded', target.is(':visible'));
148            });
149        });
150    }
151
152    /*
153     * Enable Dropdowns
154     */
155    function enableDropdowns() {
156        jQuery('.dropdown').each(function() {
157            const dropdown = jQuery(this);
158            dropdown.find('[data-toggle="dropdown"]').click(function(event) {
159                event.preventDefault();
160                const button = jQuery(this);
161                dropdown.find('.dropdown-menu').toggle(0,function(){
162                    button.attr('aria-expanded', jQuery(this).is(':visible'));
163                });
164
165                // Close dropdown when clicking outside
166                jQuery(document).on('click.dropdown', function(e) {
167                    if (!dropdown.is(e.target) && dropdown.has(e.target).length === 0) {
168                        dropdown.find('> ul').hide();
169                        button.attr('aria-expanded', 'false');
170                        jQuery(document).off('click.dropdown');
171                    }
172                });
173            });
174        });
175    }
176
177    /*
178     * Enable Tooltips
179     */
180    function enableTooltips() {
181        jQuery('body.enableTooltips [title]:not(.media):not(img):not([title=""]), body.enableTooltips [alt]:not(.media):not(img):not([alt=""])').each(function() {
182            const element = jQuery(this);
183            const content = element.attr('alt') ? element.attr('alt') : element.attr('title');
184            element.attr('data-tooltip-content', content);
185
186            element.hover(function() {
187                // Prevent default browser tooltip from showing
188                const tooltipType = element.attr('alt') ? 'alt' : 'title';
189                element.removeAttr(tooltipType).attr('data-tooltip-type', tooltipType);
190
191                // Create and append the tooltip
192                const tooltip = jQuery('<div class="tooltip"><div class="tooltip-text">' + content + '</div></div>');
193                jQuery('body').append(tooltip);
194
195                // Calculate and set the position of the tooltip
196                const elementOffset = element.offset();
197                const tooltipWidth = tooltip.outerWidth();
198                const elementWidth = element.outerWidth();
199                const topPosition = elementOffset.top + element.outerHeight() + 10; // Adjust +10 for spacing
200                const leftPosition = elementOffset.left + (elementWidth / 2) - (tooltipWidth / 2);
201
202                tooltip.css({
203                    top: topPosition,
204                    left: leftPosition,
205                    display: 'inline-block'
206                });
207
208            }, function() {
209                // Restore the original attribute and remove the tooltip
210                element.attr(element.attr('data-tooltip-type'), content);
211                jQuery('.tooltip').remove();
212            });
213        });
214    }
215
216    /*
217     * Enable Improved File Input
218     */
219    function enableFileInput() {
220      jQuery('input[type="file"]').on('change', function() {
221        var input = jQuery(this);
222        var label = input.prev('span');
223        var group = input.parent('label');
224        var fileName = input.val().split('\\').pop() || 'No file chosen';
225
226        // Check if a div already exists
227        if (input.next('div').length > 0) {
228            input.next('div').remove();
229        }
230
231        // Create a div after the input
232        var file = jQuery('<div style="text-align:center;width:100%"></div>');
233
234        // Update the text of the file-name span
235        file.prepend(fileName);
236
237        // Add a button to clear the field
238        var button = jQuery('<button type="button" class="tagerror" style="margin-left:4px;padding: 4px 8px;font-size: 80%;"><i class="bi bi-trash"></i></button>').appendTo(file);
239
240        // Add Click event on the button
241        button.click(function(){
242
243          // Clear value
244          input.val('');
245
246          // Remove the file object
247          file.remove();
248
249          // Show input and label
250          label.show();
251          input.show();
252        });
253
254        // Insert the div after the input
255        input.after(file);
256
257        // Hide label & input
258        label.hide();
259        input.hide();
260      });
261    }
262
263    /*
264     * Disable Newlines in Textareas
265     */
266    function disableNewlines() {
267        // Check if "?do=" is present in the URL
268        if (window.location.search.indexOf("?do=") === -1) {
269            jQuery("form").on("submit", function(event) {
270                // Prevent the form from submitting immediately
271                event.preventDefault();
272
273                // Find the textarea and replace newlines with " \\ "
274                var textarea = jQuery(this).find('textarea');
275                textarea.val(textarea.val().replace(/\n/gm, ' \\\\\\ '));
276
277                // After running the function, manually trigger the form submission
278                this.submit();
279            });
280        }
281    }
282
283    /*
284     * Run the functions
285     */
286    jQuery(function(){
287        toggleSidebar();
288        toggleNavigation();
289        toggleSubmenu();
290        closeToc();
291        changeSearchInput();
292        enableAddNewPage();
293        enableTranslation();
294        enableToolbarDropdowns();
295        enableDropdowns();
296        enableTooltips();
297        enableCollapse();
298        enableFileInput();
299    });
300
301    /*
302     * NSPAGES enable multi-line support
303     */
304    jQuery('.nspagesPicturesModeTitle').each(function() {
305        if (jQuery(this).prop('scrollHeight') > 32) {
306            jQuery(this).addClass('multi-line');
307        }
308    });
309});
310