1(function ($) { 2 'use strict'; 3 4 /* ===================================================== 5 UTILITY: escape HTML 6 ===================================================== */ 7 function esc(str) { 8 return $('<div>').text(String(str)).html(); 9 } 10 11 /* ===================================================== 12 APRI EDITOR INLINE (click sulla matita) 13 ===================================================== */ 14 $(document).on('click', '.ld-edit-btn', function (e) { 15 e.preventDefault(); 16 17 var $btn = $(this); 18 var $field = $btn.closest('.ld-field'); 19 20 // Il key corretto sta SEMPRE sul bottone (non sul div padre) 21 // perché per il repeater il div ha data-key="ld_idea" 22 // mentre il bottone ha data-key="ld_idea__0__id_idea_detail" 23 var key = $btn.attr('data-key'); 24 var type = $btn.attr('data-type'); 25 var postId = $btn.attr('data-post'); 26 27 var $val = $field.find('.ld-field-value').first(); 28 var $wrap = $field.find('.ld-edit-wrap').first(); 29 30 // Già aperto â ignora 31 if ($wrap.is(':visible')) return; 32 33 // Memorizziamo key/type/postId sul wrap così il salvataggio li ritrova 34 $wrap.attr('data-key', key); 35 $wrap.attr('data-type', type); 36 $wrap.attr('data-post', postId); 37 38 // Per select e checkbox recuperiamo le scelte da ACF via AJAX 39 if (type === 'select' || type === 'checkbox') { 40 // Per select/checkbox il key sul bottone coincide con il campo ACF 41 var acfKey = $field.attr('data-key'); 42 $.post(ldAjax.url, { 43 action : 'ld_get_acf_choices', 44 nonce : ldAjax.nonce, 45 key : acfKey, 46 post_id: postId 47 }, function (res) { 48 if (res.success) { 49 buildEditor($field, $val, $wrap, key, type, postId, res.data.choices, res.data.current); 50 } else { 51 alert('Errore nel recupero delle scelte: ' + (res.data || '')); 52 } 53 }).fail(function () { 54 alert('Errore di rete nel recupero delle scelte.'); 55 }); 56 57 } else if (type === 'wysiwyg') { 58 buildEditor($field, $val, $wrap, key, type, postId, [], $val.html()); 59 60 } else { 61 buildEditor($field, $val, $wrap, key, type, postId, [], $val.text().trim()); 62 } 63 }); 64 65 /* ===================================================== 66 COSTRUISCE IL FORM DI EDITING 67 ===================================================== */ 68 function buildEditor($field, $val, $wrap, key, type, postId, choices, currentVal) { 69 var html = ''; 70 71 switch (type) { 72 73 case 'select': 74 html = '<select class="ld-input">'; 75 $.each(choices, function (optVal, optLabel) { 76 var sel = (optVal === currentVal || optLabel === currentVal) ? ' selected' : ''; 77 html += '<option value="' + esc(optVal) + '"' + sel + '>' + esc(optLabel) + '</option>'; 78 }); 79 html += '</select>'; 80 break; 81 82 case 'checkbox': 83 var currentArr = currentVal ? currentVal.split(' / ').map(function (s) { return s.trim(); }) : []; 84 html = '<div class="ld-checkboxes">'; 85 $.each(choices, function (optVal, optLabel) { 86 var chk = (currentArr.indexOf(optLabel) !== -1 || currentArr.indexOf(optVal) !== -1) ? ' checked' : ''; 87 html += '<label style="display:block;margin:2px 0">' 88 + '<input type="checkbox" class="ld-input" value="' + esc(optVal) + '"' + chk + '> ' 89 + esc(optLabel) 90 + '</label>'; 91 }); 92 html += '</div>'; 93 break; 94 95 case 'wysiwyg': 96 html = '<textarea class="ld-input" rows="6" style="width:100%;box-sizing:border-box">' + currentVal + '</textarea>'; 97 break; 98 99 case 'name_surname': 100 var parts = currentVal.split(' '); 101 var nome = parts[0] || ''; 102 var cognome = parts.slice(1).join(' ') || ''; 103 html = 'Nome: <input type="text" class="ld-input-name" value="' + esc(nome) + '" placeholder="Nome" style="width:110px"> '; 104 html += 'Cognome: <input type="text" class="ld-input-surname" value="' + esc(cognome) + '" placeholder="Cognome" style="width:110px">'; 105 break; 106 107 case 'number': 108 html = '<input type="number" class="ld-input" value="' + esc(currentVal) + '" style="width:80px">'; 109 break; 110 111 case 'email': 112 html = '<input type="email" class="ld-input" value="' + esc(currentVal) + '" style="width:200
112px">'; 113 break; 114 115 default: // text, repeater_text 116 html = '<input type="text" class="ld-input" value="' + esc(currentVal) + '" style="min-width:180px">'; 117 break; 118 } 119 120 html += ' <button class="ld-save-btn">Salva</button>'; 121 html += ' <button class="ld-cancel-btn">Annulla</button>'; 122 html += ' <span class="ld-notice"></span>'; 123 124 $val.hide(); 125 $wrap.html(html).show(); 126 $wrap.find('input, select, textarea').first().focus(); 127 } 128 129 /* ===================================================== 130 ANNULLA 131 ===================================================== */ 132 $(document).on('click', '.ld-cancel-btn', function () { 133 var $wrap = $(this).closest('.ld-edit-wrap'); 134 var $field = $(this).closest('.ld-field'); 135 $wrap.hide().html(''); 136 $field.find('.ld-field-value').first().show(); 137 }); 138 139 /* ===================================================== 140 SALVA (AJAX) 141 â key/type/postId letti dal wrap (impostati all'apertura) 142 ===================================================== */ 143 $(document).on('click', '.ld-save-btn', function () { 144 var $btn = $(this); 145 var $wrap = $btn.closest('.ld-edit-wrap'); 146 var $field = $btn.closest('.ld-field'); 147 var $val = $field.find('.ld-field-value').first(); 148 149 // Leggiamo dal wrap, non dal field, così funziona anche per il repeater 150 var key = $wrap.attr('data-key'); 151 var type = $wrap.attr('data-type'); 152 var postId = $wrap.attr('data-post'); 153 var $notice = $wrap.find('.ld-notice'); 154 var value; 155 156 switch (type) { 157 case 'checkbox': 158 value = []; 159 $wrap.find('input[type=checkbox]:checked').each(function () { 160 value.push($(this).val()); 161 }); 162 break; 163 164 case 'name_surname': 165 value = { 166 nome : $wrap.find('.ld-input-name').val().trim(), 167 cognome: $wrap.find('.ld-input-surname').val().trim() 168 }; 169 break; 170 171 default: 172 value = $wrap.find('.ld-input').val(); 173 break; 174 } 175 176 $btn.prop('disabled', true); 177 $wrap.find('.ld-cancel-btn').prop('disabled', true); 178 $notice.text('Salvataggioâ¦').removeClass('ok err'); 179 180 $.post(ldAjax.url, { 181 action : 'ld_save_field', 182 nonce : ldAjax.nonce, 183 key : key, 184 type : type, 185 post_id: postId, 186 value : value 187 }, function (res) { 188 $btn.prop('disabled', false); 189 $wrap.find('.ld-cancel-btn').prop('disabled', false); 190 191 if (res.success) { 192 $notice.text('â Salvato').addClass('ok'); 193 194 var display = res.data.display; 195 if (type === 'wysiwyg') { 196 $val.html(display); 197 } else if (type === 'email') { 198 $val.html('<a href="mailto:' + esc(display) + '">' + esc(display) + '</a>'); 199 } else if (type === 'name_surname') { 200 $val.text(display); 201 $('h1.ld-field .ld-field-value').text(display); 202 } else { 203 $val.text(display); 204 } 205 206 setTimeout(function () { 207 $wrap.hide().html(''); 208 $val.show(); 209 }, 800); 210 211 } else { 212 $notice.text('â ' + (res.data || 'Errore sconosciuto')).addClass('err'); 213 } 214 215 }).fail(function (xhr) { 216 $btn.prop('disabled', false); 217 $wrap.find('.ld-cancel-btn').prop('disabled', false); 218 $notice.text('â Errore di rete (' + xhr.status + ')').addClass('err'); 219 }); 220 }); 221 222 /* ===================================================== 223 INVIO / ESC su input singoli 224 ===================================================== */ 225 $(document).on('keydown', '.ld-edit-wrap input', function (e) { 226 if (e.key === 'Enter') { 227 e.preventDefault(); 228 $(this).closest('.ld-edit-wrap').find('.ld-save-btn').trigger('click'); 229 } 230 if (e.key === 'Escape') { 231 $(this).closest('.ld-edit-wrap').find('.ld-cancel-btn').trigger('click'); 232 } 233 });
234 235 /* ===================================================== 236 REPEATER â ELIMINA RIGA 237 ===================================================== */ 238 $(document).on('click', '.ld-repeater-delete-btn', function () { 239 var $btn = $(this); 240 var $row = $btn.closest('.ld-field-repeater'); 241 var postId = $btn.attr('data-post'); 242 var index = $btn.attr('data-index'); 243 244 if (!confirm('Eliminare questa idea?')) return; 245 246 $btn.prop('disabled', true); 247 248 $.post(ldAjax.url, { 249 action : 'ld_repeater_delete', 250 nonce : ldAjax.nonce, 251 post_id: postId, 252 index : index 253 }, function (res) { 254 if (res.success) { 255 $row.fadeOut(200, function () { 256 $(this).remove(); 257 reindexRepeater(); 258 }); 259 } else { 260 alert('Errore eliminazione: ' + (res.data || '')); 261 $btn.prop('disabled', false); 262 } 263 }).fail(function (xhr) { 264 alert('Errore di rete (' + xhr.status + ')'); 265 $btn.prop('disabled', false); 266 }); 267 }); 268 269 /* ===================================================== 270 REPEATER â AGGIUNGI RIGA 271 ===================================================== */ 272 $(document).on('click', '.ld-repeater-add-btn', function () { 273 var $btn = $(this); 274 var $addWrap = $btn.closest('.ld-repeater-add-wrap'); 275 var $input = $addWrap.find('.ld-repeater-new-input'); 276 var $notice = $addWrap.find('.ld-repeater-notice'); 277 var postId = $btn.attr('data-post'); 278 var detail = $input.val().trim(); 279 280 if (detail === '') { 281 $notice.text("Inserisci il testo dell'idea.").removeClass('ok').addClass('err'); 282 $input.focus(); 283 return; 284 } 285 286 $btn.prop('disabled', true); 287 $notice.text('Salvataggioâ¦').removeClass('ok err'); 288 289 $.post(ldAjax.url, { 290 action : 'ld_repeater_add', 291 nonce : ldAjax.nonce, 292 post_id: postId, 293 detail : detail 294 }, function (res) { 295 $btn.prop('disabled', false); 296 297 if (res.success) { 298 $notice.text('â Aggiunta').addClass('ok'); 299 $input.val(''); 300 301 var newIndex = res.data.index; 302 var newText = res.data.detail; 303 304 var pencilSvg = '<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"/><path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"/></svg>'; 305 var trashSvg = '<svg xmlns="http://www.w3.org/2000/svg" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="3 6 5 6 21 6"/><path d="M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6"/><path d="M10 11v6"/><path d="M14 11v6"/><path d="M9 6V4a1 1 0 0 1 1-1h4a1 1 0 0 1 1 1v2"/></svg>'; 306 307 var $newRow = $( 308 '<div class="ld-field ld-field-repeater"' + 309 ' data-key="ld_idea"' + 310 ' data-type="repeater_text"' + 311 ' data-post="' + esc(postId) + '"' + 312 ' data-index="' + esc(newIndex) + '">' + 313 '<span class="ld-field-value">' + esc(newText) + '</span>' + 314 '<button class="ld-edit-btn"' + 315 ' data-key="ld_idea__' + newIndex + '__id_idea_detail"' + 316 ' data-type="repeater_text"' + 317 ' data-post="' + esc(postId) + '"' + 318 ' title="Modifica" aria-label="Modifica campo">' + 319 pencilSvg + 320 '</button>' + 321 '<button class="ld-repeater-delete-btn"' + 322 ' data-post="' + esc(postId) + '"' + 323 ' data-index="' + esc(newIndex) + '"' + 324 ' title="Elimina idea" aria-label="Elimina idea">' + 325 trashSvg + 326 '</button>' + 327 '<span class="ld-edit-wrap" style="display:none;"></span>' + 328 '</div>' 329 ); 330 331 $addWrap.before($newRow); 332 333 setTimeout(function () { $notice.text(''); }, 2000); 334 335 } else { 336 $notice.text('â ' + (res.data || 'Errore')).addClass('err'); 337 } 338 }).fail(function (xhr) { 339 $btn.prop('disabled', false); 340 $notice.text('â Errore di rete (' + xhr.status + ')').addClass('err'); 341 }); 342 });
343 344 // Enter sul campo nuova idea 345 $(document).on('keydown', '.ld-repeater-new-input', function (e) { 346 if (e.key === 'Enter') { 347 e.preventDefault(); 348 $(this).closest('.ld-repeater-add-wrap').find('.ld-repeater-add-btn').trigger('click'); 349 } 350 }); 351 352 /* ===================================================== 353 REPEATER â reindicizza dopo eliminazione 354 Usa .attr() invece di .data() per evitare la cache jQuery 355 ===================================================== */ 356 function reindexRepeater() { 357 $('.ld-repeater-wrap .ld-field-repeater').each(function (i) { 358 var $row = $(this); 359 $row.attr('data-index', i); 360 $row.find('.ld-edit-btn').attr('data-key', 'ld_idea__' + i + '__id_idea_detail'); 361 $row.find('.ld-repeater-delete-btn').attr('data-index', i); 362 }); 363 } 364 365})(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.