Team Gallery Block Documentation
The Team Gallery Block is a dynamic website component that displays real estate agents in a responsive grid layout. It automatically fetches agent data from the ListingVillage API and renders professional agent cards with contact information.
What It Does
Fetches Agent Data: Automatically retrieves agent information from https://www.listingvillage.com/get-company-agents based on the current domain
Responsive Grid: Displays agents in a Bootstrap-based responsive grid (3 columns on desktop, 2 on tablet, 1 on mobile)
Professional Cards: Shows each agent with a square profile image, name, and contact icons
Interactive Elements: Includes hover effects on images and clickable contact links (phone/email)
Domain Detection: Automatically uses the current website's domain or allows manual override
Usage
Basic Implementation
Simply add the HTML block to any page where you want to display the team:
<div id="our-team-query">
<div id="our-team-query">
<section class="team-grid py-2 mt-0 mb-0" data-site-builder-block-id="team_1">
<div class="container">
<div class="row" id="teamGalleryRow">
<!-- The agent cards will be injected here by the script. -->
</div>
</div>
</section>
</div>
<style>
/* Style for consistent square images */
.team-image-container {
position: relative;
overflow: hidden;
margin-bottom: 20px;
}
.team-image-wrapper {
position: relative;
width: 100%;
padding-top: 100%; /* Creates a square aspect ratio container */
overflow: hidden;
}
.team-image {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
object-fit: cover;
object-position: center top; /* Position from the top to show faces */
transition: transform 0.3s ease;
}
.team-image:hover {
transform: scale(1.05);
}
.team-content {
padding: 15px;
text-align: center;
}
.team-name {
margin-top: 5px;
margin-bottom: 10px;
}
.team-icons a {
margin: 0 5px;
color: white; /* Changed from #333 to white */
font-size: 16px;
}
</style>
<script>
// Domain override variable - set this to override the automatic domain detection
var domainOverride = '';
(async function loadAgents() {
try {
// 1. Dynamically get domain name, use override if available
const domainName = domainOverride || window.location.hostname;
// Log the domain being used (for debugging)
console.log('Using domain:', domainName);
// 2. Fetch the agent data
const response = await fetch(`https://www.listingvillage.com/get-company-agents?domain_name=${domainName}`);
if (!response.ok) {
throw new Error(`Network error: ${response.status} - ${response.statusText}`);
}
const agents = await response.json();
// 3. Build the HTML for each agent
let htmlString = '';
agents.forEach(agent => {
htmlString += `
<div class="col-md-4 col-sm-6 team-card">
<div class="team-image-container">
<a href="https://${agent.domain}" target="_blank" rel="noopener noreferrer">
<div class="team-image-wrapper">
<img
src="${agent.image}"
alt="${agent.name}"
class="team-image"
loading="eager"
/>
</div>
</a>
<div class="team-content">
<p class="team-position"></p>
<h3 class="team-name">${agent.name}</h3>
<div class="team-icons">
${
agent.phone
? `<a href="tel:${agent.phone}"><i class="fa fa-phone"></i></a>`
: ''
}
${
agent.email
? `<a href="mailto:${agent.email}"><i class="fa fa-envelope"></i></a>`
: ''
}
</div>
</div>
</div>
</div>
`;
});
// 4. Inject into the DOM
document.getElementById('teamGalleryRow').innerHTML = htmlString;
// Optional: You can adjust the size of the square container dynamically
// adjustSquareSize();
} catch (error) {
console.error('Error fetching or displaying agents:', error);
// Handle error (e.g., show a fallback message)
}
})();
// Optional function to dynamically adjust the square size based on screen width
function adjustSquareSize() {
const cardWidth = document.querySelector('.team-card').offsetWidth;
const wrappers = document.querySelectorAll('.team-image-wrapper');
wrappers.forEach(wrapper => {
// Make the height equal to the width for a perfect square
wrapper.style.height = cardWidth + 'px';
});
}
</script>
</div>
html
Configuration Options
Domain Override
Set a custom domain instead of using automatic detection:
// At the top of the script section, modify this variable:
var domainOverride = 'your-custom-domain.com';
javascript
Default: Uses window.location.hostname (automatic detection)
Square Image Adjustment
Enable dynamic square sizing based on screen width:
// Uncomment this line in the script:
adjustSquareSize();
javascript
API Requirements
The component expects the ListingVillage API endpoint to return JSON data with this structure:
[
{
"name": "Agent Name",
"image": "https://example.com/agent-photo.jpg",
"domain": "agent-website.com",
"phone": "+1234567890",
"email": "agent@example.com"
}
]
json
Styling Features
Square Images: All agent photos are displayed in perfect squares with consistent sizing
Hover Effects: Images scale slightly (1.05x) on hover
Responsive Design: Uses Bootstrap grid classes for mobile-friendly layout
Contact Icons: FontAwesome icons for phone and email (requires FA to be loaded)
Professional Layout: Clean, centered design with proper spacing
Dependencies
Bootstrap: For responsive grid layout (col-md-4, col-sm-6 classes)
FontAwesome: For contact icons (fa-phone, fa-envelope)
Modern Browser: Requires fetch() API and async/await support
Error Handling
The component includes built-in error handling that:
Logs errors to the browser console
Gracefully fails without breaking the page
Provides network error details for debugging
Fetches Agent Data: Automatically retrieves agent information from https://www.listingvillage.com/get-company-agents based on the current domain
Responsive Grid: Displays agents in a Bootstrap-based responsive grid (3 columns on desktop, 2 on tablet, 1 on mobile)
Professional Cards: Shows each agent with a square profile image, name, and contact icons
Interactive Elements: Includes hover effects on images and clickable contact links (phone/email)
Domain Detection: Automatically uses the current website's domain or allows manual override
Usage
Basic Implementation
Simply add the HTML block to any page where you want to display the team:
<div id="our-team-query">
<div id="our-team-query">
<section class="team-grid py-2 mt-0 mb-0" data-site-builder-block-id="team_1">
<div class="container">
<div class="row" id="teamGalleryRow">
<!-- The agent cards will be injected here by the script. -->
</div>
</div>
</section>
</div>
<style>
/* Style for consistent square images */
.team-image-container {
position: relative;
overflow: hidden;
margin-bottom: 20px;
}
.team-image-wrapper {
position: relative;
width: 100%;
padding-top: 100%; /* Creates a square aspect ratio container */
overflow: hidden;
}
.team-image {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
object-fit: cover;
object-position: center top; /* Position from the top to show faces */
transition: transform 0.3s ease;
}
.team-image:hover {
transform: scale(1.05);
}
.team-content {
padding: 15px;
text-align: center;
}
.team-name {
margin-top: 5px;
margin-bottom: 10px;
}
.team-icons a {
margin: 0 5px;
color: white; /* Changed from #333 to white */
font-size: 16px;
}
</style>
<script>
// Domain override variable - set this to override the automatic domain detection
var domainOverride = '';
(async function loadAgents() {
try {
// 1. Dynamically get domain name, use override if available
const domainName = domainOverride || window.location.hostname;
// Log the domain being used (for debugging)
console.log('Using domain:', domainName);
// 2. Fetch the agent data
const response = await fetch(`https://www.listingvillage.com/get-company-agents?domain_name=${domainName}`);
if (!response.ok) {
throw new Error(`Network error: ${response.status} - ${response.statusText}`);
}
const agents = await response.json();
// 3. Build the HTML for each agent
let htmlString = '';
agents.forEach(agent => {
htmlString += `
<div class="col-md-4 col-sm-6 team-card">
<div class="team-image-container">
<a href="https://${agent.domain}" target="_blank" rel="noopener noreferrer">
<div class="team-image-wrapper">
<img
src="${agent.image}"
alt="${agent.name}"
class="team-image"
loading="eager"
/>
</div>
</a>
<div class="team-content">
<p class="team-position"></p>
<h3 class="team-name">${agent.name}</h3>
<div class="team-icons">
${
agent.phone
? `<a href="tel:${agent.phone}"><i class="fa fa-phone"></i></a>`
: ''
}
${
agent.email
? `<a href="mailto:${agent.email}"><i class="fa fa-envelope"></i></a>`
: ''
}
</div>
</div>
</div>
</div>
`;
});
// 4. Inject into the DOM
document.getElementById('teamGalleryRow').innerHTML = htmlString;
// Optional: You can adjust the size of the square container dynamically
// adjustSquareSize();
} catch (error) {
console.error('Error fetching or displaying agents:', error);
// Handle error (e.g., show a fallback message)
}
})();
// Optional function to dynamically adjust the square size based on screen width
function adjustSquareSize() {
const cardWidth = document.querySelector('.team-card').offsetWidth;
const wrappers = document.querySelectorAll('.team-image-wrapper');
wrappers.forEach(wrapper => {
// Make the height equal to the width for a perfect square
wrapper.style.height = cardWidth + 'px';
});
}
</script>
</div>
html
Configuration Options
Domain Override
Set a custom domain instead of using automatic detection:
// At the top of the script section, modify this variable:
var domainOverride = 'your-custom-domain.com';
javascript
Default: Uses window.location.hostname (automatic detection)
Square Image Adjustment
Enable dynamic square sizing based on screen width:
// Uncomment this line in the script:
adjustSquareSize();
javascript
API Requirements
The component expects the ListingVillage API endpoint to return JSON data with this structure:
[
{
"name": "Agent Name",
"image": "https://example.com/agent-photo.jpg",
"domain": "agent-website.com",
"phone": "+1234567890",
"email": "agent@example.com"
}
]
json
Styling Features
Square Images: All agent photos are displayed in perfect squares with consistent sizing
Hover Effects: Images scale slightly (1.05x) on hover
Responsive Design: Uses Bootstrap grid classes for mobile-friendly layout
Contact Icons: FontAwesome icons for phone and email (requires FA to be loaded)
Professional Layout: Clean, centered design with proper spacing
Dependencies
Bootstrap: For responsive grid layout (col-md-4, col-sm-6 classes)
FontAwesome: For contact icons (fa-phone, fa-envelope)
Modern Browser: Requires fetch() API and async/await support
Error Handling
The component includes built-in error handling that:
Logs errors to the browser console
Gracefully fails without breaking the page
Provides network error details for debugging