Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
113 changes: 109 additions & 4 deletions src/assets/css/simply-rets-admin.css
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,9 @@

.sr-admin-wrap .sr-admin-logo {
display: inline-block;
max-height: 50px;
margin-bottom: 5px;
margin-right: 5px;
vertical-align: bottom;
max-height: 42px;
margin: 0 12px 5px 0;
}

.sr-admin-wrap .sr-admin-title {
Expand All @@ -29,6 +28,9 @@
line-height: 50px;
margin-top: 0px;
margin-bottom: 5px;
font-size: 26px;
font-weight: 600;
letter-spacing: -.5px;
}

.sr-admin-msg-btn {
Expand All @@ -44,4 +46,107 @@
#admin-msg {
display: inline-block;

}
}
/* Settings styles stay inside the plugin admin page. */
.sr-admin-wrap {
max-width: 1180px;
color: #25343c;
padding-bottom: 24px;
}
.sr-admin-wrap [hidden] { display: none !important; }
.sr-admin-wrap .sr-settings-header { margin: 26px 0 18px; }
.sr-admin-wrap .sr-settings-intro { margin: 6px 0 0; color: #596971; font-size: 14px; }
.sr-admin-wrap .sr-doc-links {
display: flex;
flex-wrap: wrap;
align-items: center;
justify-content: space-between;
gap: 12px;
padding-bottom: 22px;
border-bottom: 1px solid #dce2e5;
margin-bottom: 22px;
}
.sr-admin-wrap .sr-doc-links p { margin: 0; color: #c2cccf; }
.sr-admin-wrap a { color: #096c65; }
.sr-admin-wrap .sr-doc-links a { margin-right: 6px; text-decoration: none; }
.sr-admin-wrap .sr-doc-links a:hover { text-decoration: underline; }
.sr-admin-wrap .sr-settings-tools { display: flex; flex-wrap: wrap; gap: 8px; }
.sr-admin-wrap .sr-settings-tools .button { margin: 0; }
.sr-admin-wrap .sr-settings-toolbar { margin: 0 0 24px; max-width: 620px; }
.sr-admin-wrap .sr-settings-toolbar > label { display: block; font-weight: 600; margin-bottom: 8px; }
.sr-admin-wrap .sr-settings-search-box { display: flex; align-items: center; gap: 8px; }
.sr-admin-wrap .sr-settings-search-box .dashicons { position: absolute; margin-left: 12px; color: #73838a; pointer-events: none; }
.sr-admin-wrap #sr-settings-search { width: 100%; min-height: 42px; padding-left: 40px; border-color: #b9c6cc; border-radius: 6px; }
.sr-admin-wrap .sr-clear-search { flex-shrink: 0; }
.sr-admin-wrap .sr-search-status { margin: 8px 0 0; color: #596971; }
.sr-admin-wrap .sr-search-status:empty { display: none; }
.sr-admin-wrap.sr-settings-enhanced .sr-settings-layout { display: grid; grid-template-columns: 230px minmax(0, 1fr); gap: 24px; align-items: start; }
.sr-admin-wrap .sr-settings-nav { position: sticky; top: 52px; }
.sr-admin-wrap .sr-nav-heading { padding-left: 14px; margin: 0 0 10px; font-size: 10px; font-weight: 700; letter-spacing: 1.5px; color: #728087; }
.sr-admin-wrap .sr-settings-nav a { display: flex; align-items: center; gap: 12px; padding: 12px 14px; margin-bottom: 4px; border-radius: 6px; text-decoration: none; color: #43545d; border: 1px solid transparent; }
.sr-admin-wrap .sr-settings-nav a strong { display: block; font-size: 13px; font-weight: 600; }
.sr-admin-wrap .sr-settings-nav a small { display: block; font-size: 11px; margin-top: 3px; color: #647780; }
.sr-admin-wrap .sr-settings-nav a:hover { background: #e7edee; }
.sr-admin-wrap .sr-settings-nav a[aria-current] { background: #e1efec; color: #075c55; border-color: #bfd9d2; }
.sr-admin-wrap .sr-settings-nav a:last-child { border-top: 1px solid #dce2e5; border-radius: 0; margin-top: 16px; padding-top: 18px; }
.sr-admin-wrap .sr-settings-form { min-width: 0; }
.sr-admin-wrap .sr-settings-panel, .sr-admin-wrap .sr-settings-empty { background: #fff; border: 1px solid #dce2e5; border-radius: 8px; padding: 28px 30px; margin: 0 0 20px; box-shadow: 0 2px 4px rgba(24, 46, 54, .03); }
.sr-admin-wrap .sr-settings-panel > h2 { margin: 0 0 10px; font-size: 21px; line-height: 1.4; letter-spacing: -.3px; }
.sr-admin-wrap .sr-settings-panel h3 { font-size: 14px; margin: 26px 0 12px; padding-top: 22px; border-top: 1px solid #edf0f2; }
.sr-admin-wrap .sr-settings-panel > h2 + h3 { padding-top: 14px; margin-top: 14px; }
.sr-admin-wrap .sr-settings-panel p, .sr-admin-wrap .sr-settings-panel li { line-height: 1.7; }
.sr-admin-wrap .sr-settings-panel table { width: 100%; border-collapse: collapse; }
.sr-admin-wrap .sr-settings-panel td { padding: 10px 0; vertical-align: top; line-height: 1.65; }
.sr-admin-wrap .sr-settings-panel td + td { padding-left: 18px; width: 55%; }
.sr-admin-wrap .sr-settings-panel label { display: block; cursor: pointer; }
.sr-admin-wrap .sr-settings-panel input[type="checkbox"], .sr-admin-wrap .sr-settings-panel input[type="radio"] { margin-top: 2px; }
.sr-admin-wrap .sr-settings-panel input[type="text"],
.sr-admin-wrap .sr-settings-panel input[type="password"],
.sr-admin-wrap .sr-settings-panel input[type="email"],
.sr-admin-wrap .sr-settings-panel select,
.sr-admin-wrap .sr-settings-panel textarea { width: 100%; max-width: 540px; min-height: 38px; border-color: #b9c6cc; border-radius: 5px; }
.sr-admin-wrap .sr-settings-panel textarea { padding: 12px; font-family: monospace; }
.sr-admin-wrap .sr-settings-panel small { font-size: 12px; color: #64717b; }
.sr-admin-wrap .sr-demo-note { padding: 14px 16px; background: #f1f6f5; border-radius: 5px; color: #52666a; }
.sr-admin-wrap .sr-demo-note > span { display: block; line-height: 1.8; }
.sr-admin-wrap .sr-demo-note > span + span { margin-top: 10px; }
.sr-admin-wrap .sr-credential-input { position: relative; width: 100%; max-width: 540px; }
.sr-admin-wrap .sr-credential-input input { padding-right: 44px; box-sizing: border-box; }
.sr-admin-wrap .sr-reveal-credentials { position: absolute; right: 1px; top: 1px; bottom: 1px; width: 38px; padding: 0; border: 0; border-radius: 0 4px 4px 0; background: transparent; color: #52666a; cursor: pointer; display: flex; align-items: center; justify-content: center; }
.sr-admin-wrap .sr-reveal-credentials:hover { color: #075c55; background: #e1efec; }
.sr-admin-wrap .sr-reveal-credentials:focus { outline: 2px solid #08776e; outline-offset: -2px; }
.sr-admin-wrap .sr-settings-savebar { display: flex; justify-content: space-between; align-items: center; gap: 16px; position: sticky; bottom: 0; z-index: 5; padding: 16px 22px; border: 1px solid #dce2e5; border-radius: 8px; background: #fff; box-shadow: 0 -3px 16px rgba(24, 46, 54, .06); }
.sr-admin-wrap .sr-settings-savebar strong { display: block; font-size: 13px; }
.sr-admin-wrap .sr-settings-savebar span { display: block; font-size: 12px; margin-top: 3px; color: #647780; }
.sr-admin-wrap .sr-settings-savebar.sr-is-dirty { border-color: #9cc8ba; }
.sr-admin-wrap .sr-is-dirty .sr-save-status { color: #08665d; }
.sr-admin-wrap .sr-settings-savebar .button-primary { background: #08776e; border-color: #08776e; padding: 2px 20px; min-height: 38px; }
.sr-admin-wrap .sr-settings-savebar .button-primary:hover { background: #065e57; border-color: #065e57; }
.sr-admin-wrap .sr-search-match { background: #edf6f2; outline: 4px solid #edf6f2; }
@media (max-width: 1100px) {
.sr-admin-wrap.sr-settings-enhanced .sr-settings-layout { grid-template-columns: 200px minmax(0, 1fr); gap: 16px; }
.sr-admin-wrap .sr-settings-panel { padding: 22px; }
}
@media (max-width: 782px) {
.sr-admin-wrap .sr-admin-title { height: auto; line-height: 1.35; font-size: 23px; }
.sr-admin-wrap .sr-admin-logo { display: none; }
.sr-admin-wrap.sr-settings-enhanced .sr-settings-layout { display: block; }
.sr-admin-wrap .sr-settings-nav { position: static; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 4px; margin-bottom: 20px; }
.sr-admin-wrap .sr-nav-heading { display: none; }
.sr-admin-wrap .sr-settings-nav a { padding: 10px; margin: 0; }
.sr-admin-wrap .sr-settings-nav a small { display: none; }
.sr-admin-wrap .sr-settings-nav a:last-child { margin: 0; border: 1px solid transparent; padding-top: 10px; border-radius: 6px; }
.sr-admin-wrap .sr-settings-panel { padding: 20px 16px; }
.sr-admin-wrap .sr-settings-panel td { display: block; width: auto; padding: 8px 0; }
.sr-admin-wrap .sr-settings-panel td + td { width: auto; padding-left: 0; }
.sr-admin-wrap .sr-settings-panel td > div[style] { max-width: none !important; }
.sr-admin-wrap .sr-credential-input input { min-height: 46px; padding-right: 48px; }
.sr-admin-wrap .sr-reveal-credentials { width: 44px; }
.sr-admin-wrap .sr-settings-panel textarea { max-width: 100%; box-sizing: border-box; }
.sr-admin-wrap #sr_leadcapture_custom_form { margin-left: 0 !important; }
.sr-admin-wrap .sr-settings-savebar { padding: 12px; gap: 8px; border-radius: 6px; }
.sr-admin-wrap .sr-settings-savebar .button-primary { padding: 4px 12px; flex-shrink: 0; }
.sr-admin-wrap .sr-settings-search-box { flex-wrap: wrap; }
}

.sr-admin-wrap .sr-settings-panel { scroll-margin-top: 54px; }
223 changes: 155 additions & 68 deletions src/assets/js/simply-rets-admin.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,82 +7,169 @@
*/


jQuery(function() {
// Listing-page editor filters use the existing labels and control IDs.
jQuery(function($) {
var filterInputs = {
'Minimum Price': '#sr-min-price-span',
'Maximum Price': '#sr-max-price-span',
'Minimum Beds': '#sr-min-bed-span',
'Maximum Beds': '#sr-max-bed-span',
'Minimum Bathrooms': '#sr-min-bath-span',
'Maximum Bathrooms': '#sr-max-bath-span',
'Listing Agent': '#sr-listing-agent-span',
'Listing Type': '#sr-listing-type-span',
'Amount of listings': '#sr-limit-span'
};

// create jquery objects for all of our different input boxes
var minPriceFilterInput = jQuery('#sr-min-price-span');
var maxPriceFilterInput = jQuery('#sr-max-price-span');
var minBedFilterInput = jQuery('#sr-min-bed-span');
var maxBedFilterInput = jQuery('#sr-max-bed-span');
var minBathFilterInput = jQuery('#sr-min-bath-span');
var maxBathFilterInput = jQuery('#sr-max-bath-span');
var agentFilterInput = jQuery('#sr-listing-agent-span');
var listingTypeSelect = jQuery('#sr-listing-type-span');
var limitInput = jQuery('#sr-limit-span');
$('#sr-filter-select').on('change', function() {
var selector = filterInputs[$(this).val()];
if (!selector) return;
var input = $(selector);
$('.current-filters').append(input);
input.show();
$(this).find('option:selected').remove();
});

$('.sr-remove-filter').on('click', function() {
$(this).parent('.sr-filter-input').hide();
$(this).prev('input').val('');
});
});

var filterArea = jQuery('.current-filters');
var filterSelectBox = jQuery('#sr-filter-select');
filterSelectBox.change(function() {
/* Enhance only the settings page. Every section remains available without JS,
* and hidden panels keep their controls in the single WordPress settings form. */
jQuery(function($) {
var root = $('.sr-admin-wrap');
var form = root.find('#sr-settings-form');
if (!form.length) return;

var filterVal = filterSelectBox.val();
var panels = form.find('[data-sr-panel]');
var nav = root.find('.sr-settings-nav');
var search = root.find('#sr-settings-search');
var clear = root.find('.sr-clear-search');
var empty = form.find('.sr-settings-empty');
var searchStatus = root.find('.sr-search-status');
var savebar = form.find('.sr-settings-savebar');
var saveStatus = savebar.find('.sr-save-status');

// Keep custom-form visibility and submission behavior together with the
// other settings handlers, instead of an inline script in the PHP view.
form.find('#sr_enable_custom_lead_form_toggle').on('change', function() {
form.find('#sr_custom_lead_form_row').toggle(this.checked);
form.find('#sr_leadcapture_custom_form').prop('disabled', !this.checked);
});
var active = 'account';
var storageKey = 'simplyrets-settings-section';
var submitting = false;
var firstInvalid = null;
var initialValues = form.serialize();
var searchIndex = [];

// Index help text and option names once, never stored field values.
function searchText(element) {
var text = element.clone();
text.find('input, textarea, select, button').remove();
var names = element.find('[name]').map(function() { return this.name; }).get().join(' ');
return (text.text() + ' ' + names).toLowerCase();
}
panels.each(function() {
var panel = $(this);
var rows = panel.find('tr').map(function() {
var row = $(this);
return { row: row, text: searchText(row) };
}).get();
searchIndex.push({ panel: panel, text: searchText(panel), rows: rows });
});

// when a new filter is selected, show the input box and remove the
// option from the dropdown menu
switch(filterVal) {
case "Minimum Price":
filterArea.append(minPriceFilterInput);
minPriceFilterInput.show();
jQuery(this).find("option:selected").remove();
break;
case "Maximum Price":
filterArea.append(maxPriceFilterInput);
maxPriceFilterInput.show();
jQuery(this).find("option:selected").remove();
break;
case "Minimum Beds":
filterArea.append(minBedFilterInput);
minBedFilterInput.show();
jQuery(this).find("option:selected").remove();
break;
case "Maximum Beds":
filterArea.append(maxBedFilterInput);
maxBedFilterInput.show();
jQuery(this).find("option:selected").remove();
break;
case "Minimum Bathrooms":
filterArea.append(minBathFilterInput);
minBathFilterInput.show();
jQuery(this).find("option:selected").remove();
break;
case "Maximum Bathrooms":
filterArea.append(maxBathFilterInput);
maxBathFilterInput.show();
jQuery(this).find("option:selected").remove();
break;
case "Listing Agent":
filterArea.append(agentFilterInput);
agentFilterInput.show();
jQuery(this).find("option:selected").remove();
break;
case "Listing Type":
filterArea.append(listingTypeSelect);
listingTypeSelect.show();
jQuery(this).find("option:selected").remove();
break;
case "Amount of listings":
filterArea.append(limitInput);
limitInput.show();
jQuery(this).find("option:selected").remove();
break;
default:
break;
function showSection(section, remember) {
if (section !== 'all' && !panels.filter(function() { return $(this).attr('data-sr-panel') === section; }).length) section = 'account';
active = section;
search.val('');
clear.prop('hidden', true);
panels.each(function() { this.hidden = section !== 'all' && $(this).attr('data-sr-panel') !== section; });
empty.prop('hidden', true);
searchStatus.text('');
nav.find('a').removeAttr('aria-current').filter(function() { return $(this).attr('data-sr-section') === section; }).attr('aria-current', 'true');
form.find('.sr-search-match').removeClass('sr-search-match');
if (remember) {
try { window.sessionStorage.setItem(storageKey, section); } catch (error) { /* Storage may be unavailable. */ }
}
}

try { active = window.sessionStorage.getItem(storageKey) || active; } catch (error) { /* Use the account section. */ }
root.addClass('sr-settings-enhanced');
root.find('.sr-settings-toolbar, .sr-settings-nav, .sr-settings-savebar-info, .sr-reveal-credentials').prop('hidden', false);
showSection(active, false);

nav.on('click', 'a', function(event) {
event.preventDefault();
showSection($(this).attr('data-sr-section'), true);
var visiblePanel = panels.filter(function() { return !this.hidden; }).first()[0];
var position = visiblePanel.getBoundingClientRect();
if (window.innerWidth <= 782 || position.top < 52 || position.top > window.innerHeight - 100) visiblePanel.scrollIntoView();
});

search.on('input', function() {
var query = search.val().trim().toLowerCase();
if (!query) { showSection(active, false); return; }
var matches = 0;
nav.find('a').removeAttr('aria-current');
clear.prop('hidden', false);
form.find('.sr-search-match').removeClass('sr-search-match');
$.each(searchIndex, function(index, entry) {
var match = entry.text.indexOf(query) !== -1;
entry.panel.prop('hidden', !match);
if (match) {
matches++;
$.each(entry.rows, function(index, entryRow) {
entryRow.row.toggleClass('sr-search-match', entryRow.text.indexOf(query) !== -1);
});
}
});
empty.prop('hidden', matches !== 0);
searchStatus.text(matches + (matches === 1 ? ' section matches' : ' sections match') + ' “' + search.val() + '”.');
});
clear.on('click', function() { showSection(active, false); search.trigger('focus'); });
search.on('keydown', function(event) { if (event.key === 'Escape') { showSection(active, false); } });

root.find('.sr-reveal-credentials').on('click', function() {
var reveal = $(this).attr('aria-pressed') !== 'true';
var input = $(this).closest('.sr-credential-input').find('input');
input.attr('type', reveal ? 'text' : 'password');
var label = (reveal ? 'Hide ' : 'Show ') + input.attr('aria-label');
$(this).attr({ 'aria-pressed': reveal ? 'true' : 'false', 'aria-label': label, title: label });
$(this).find('.dashicons').toggleClass('dashicons-visibility', !reveal).toggleClass('dashicons-hidden', reveal);
});

jQuery('.sr-remove-filter').click(function() {
jQuery(this).parent('.sr-filter-input').hide();
jQuery(this).prev('input').val("");
// Give legacy text fields accessible names without replacing existing IDs.
form.find('input:not([type="hidden"]):not([type="submit"]), select, textarea').each(function() {
var field = $(this);
if (field.attr('aria-label') || field.closest('label').length) return;
var label = field.closest('tr').find('strong').first().text() || field.closest('tr').find('p').first().text();
if (!label) label = field.closest('[data-sr-panel]').find('h3').first().text();
if (this.name === 'sr_custom_no_results_message') label = 'No search results message';
if (label) field.attr('aria-label', label.trim());
});

form.on('input change', ':input', function() {
var dirty = form.serialize() !== initialValues;
saveStatus.text(dirty ? 'You have unsaved changes' : 'No unsaved changes');
savebar.toggleClass('sr-is-dirty', dirty);
});
// Browser validation must be able to focus an invalid field on a hidden panel.
form[0].addEventListener('invalid', function(event) {
if (firstInvalid) return;
firstInvalid = event.target;
var panel = $(event.target).closest('[data-sr-panel]');
if (panel.length) showSection(panel.attr('data-sr-panel'), true);
window.setTimeout(function() { firstInvalid = null; }, 0);
}, true);
form.on('submit', function() { submitting = true; });
$(window).on('beforeunload', function(event) {
if (!submitting && form.serialize() !== initialValues) {
event.preventDefault();
event.originalEvent.returnValue = '';
return '';
}
});
});
Loading
Loading