Salary Information
Job description will appear here.
/* Customizable Variables - Edit these to change the appearance */
:root {
/* Colors */
--eh-primary-color: #ffb700; /* Main accent color (buttons, salary) */
--eh-primary-hover: #ffb700; /* Hover state for primary color */
--eh-text-primary: #333333; /* Primary text color */
--eh-text-secondary: #333333; /* Secondary text color */
--eh-text-description: #444444; /* Job description text color */
--eh-background: #ffffff; /* Job item background */
--eh-border-color: #e0e0e0; /* Border color */
--eh-tag-color: #800020; /* Tag background color (maroon) */
--eh-tag-text: #ffffff; /* Tag text color */
/* Spacing */
--eh-container-gap: 2rem; /* Space between job listings */
--eh-card-padding: 1.5rem; /* Padding inside job cards */
--eh-section-margin: 1rem; /* Margin between sections */
/* Sizing */
--eh-title-size: 1.5rem; /* Job title font size */
--eh-meta-size: 0.9rem; /* Meta information font size */
--eh-description-line-height: 1.6; /* Line height for description */
--eh-border-radius: 1rem; /* Border radius for cards and buttons */
--eh-tag-radius: 0.5rem; /* Border radius for tags */
/* Effects */
--eh-shadow-normal: 0 2px 4px rgba(0, 0, 0, 0.05); /* Default shadow */
--eh-shadow-hover: 0 4px 8px rgba(0, 0, 0, 0.1); /* Hover shadow */
--eh-transition-speed: 0.2s; /* Transition speed for hover effects */
}
/* Basic styling for the job listings */
.eh-job-listings-container {
font-family: inherit;
max-width: 100%;
margin: 0 auto;
}
.eh-job-list {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: var(--eh-container-gap);
}
/* Make grid responsive for smaller screens */
@media (max-width: 768px) {
.eh-job-list {
grid-template-columns: 1fr;
}
}
.eh-job-item {
border: 1px solid var(--eh-border-color);
border-radius: var(--eh-border-radius);
padding: var(--eh-card-padding);
background-color: var(--eh-background);
box-shadow: var(--eh-shadow-normal);
transition: transform var(--eh-transition-speed) ease,
box-shadow var(--eh-transition-speed) ease;
/* Use flexbox for vertical layout within cards */
display: flex;
flex-direction: column;
}
.eh-job-item:hover {
transform: translateY(-2px);
box-shadow: var(--eh-shadow-hover);
}
.eh-job-header {
margin-bottom: var(--eh-section-margin);
}
.eh-job-title {
margin: 0 0 10px 0;
color: var(--eh-text-primary);
font-size: var(--eh-title-size);
font-weight: bold;
}
.eh-job-meta {
display: flex;
flex-wrap: wrap;
gap: 0.5rem;
margin-bottom: 10px;
}
.eh-tag {
display: inline-block;
background-color: var(--eh-tag-color);
color: var(--eh-tag-text);
font-size: var(--eh-meta-size);
padding: 0.3rem 0.8rem;
border-radius: var(--eh-tag-radius);
white-space: nowrap;
}
.eh-job-salary {
font-weight: bold;
color: var(--eh-primary-color);
margin-bottom: var(--eh-section-margin);
}
.eh-job-description {
margin-bottom: var(--eh-section-margin);
color: var(--eh-text-description);
line-height: var(--eh-description-line-height);
/* Truncate text to 5 lines with ellipsis */
display: -webkit-box;
-webkit-line-clamp: 5;
-webkit-box-orient: vertical;
overflow: hidden;
text-overflow: ellipsis;
max-height: calc(var(--eh-description-line-height) * 5em);
}
.eh-job-footer {
margin-top: auto;
padding-top: var(--eh-section-margin);
}
.eh-apply-button {
display: inline-block;
background-color: var(--eh-primary-color);
color: white !important;
padding: 10px 20px;
border-radius: var(--eh-border-radius);
text-decoration: none;
font-weight: bold;
transition: background-color var(--eh-transition-speed) ease;
}
.eh-apply-button:hover {
background-color: var(--eh-primary-hover);
}
.eh-loading {
text-align: center;
padding: var(--eh-card-padding);
color: var(--eh-text-secondary);
}
document.addEventListener("DOMContentLoaded", function () {
// Replace these with your actual Employment Hero credentials
const ORG_ID = "e10f0ed6-f4c4-4aaf-8b29-667f086e4816"; // Your organization ID
const API_TOKEN = "8gNxSDLhmo4OFHJPEOC7-w"; // Your API token
const API_URL = `https://api.employmenthero.com/ats/api/v1/embedded/organisations/${ORG_ID}/jobs`;
// Function to fetch job listings from Employment Hero API
async function fetchJobListings() {
try {
const response = await fetch(API_URL, {
headers: {
"X_ATS_TOKEN": API_TOKEN
}
});
if (!response.ok) {
throw new Error(`HTTP error! Status: ${response.status}`);
}
const data = await response.json();
updateJobListings(data.data.items);
} catch (error) {
console.error("Error fetching job listings:", error);
document.getElementById("job-listings").innerHTML =
"
Unable to load job listings at this time. Please try again later.
";
}
}
// Function to extract the first paragraph from HTML
function extractFirstParagraph(htmlContent) {
// Create a temporary div to hold the HTML content
const tempDiv = document.createElement('div');
tempDiv.innerHTML = htmlContent;
// Look for the first paragraph
let firstParagraph = null;
let isComplete = true;
// First check for
tags
const paragraphs = tempDiv.querySelectorAll('p');
if (paragraphs.length > 0) {
firstParagraph = paragraphs[0].innerHTML;
// Check if we'll need truncation based on paragraph length
const testP = document.createElement('p');
testP.innerHTML = firstParagraph;
testP.style.position = 'absolute';
testP.style.visibility = 'hidden';
testP.style.width = '100%';
testP.style.lineHeight = 'var(--eh-description-line-height)';
document.body.appendChild(testP);
// Calculate if it's more than 5 lines
const lineHeight = parseFloat(getComputedStyle(testP).lineHeight);
const height = testP.offsetHeight;
const lines = height / lineHeight;
isComplete = lines <= 5;
document.body.removeChild(testP);
} else {
// If no
tags, look for any text content divided by
tags or line breaks
const content = tempDiv.innerHTML;
const sections = content.split(/
/i);
if (sections.length > 0) {
firstParagraph = sections[0];
// If there are multiple sections, it's likely we're truncating
isComplete = sections.length === 1;
} else {
// Just take the entire content if we can't find paragraphs
firstParagraph = content;
// For plain text, rough estimate if it's longer than 5 lines (approx 400 chars)
isComplete = content.length < 400;
}
}
return { text: firstParagraph, isComplete: isComplete };
}
// Function to update the DOM with job listings
function updateJobListings(jobs) {
const jobContainer = document.getElementById("job-listings");
const jobTemplate = document.getElementById("job-item");
// Clear loading message
jobContainer.innerHTML = "";
if (!jobs || jobs.length === 0) {
jobContainer.innerHTML = "
No job openings at the moment.
";
return;
}
// Sort jobs by department (optional)
jobs.sort((a, b) => {
return (a.department || "").localeCompare(b.department || "");
});
// Add each job to the container
jobs.forEach((job) => {
const jobClone = jobTemplate.cloneNode(true);
jobClone.removeAttribute("id"); // Remove the template ID
jobClone.style.display = "block";
// Update job details
jobClone.querySelector("#job-title").textContent = job.title || "Position Available";
jobClone.querySelector("#job-title").removeAttribute("id");
jobClone.querySelector("#job-department").textContent = job.department || "Various";
jobClone.querySelector("#job-department").removeAttribute("id");
jobClone.querySelector("#job-location").textContent = job.city || "Remote";
jobClone.querySelector("#job-location").removeAttribute("id");
jobClone.querySelector("#job-type").textContent = job.employment_type_name || "Various";
jobClone.querySelector("#job-type").removeAttribute("id");
// Process the description (render HTML safely)
const descriptionElement = jobClone.querySelector("#job-description");
if (job.description) {
// Extract the first paragraph and check if it's complete
const { text: firstParagraph, isComplete } = extractFirstParagraph(job.description);
// Set the content with the first paragraph only
descriptionElement.innerHTML = firstParagraph;
// Only add ellipsis if the text is actually truncated
if (!isComplete) {
descriptionElement.innerHTML += '
...';
}
} else {
descriptionElement.textContent = "Please contact us for more information about this position.";
}
descriptionElement.removeAttribute("id");
// Handle salary visibility
const salaryElement = jobClone.querySelector("#job-salary");
if (job.hide_pay_rate || !job.salary_min) {
salaryElement.style.display = "none";
} else {
const formattedMin = new Intl.NumberFormat('en-US').format(job.salary_min);
const formattedMax = job.salary_max ? new Intl.NumberFormat('en-US').format(job.salary_max) : null;
if (formattedMax) {
salaryElement.textContent = `${job.salary_currency || 'AUD'} ${formattedMin} - ${formattedMax} per ${job.salary_rate_name || 'annum'}`;
} else {
salaryElement.textContent = `${job.salary_currency || 'AUD'} ${formattedMin} per ${job.salary_rate_name || 'annum'}`;
}
}
salaryElement.removeAttribute("id");
// Update the apply button
const applyButton = jobClone.querySelector("#job-button");
if (applyButton) {
applyButton.href = job.application_url || "#";
if (!job.application_url) {
applyButton.textContent = "Contact Us";
}
applyButton.removeAttribute("id");
}
// Add the job to the container
jobContainer.appendChild(jobClone);
});
}
// Initial fetch of job listings
fetchJobListings();
// Optional: Refresh job listings periodically (e.g., every hour)
// setInterval(fetchJobListings, 3600000);
});