PluginProbe ʕ •ᴥ•ʔ
Admin Help Docs / trunk
Admin Help Docs vtrunk
2.0.1.1 trunk 1.4.3.2 2.0.0 2.0.0.1 2.0.0.2 2.0.1
admin-help-docs / inc / tabs / js / admin-menu.js
admin-help-docs / inc / tabs / js Last commit date
admin-menu.js 3 months ago documentation.js 3 months ago import.js 3 months ago settings.js 3 months ago support.js 3 months ago
admin-menu.js
218 lines
1 jQuery( document ).ready( function( $ ) {
2
3 // Drag-and-drop sorting
4 let draggedItem = null;
5 let placeholder = $( '<li class="helpdocs-sorter-placeholder"></li>' );
6
7 let scrollAnimationFrame = null;
8 let pointerY = 0;
9
10 $( document ).on( 'dragstart', '.helpdocs-sorter-item', function ( e ) {
11 draggedItem = this;
12 $( this ).addClass( 'is-dragging' );
13 $( this ).after( placeholder );
14 e.originalEvent.dataTransfer.effectAllowed = 'move';
15 } );
16
17 $( document ).on( 'dragend', '.helpdocs-sorter-item', function ( ) {
18 $( this ).removeClass( 'is-dragging' );
19 if ( draggedItem ) { placeholder.replaceWith( draggedItem ); }
20 cancelAnimationFrame( scrollAnimationFrame );
21 scrollAnimationFrame = null;
22 markDirty();
23 } );
24
25 $( document ).on( 'dragover', '.helpdocs-sorter-item', function ( e ) {
26 e.preventDefault();
27 pointerY = e.originalEvent.clientY;
28 if ( this === draggedItem ) { return; }
29 const bounding = this.getBoundingClientRect();
30 const offset = pointerY - bounding.top;
31 const middle = bounding.height / 2;
32 if ( offset > middle ) { $( this ).after( placeholder ); }
33 else { $( this ).before( placeholder ); }
34 startAutoScroll();
35 } );
36
37 function startAutoScroll() {
38 if ( scrollAnimationFrame ) { return; }
39 function step ( ) {
40 const margin = 80;
41 const speed = 12;
42 if ( pointerY < margin ) { window.scrollBy( 0, -speed ); }
43 else if ( pointerY > window.innerHeight - margin ) { window.scrollBy( 0, speed ); }
44 scrollAnimationFrame = requestAnimationFrame( step );
45 }
46 step();
47 }
48
49 // Dirty state tracking
50 const saveReminder = $( '#helpdocs-save-reminder' );
51 let isDirty = false;
52
53 function markDirty() {
54 if ( ! isDirty ) {
55 isDirty = true;
56 saveReminder.fadeIn( 150 );
57 $( '#helpdocs-save-status' ).remove();
58 }
59 }
60
61 function clearDirty() {
62 isDirty = false;
63 saveReminder.hide();
64 }
65
66 $( window ).on( 'beforeunload', function( e ) {
67 if( isDirty ){
68 e.preventDefault();
69 e.returnValue = '';
70 return '';
71 }
72 });
73
74 $( document ).on( 'change input', '.helpdocs-settings-grid [name]', function() {
75 markDirty();
76 });
77
78 // Saving
79 const $saveButton = $( '#helpdocs-subheader .tab-button' );
80 const originalText = $saveButton.text();
81 let savingInterval;
82
83 // Start animated "Saving..." in browser tab
84 function startSavingTitle() {
85 const originalTitle = document.title;
86 let dots = 0;
87
88 document.title = 'Saving'; // immediate first update
89
90 savingInterval = setInterval( function() {
91 dots = (dots + 1) % 4; // cycles 0 → 3
92 document.title = 'Saving' + '.'.repeat(dots);
93 }, 500 );
94
95 return originalTitle;
96 }
97
98 // Stop animation and restore tab title
99 function stopSavingTitle( originalTitle ) {
100 clearInterval( savingInterval );
101 document.title = originalTitle;
102 }
103
104 function showSaving() {
105 $saveButton.prop( 'disabled', true ).html( '<span class="dashicons dashicons-update spin"></span> Saving...' );
106 $( '#helpdocs-save-status' ).remove();
107 }
108
109 function showResult( message, success = true ) {
110 $saveButton.prop( 'disabled', false ).text( originalText );
111 const $status = $( '<span id="helpdocs-save-status"></span>' ).text( message );
112 $status.css({
113 marginLeft: '10px',
114 color: success ? 'green' : 'red',
115 fontWeight: 'bold'
116 });
117 $saveButton.after( $status );
118 }
119
120 function gatherSettings() {
121 const data = {};
122 $( '.helpdocs-settings-grid [name]' ).each( function() {
123 const $field = $( this );
124 let val;
125
126 if ( $field.attr( 'type' ) === 'checkbox' ) {
127 if ( $field.is( ':checkbox' ) && $field.attr( 'name' ).endsWith( '[]' ) ) {
128 val = $( '[name="' + $field.attr( 'name' ) + '"]:checked' ).map( function() { return this.value; } ).get();
129 } else {
130 val = $field.is( ':checked' ) ? 1 : 0;
131 }
132 } else {
133 val = $field.val();
134 }
135
136 let key = $field.attr( 'name' ).replace( /\[\]$/, '' );
137 data[ key ] = val;
138 });
139 return data;
140 }
141
142 function saveSettings() {
143 const settings = gatherSettings();
144 const menuOrder = [];
145 $( '.helpdocs-sorter-item' ).each( function() {
146 menuOrder.push( $( this ).attr( 'data-value' ) );
147 } );
148 const originalTitle = startSavingTitle();
149 showSaving();
150
151 $.ajax({
152 url: ajaxurl,
153 method: 'POST',
154 dataType: 'json',
155 data: {
156 action: 'helpdocs_save_menu_order',
157 nonce: helpdocs_admin_menu.nonce,
158 settings: settings,
159 menu_order: menuOrder
160 },
161 success: function( response ) {
162 stopSavingTitle( originalTitle );
163 if ( response.success ) {
164 showResult( 'Settings saved successfully.' );
165 clearDirty();
166 } else {
167 showResult( response.data || 'Error saving settings. Please try again.', false );
168 }
169
170 setTimeout( function() {
171 location.reload();
172 }, 1000 );
173 },
174 error: function() {
175 stopSavingTitle( originalTitle );
176 showResult( 'Error saving settings. Please try again.', false );
177 }
178 });
179 }
180
181 $saveButton.on( 'click', saveSettings );
182
183 $( document ).on( 'keydown', function( e ) {
184 if ( ( e.ctrlKey || e.metaKey ) && e.key.toLowerCase() === 's' ) {
185 e.preventDefault();
186 saveSettings();
187 }
188 } );
189
190 // Colorize Separators
191 function updateSeparatorColor() {
192 var enabled = $( '#helpdocs_field_colorize_separators input' ).is( ':checked' );
193 var color = $( '#helpdocs_field_color_admin_menu_sep input' ).val();
194
195 if ( enabled ) {
196 $( 'body' ).addClass( 'helpdocs-separator-enabled' );
197 $( '#adminmenu div.separator' ).css( 'border-top-color', color );
198 } else {
199 $( 'body' ).removeClass( 'helpdocs-separator-enabled' );
200 }
201 }
202
203 // Listen for changes
204 $( document ).on( 'change', '#helpdocs_field_colorize_separators input, #helpdocs_field_color_admin_menu_sep input', function() {
205 updateSeparatorColor();
206 console.log( 'Separator color updated.' );
207 } );
208
209 // Show the sublabels
210 $( document ).on( 'change', '#helpdocs_field_show_menu_item_slugs input', function () {
211 if ( $( this ).is( ':checked' ) ) {
212 $( 'html' ).addClass( 'helpdocs-view-sublabels' );
213 } else {
214 $( 'html' ).removeClass( 'helpdocs-view-sublabels' );
215 }
216 } );
217
218 } );