Better domain selector for default settings (#7801)

* Add a better domain selector implementation for default settings

* Add functionality to default_settings copy function
This commit is contained in:
simplecoder732
2026-03-25 13:53:34 -04:00
committed by GitHub
parent 0c4122cb94
commit 68f5e2e38c
2 changed files with 386 additions and 0 deletions

View File

@@ -273,12 +273,14 @@
echo " document.getElementById('btn_copy').style.display = 'none'; \n";
echo " document.getElementById('btn_copy_cancel').style.display = 'inline'; \n";
echo " document.getElementById('target_domain_uuid').style.display = 'inline'; \n";
echo " if (typeof window.sync_domain_search_select_visibility === 'function') { window.sync_domain_search_select_visibility('target_domain_uuid'); }\n";
echo " document.getElementById('btn_paste').style.display = 'inline'; \n";
echo " }";
echo " function hide_domains() {\n";
echo " document.getElementById('action').value = '';\n";
echo " document.getElementById('btn_copy_cancel').style.display = 'none'; \n";
echo " document.getElementById('target_domain_uuid').style.display = 'none'; \n";
echo " if (typeof window.sync_domain_search_select_visibility === 'function') { window.sync_domain_search_select_visibility('target_domain_uuid'); }\n";
echo " document.getElementById('target_domain_uuid').selectedIndex = 0;\n";
echo " document.getElementById('btn_paste').style.display = 'none'; \n";
echo " document.getElementById('btn_copy').style.display = 'inline'; \n";

View File

@@ -734,6 +734,390 @@
}
{/literal}
//domain select: searchable picker
{literal}
(function() {
var domain_cache = null;
var domain_cache_loading = false;
var domain_cache_callbacks = [];
var domain_picker_styles_loaded = false;
function load_domain_picker_styles() {
if (domain_picker_styles_loaded) { return; }
var style = document.createElement('style');
style.type = 'text/css';
style.innerHTML = ""
+ ".domain-search-picker { position: relative; display: inline-block; max-width: 100%; }"
+ ".domain-search-picker .domain-search-input { max-width: 100%; }"
+ ".domain-search-results {"
+ " position: fixed; z-index: 10050; left: 0; top: 0;"
+ " border: 1px solid rgba(0,0,0,.2); border-radius: 4px;"
+ " background: #fff; box-shadow: 0 10px 20px rgba(0,0,0,.12);"
+ " max-height: 260px; overflow-y: auto; display: none;"
+ " box-sizing: border-box; text-align: left;"
+ "}"
+ ".domain-search-result-item {"
+ " padding: 6px 10px; cursor: pointer; line-height: 1.3;"
+ "}"
+ ".domain-search-result-item:hover,"
+ ".domain-search-result-item.active {"
+ " background: #f1f4f8;"
+ "}"
+ ".domain-search-result-name { display: block; }"
+ ".domain-search-result-description {"
+ " display: block; opacity: 0.75; font-size: 0.92em; margin-top: 1px;"
+ "}"
+ ".domain-search-empty {"
+ " padding: 8px 10px; opacity: 0.85;"
+ "}";
document.head.appendChild(style);
domain_picker_styles_loaded = true;
}
function fetch_domains(callback) {
if (domain_cache !== null) {
callback(domain_cache);
return;
}
domain_cache_callbacks.push(callback);
if (domain_cache_loading) { return; }
domain_cache_loading = true;
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState === 4) {
var results = [];
if (this.status === 200) {
try { results = JSON.parse(this.responseText) || []; }
catch (error) { results = []; }
}
domain_cache = results;
domain_cache_loading = false;
while (domain_cache_callbacks.length) {
domain_cache_callbacks.shift()(domain_cache);
}
}
};
xhttp.open("GET", "/core/domains/domain_json.php?{/literal}{$domain_json_token_name}={$domain_json_token_hash}{literal}", true);
xhttp.send();
}
function init_domain_search_select(select) {
if (!select || select.dataset.domainSearchInit === 'true') { return; }
select.dataset.domainSearchInit = 'true';
var option_values = {};
var option_order = [];
var global_option = null;
for (var o = 0; o < select.options.length; o++) {
var option = select.options[o];
var option_text = (option.text || option.innerText || '').trim();
if (option.value === '') {
if (!option.disabled && option_text !== '') {
global_option = { domain_uuid: '', domain_name: option_text };
}
continue;
}
option_values[option.value] = option_text;
option_order.push(option.value);
}
if (option_order.length === 0) { return; }
var picker = document.createElement('div');
picker.className = 'domain-search-picker';
var input = document.createElement('input');
input.type = 'text';
input.className = 'formfld domain-search-input';
input.placeholder = 'Search domains...';
var results = document.createElement('div');
results.className = 'domain-search-results';
results.setAttribute('role', 'listbox');
picker.appendChild(input);
select.parentNode.insertBefore(picker, select.nextSibling);
document.body.appendChild(results);
select.style.position = 'absolute';
select.style.left = '-10000px';
select.style.width = '1px';
select.style.height = '1px';
select.style.opacity = '0';
select.style.pointerEvents = 'none';
select.setAttribute('tabindex', '-1');
if (select.id) {
picker.id = select.id + '_domain_search_picker';
}
var dataset = [];
var active_index = -1;
var current_items = [];
function get_selected_label() {
if (select.selectedIndex > -1) {
var selected_option = select.options[select.selectedIndex];
if (selected_option && selected_option.value !== '') {
return selected_option.text || selected_option.innerText || '';
}
}
return '';
}
function sync_input_to_select() {
input.value = get_selected_label();
}
// Results panel is on document.body; match .formfld / theme input typography
function sync_results_typography_from_input() {
var cs = window.getComputedStyle(input);
results.style.fontFamily = cs.fontFamily;
results.style.fontSize = cs.fontSize;
results.style.fontWeight = cs.fontWeight;
results.style.fontStyle = cs.fontStyle;
results.style.lineHeight = cs.lineHeight;
results.style.letterSpacing = cs.letterSpacing;
results.style.color = cs.color;
}
function position_results_panel() {
if (results.style.display === 'none' || results.style.display === '') { return; }
var rect = input.getBoundingClientRect();
var vw = window.innerWidth || document.documentElement.clientWidth;
var vh = window.innerHeight || document.documentElement.clientHeight;
var panel_width = Math.min(Math.max(rect.width, 160), vw - 16);
var left = rect.left;
if (left + panel_width > vw - 8) { left = Math.max(8, vw - panel_width - 8); }
else if (left < 8) { left = 8; }
results.style.left = left + 'px';
var max_h = Math.min(260, Math.max(120, vh - 16));
results.style.maxHeight = max_h + 'px';
results.style.width = panel_width + 'px';
var top = rect.bottom + 2;
var h = results.offsetHeight || 1;
if (top + h > vh - 8 && rect.top > h + 8) {
top = rect.top - h - 2;
}
if (top < 8) { top = 8; }
results.style.top = top + 'px';
}
function close_results() {
active_index = -1;
results.style.display = 'none';
results.innerHTML = '';
}
function open_results() {
results.style.display = 'block';
}
function score_item(item, query) {
if (!query) { return 1; }
var score = 0;
var name = item.domain_name_lc;
var description = item.domain_description_lc;
if (name === query) { score += 1000; }
if (name.indexOf(query) === 0) { score += 500; }
else if (name.indexOf(query) > -1) { score += 300; }
if (description && description.indexOf(query) > -1) { score += 100; }
return score;
}
function render_results() {
sync_results_typography_from_input();
var query = (input.value || '').toLowerCase().trim();
var matches = [];
if (global_option !== null) {
if (!query || global_option.domain_name.toLowerCase().indexOf(query) > -1) {
matches.push({
domain_uuid: '',
domain_name: global_option.domain_name,
domain_name_lc: global_option.domain_name.toLowerCase(),
domain_description: '',
domain_description_lc: '',
score: query ? 800 : 2
});
}
}
for (var i = 0; i < dataset.length; i++) {
var score = score_item(dataset[i], query);
if (score > 0) {
dataset[i].score = score;
matches.push(dataset[i]);
}
}
matches.sort(function(a, b) {
if (b.score !== a.score) { return b.score - a.score; }
return a.domain_name_lc.localeCompare(b.domain_name_lc);
});
current_items = matches.slice(0, 50);
results.innerHTML = '';
active_index = current_items.length > 0 ? 0 : -1;
if (current_items.length === 0) {
var empty = document.createElement('div');
empty.className = 'domain-search-empty';
empty.innerText = 'No matching domains';
results.appendChild(empty);
open_results();
window.requestAnimationFrame(position_results_panel);
return;
}
for (var r = 0; r < current_items.length; r++) {
var row = document.createElement('div');
row.className = 'domain-search-result-item' + (r === active_index ? ' active' : '');
row.setAttribute('data-index', r);
var name = document.createElement('span');
name.className = 'domain-search-result-name';
name.innerText = current_items[r].domain_name;
row.appendChild(name);
if (current_items[r].domain_description) {
var desc = document.createElement('span');
desc.className = 'domain-search-result-description';
desc.innerText = current_items[r].domain_description;
row.appendChild(desc);
}
results.appendChild(row);
}
open_results();
window.requestAnimationFrame(position_results_panel);
}
function update_active_row() {
var rows = results.querySelectorAll('.domain-search-result-item');
for (var i = 0; i < rows.length; i++) {
rows[i].classList.toggle('active', i === active_index);
}
}
function select_value(domain_uuid) {
select.value = domain_uuid;
select.dispatchEvent(new Event('change', { bubbles: true }));
sync_input_to_select();
close_results();
}
results.addEventListener('mousedown', function(event) {
var row = event.target.closest('.domain-search-result-item');
if (!row) { return; }
event.preventDefault();
var index = parseInt(row.getAttribute('data-index'), 10);
if (!isNaN(index) && current_items[index]) {
select_value(current_items[index].domain_uuid);
}
});
input.addEventListener('focus', function() {
render_results();
});
input.addEventListener('input', function() {
render_results();
});
input.addEventListener('keydown', function(event) {
if (results.style.display !== 'block') {
if (event.key === 'ArrowDown' || event.key === 'ArrowUp') {
render_results();
event.preventDefault();
}
return;
}
if (event.key === 'ArrowDown') {
if (active_index < current_items.length - 1) { active_index++; }
update_active_row();
event.preventDefault();
}
else if (event.key === 'ArrowUp') {
if (active_index > 0) { active_index--; }
update_active_row();
event.preventDefault();
}
else if (event.key === 'Enter') {
if (active_index > -1 && current_items[active_index]) {
select_value(current_items[active_index].domain_uuid);
event.preventDefault();
}
}
else if (event.key === 'Escape') {
close_results();
}
});
select.addEventListener('change', function() {
sync_input_to_select();
});
function sync_picker_visibility() {
var hide = window.getComputedStyle(select).display === 'none';
picker.style.display = hide ? 'none' : 'inline-block';
if (hide) { close_results(); }
}
sync_picker_visibility();
select._domainSearchSyncVisibility = sync_picker_visibility;
function on_reposition_results() {
if (results.style.display === 'block') { position_results_panel(); }
}
window.addEventListener('scroll', on_reposition_results, true);
window.addEventListener('resize', on_reposition_results);
document.addEventListener('mousedown', function(event) {
if (!picker.contains(event.target) && !results.contains(event.target)) {
close_results();
}
});
fetch_domains(function(domains) {
var domains_by_uuid = {};
for (var i = 0; i < domains.length; i++) {
domains_by_uuid[domains[i].domain_uuid] = domains[i];
}
var longest_label = global_option !== null ? global_option.domain_name.length : 0;
for (var x = 0; x < option_order.length; x++) {
var domain_uuid = option_order[x];
var domain = domains_by_uuid[domain_uuid] || {};
var domain_name = (domain.domain_name || option_values[domain_uuid] || '').trim();
if (!domain_name) { continue; }
if (domain_name.length > longest_label) { longest_label = domain_name.length; }
var domain_description = (domain.domain_description || '').trim();
dataset.push({
domain_uuid: domain_uuid,
domain_name: domain_name,
domain_name_lc: domain_name.toLowerCase(),
domain_description: domain_description,
domain_description_lc: domain_description.toLowerCase(),
score: 0
});
}
var width_ch = Math.max(18, Math.min(longest_label + 2, 80));
input.style.width = width_ch + 'ch';
sync_input_to_select();
sync_results_typography_from_input();
});
}
window.sync_domain_search_select_visibility = function(select_id) {
var select = document.getElementById(select_id);
if (select && typeof select._domainSearchSyncVisibility === 'function') {
select._domainSearchSyncVisibility();
}
};
window.init_domain_search_selects = function() {
load_domain_picker_styles();
var selectors = document.querySelectorAll("select[name='domain_uuid'], select[id='domain_uuid'], select[data-domain-search='true']");
for (var i = 0; i < selectors.length; i++) {
if (selectors[i].dataset.domainSearch === 'false') { continue; }
if (selectors[i].multiple) { continue; }
init_domain_search_select(selectors[i]);
}
};
})();
window.init_domain_search_selects();
{/literal}
// Multi select box with search
{literal}
const container = document.querySelector('.multiselect_container');