added more preview pages and more templates

This commit is contained in:
2026-07-21 07:10:03 -05:00
parent c6119ffdf5
commit b19fdee30d
3726 changed files with 651487 additions and 6169 deletions
@@ -0,0 +1,45 @@
const rangeInput = document.querySelectorAll(".range-input input"), // Get all range input elements
priceInput = document.querySelectorAll(".price-input input"), // Get all price input elements
range = document.querySelector(".slider .progress"); // Get the range element for displaying the progress
let priceGap = 100; // Define the desired price gap
// Event listeners for price inputs
priceInput.forEach(input => {
input.addEventListener("input", e => {
let minPrice = parseInt(priceInput[0].value), // Get the minimum price value
maxPrice = parseInt(priceInput[1].value); // Get the maximum price value
// Check if the price gap is within the desired range and the maxPrice is within the allowed range
if ((maxPrice - minPrice >= priceGap) && maxPrice <= rangeInput[1].max) {
if (e.target.className === "input-min") {
rangeInput[0].value = minPrice; // Update the range input value for the minimum price
range.style.left = ((minPrice / rangeInput[0].max) * 100) + "%"; // Update the range progress position
} else {
rangeInput[1].value = maxPrice; // Update the range input value for the maximum price
range.style.right = 100 - (maxPrice / rangeInput[1].max) * 100 + "%"; // Update the range progress position
}
}
});
});
// Event listeners for range inputs
rangeInput.forEach(input => {
input.addEventListener("input", e => {
let minVal = parseInt(rangeInput[0].value), // Get the minimum range value
maxVal = parseInt(rangeInput[1].value); // Get the maximum range value
// Check if the price gap is smaller than the desired range
if ((maxVal - minVal) < priceGap) {
if (e.target.className === "range-min") {
rangeInput[0].value = maxVal - priceGap; // Adjust the minimum range value to maintain the price gap
} else {
rangeInput[1].value = minVal + priceGap; // Adjust the maximum range value to maintain the price gap
}
} else {
priceInput[0].value = minVal; // Update the minimum price input value
priceInput[1].value = maxVal; // Update the maximum price input value
range.style.left = ((minVal / rangeInput[0].max) * 100) + "%"; // Update the range progress position for the minimum value
range.style.right = 100 - (maxVal / rangeInput[1].max) * 100 + "%"; // Update the range progress position for the maximum value
}
});
});
@@ -0,0 +1,24 @@
/*---------- Product Image Gallery ----------*/
// Get the main product image container and the main product image element
let productImage = document.querySelector(".product-des .image");
let productMain = document.querySelector(".main img");
// Get all the thumbnail images in the change-btns container
let productAll = document.querySelectorAll(".change-btns img");
// Add click event listeners to each thumbnail image
productAll.forEach(product => {
product.addEventListener("click", () =>{
/*----- Active Button -----*/
productImage.querySelector(".active").classList.remove("active"); // Remove the "active" class from the currently active button
product.classList.add("active"); // Add the "active" class to the clicked button to mark it as active
/*----- Active Image -----*/
let src = product.getAttribute("src"); // Get the source attribute of the clicked thumbnail image
productMain.src = src; // Update the source attribute of the main product image to display the clicked image
})
})
@@ -0,0 +1,23 @@
/*---------- Accordion ----------*/
// Document ready function to ensure the script runs after the DOM is fully loaded.
$(document).ready(function(){
// Click event handler for the accordion.
$(".accordion").click(function(){
// Check if the clicked accordion is already active.
if($(this).hasClass("active")){
// If active, close the accordion by removing active class and changing the icon.
$(this).removeClass("active");
$(this).find("i").removeClass("fa-minus").addClass("fa-plus");
}
else{
// If not active, close any open accordion and open the clicked one.
$(".accordion").removeClass("active");
$(".accordion .accordion-heading i").removeClass("fa-minus").addClass("fa-plus");
$(this).addClass("active");
$(this).find("i").removeClass("fa-plus").addClass("fa-minus");
}
})
})
@@ -0,0 +1,32 @@
/*--------------- Clients Slider ---------------*/
// Initialize Swiper for client slider
var swiper = new Swiper(".client-slider", {
spaceBetween: 25, // Set space between slides
loop: true, // Enable looping through slides
// Autoplay settings
autoplay: {
delay: 5000, // Delay between slide transitions
disableOnInteraction: false, // Continue autoplay on user interaction
},
// Define responsive breakpoints
breakpoints: {
0: { // For screens less than 450px
slidesPerView: 2, // Show 1 slide per view
},
450: { // For screens 450px and above
slidesPerView: 3, // Show 2 slides per view
},
768: { // For screens 768px and above
slidesPerView: 4, // Show 3 slides per view
},
990: { // For screens 980px and above
slidesPerView: 5, // Show 4 slides per view
},
},
});
@@ -0,0 +1,134 @@
$(document).ready(function () {
const $form = $('.calculator-form'); // Form where user inputs data
const $totalDisplay = $('.cost-total span'); // Element where total cost will be displayed
// Function to update the total cost based on user inputs
function updateTotal() {
const serviceType = $form.find('[name="service-type"]').val(); // Type of gardening service
const propertyType = $form.find('[name="property-type"]').val(); // Residential or commercial
const areaSize = parseFloat($form.find('[name="area-size"]').val()) || 0; // Size of area in square meters
const gardenStyle = $form.find('[name="garden-style"]').val(); // Style of garden
const numberOfPlants = parseInt($form.find('[name="number-of-plants"]').val()) || 0; // Number of plants
const projectUrgency = $form.find('[name="project-urgency"]').val(); // Urgency of project
const soilType = $form.find('[name="soil-type"]').val(); // Type of soil or substrate
const budget = $form.find('[name="budget"]').val(); // User's budget range
let total = 0; // Initialize total cost
// Calculate base cost based on selected service type and property type
if (serviceType && propertyType) {
total += getServiceCost(serviceType, propertyType);
}
// Add cost for area size ($10 per square meter)
total += areaSize * 10;
// Add cost for number of plants ($5 per plant)
total += numberOfPlants * 5;
// Add cost for garden style based on selected style
total += getGardenStyleCost(gardenStyle);
// Add cost based on project urgency
total += getProjectUrgencyCost(projectUrgency);
// Add cost based on selected soil type
total += getSoilTypeCost(soilType);
// Add additional costs based on selected extra services (checkboxes)
if ($form.find('#automated-irrigation-checkbox').is(':checked')) total += 500;
if ($form.find('#custom-pathways-checkbox').is(':checked')) total += 300;
if ($form.find('#outdoor-seating-checkbox').is(':checked')) total += 700;
// Adjust total based on user's selected budget range
total = adjustForBudget(total, budget);
// Display the calculated total cost in the specified element
$totalDisplay.text(`$${total.toFixed(2)}`); // Format total cost with dollar sign and two decimal places
}
// Function to calculate base cost based on service type and property type
function getServiceCost(serviceType, propertyType) {
// Base costs for different types of gardening services
const baseCosts = {
'lawn-maintenance': 100,
'garden-design': 200,
'tree-planting': 150,
'hardscaping': 300,
'water-features': 400,
'outdoor-lighting': 250,
};
// Apply multiplier for commercial properties
const propertyMultiplier = propertyType === 'commercial' ? 1.5 : 1;
// Calculate and return the adjusted base cost based on selected service type
return baseCosts[serviceType] * propertyMultiplier || 0; // Return 0 if serviceType is not found
}
// Function to retrieve cost based on selected garden style
function getGardenStyleCost(gardenStyle) {
// Costs associated with different garden styles
const gardenStyleCosts = {
'native': 100,
'formal': 200,
'cottage': 150,
'japanese': 250,
'modern': 300,
'eclectic': 200,
'default': 0 // Default cost if style is not recognized
};
return gardenStyleCosts[gardenStyle] || 0; // Return cost of selected garden style or default if not found
}
// Function to retrieve cost based on project urgency
function getProjectUrgencyCost(projectUrgency) {
// Costs associated with different project urgency levels
const projectUrgencyCosts = {
'asap': 300,
'within-a-month': 200,
'within-three-months': 100,
'no-rush': 0 // No additional cost for "no rush" projects
};
return projectUrgencyCosts[projectUrgency] || 0; // Return cost based on selected urgency or 0 if not found
}
// Function to retrieve cost based on selected soil type
function getSoilTypeCost(soilType) {
// Costs associated with different soil types
const soilTypeCosts = {
'loam': 50,
'sandy': 30,
'clay': 40,
'silt': 45,
'peat': 60,
'chalk': 55,
'rocky': 70,
};
return soilTypeCosts[soilType] || 0; // Return cost of selected soil type or 0 if not found
}
// Function to adjust total cost based on user's budget range
function adjustForBudget(total, budget) {
// Define budget limits and corresponding maximum total costs
const budgetLimits = {
'under-1000': 1000,
'1000-5000': 5000,
'5000-10000': 10000,
'10000-20000': 20000,
'over-20000': Infinity,
'not-sure': Infinity // Default maximum if user is unsure about budget
};
// Retrieve maximum total cost based on user's selected budget range
const maxBudget = budgetLimits[budget] || Infinity;
// Return adjusted total cost (cannot exceed maximum budget limit)
return total > maxBudget ? maxBudget : total;
}
// When any input in the form changes, update the total cost
$form.on('input', updateTotal);
});
@@ -0,0 +1,30 @@
/*---------- Counter-Up ----------*/
$(document).ready(function(){
// Loop through each element with class 'count'
$('.count').each(function() {
var $this = $(this),
countTo = $this.attr('data-count'); // Get the target value
// Animate the counting from the 'Current Value' to the 'Target Value'
$({ countNum: $this.text()}).animate({
countNum: countTo // Animate towards the target value
},
{
duration: 5000, // Animation duration (5 seconds)
// Function called on each step of the animation
step: function() {
$this.text(Math.floor(this.countNum)); // Update the displayed value
},
// Function called when the animation is complete
complete: function() {
$this.text(this.countNum + '+'); // Update the displayed value with a '+' sign
}
});
});
});
@@ -0,0 +1,16 @@
/*---------- gallery ----------*/
$(document).ready(function(){
//MAGNIFIC-POPUP
$(".gallery").magnificPopup({
delegate: "a",
type: "image",
removalDelay: 500, //delay removal by X to allow out-animation
gallery:{
enabled: true
},
})
});
@@ -0,0 +1,21 @@
/*--------------- Home Slider ---------------*/
var swiper = new Swiper(".home-slider", {
loop:true, // Enable looping of slides
autoplay: {
delay: 5000, // Delay between slide transitions
disableOnInteraction: false, // Allow autoplay on user interaction
},
pagination: {
el: ".swiper-pagination1", // Pagination element
clickable: true, // Enable clickable pagination bullets
},
navigation: {
nextEl: ".swiper-button-next", // Next slide button
prevEl: ".swiper-button-prev", // Previous slide button
},
});
@@ -0,0 +1,25 @@
/*---------- Mobile-Navbar Nav Toggler ----------*/
$(document).ready(function(){
// Handle main navigation link clicking
$(".main-nav-link").click(function(){
// Check if the clicked link is already active
if($(this).hasClass("active")){
$(this).removeClass("active"); // Remove "active" class from clicked link
$(this).next(".sub-nav-link").removeClass("active").slideUp(); // Remove "active" class and slide up the corresponding sub-navigation
$(this).find("i").removeClass("fa-minus").addClass("fa-plus"); // Update the icon to "fa-plus"
}
else{
$(".nav-link .main-nav-link").removeClass("active"); // Remove "active" class from all main navigation links
$(".nav-link .sub-nav-link").removeClass("active").slideUp(); // Remove "active" class and slide up all sub-navigations
$(".nav-link .main-nav-link i").removeClass("fa-minus").addClass("fa-plus"); // Update all icons to "fa-plus"
$(this).addClass("active"); // Add "active" class to clicked link
$(this).next(".sub-nav-link").addClass("active").slideDown(); // Add "active" class and slide down the corresponding sub-navigation
$(this).find("i").removeClass("fa-plus").addClass("fa-minus"); // Update the icon to "fa-minus"
}
});
});
@@ -0,0 +1,46 @@
$(document).ready(function() {
function setupNewsletterForm(formId, msgId, submitId) {
$(formId).on('submit', function (e) {
var form = $(this);
var msgElement = form.find(msgId);
var submitBtn = form.find(submitId);
// Clear previous message and update button text
msgElement.html('').show();
submitBtn.html('Processing...').attr('disabled', true);
// Submit form data using AJAX
$.ajax({
url: '../../assets/php/newsletter.php',
type: 'post',
data: form.serialize(),
success: function (result) {
msgElement.html(result).fadeIn(); // Display success message
// Reset form fields
form[0].reset();
// Reset button text and enable button
submitBtn.html('Subscribe').attr('disabled', false);
// Clear success message after 5 seconds
setTimeout(function () {
msgElement.css('visibility', 'hidden');
}, 4000); // 4 seconds delay
},
error: function () {
msgElement.html('<span style="color: red;">Error occurred. Please try again later.</span>').fadeIn(); // Display error message if AJAX request fails
// Reset button text and enable button
submitBtn.html('Subscribe').attr('disabled', false);
}
});
e.preventDefault(); // Prevent default form submission
});
}
// Setup both newsletter forms
setupNewsletterForm('#newsletter-form-1', '#msg-1', '#submit-1');
setupNewsletterForm('#newsletter-form-2', '#msg-2', '#submit-2');
});
@@ -0,0 +1,17 @@
/*---------- Page Gallery ----------*/
$(document).ready(function(){
//MAGNIFIC-POPUP
$(".page-gallery").magnificPopup({
delegate: "a",
type: "image",
removalDelay: 500, //delay removal by X to allow out-animation
gallery:{
enabled: true
},
})
});
@@ -0,0 +1,13 @@
/*---------- Payment Methods ----------*/
// Wait for the document to be ready
$(document).ready(function () {
// Add a click event listener to all labels inside the "payment" class
$(".payment .radio-label").click(function () {
// Remove the "active" class from all payment bodies
$(".payment .payment-body").removeClass("active");
// Add the "active" class to the next sibling with class "payment-body"
$(this).next(".payment-body").addClass("active");
});
});
@@ -0,0 +1,31 @@
/*--------------- Process Slider ---------------*/
var swiper = new Swiper(".process-slider", {
spaceBetween: 10, // Space between slides
loop:true, // Enable looping of slides
autoplay: {
delay: 5000, // Delay between slide transitions
disableOnInteraction: false, // Allow autoplay on user interaction
},
// Pagination settings
pagination: {
el: ".swiper-pagination6", // Pagination element
clickable: true, // Enable clickable pagination bullets
},
breakpoints: {
450: {
slidesPerView: 1,
},
768: {
slidesPerView: 2,
},
990: {
slidesPerView: 4,
},
},
});
@@ -0,0 +1,42 @@
/*---------- Projects ----------*/
$(document).ready(function(){
var $container = $('.projects .box-container');//THIS IS THE NAME OF THE CLASS FOR THE CONTAINER THAT WILL HOLD THE PROJECTS IMAGES
$container.isotope({
filter: '*',
animationOptions: {
duration: 750, //TIMING IN MS
easing: 'linear', //EASING
queue: false
}
});
$('.projects .tab-buttons li').click(function(){
$('.projects .tab-buttons .active').removeClass('active');
$(this).addClass('active');
var selector = $(this).attr('data-filter');
$container.isotope({
filter: selector,
animationOptions: {
duration: 750, //TIMING IN MS
easing: 'linear', //EASING
queue: false
}
});
return false;
});
//MAGNIFIC-POPUP
$(".projects").magnificPopup({
delegate: ".view",
type: "image",
removalDelay: 500, //delay removal by X to allow out-animation
gallery:{
enabled: true
},
})
});
@@ -0,0 +1,44 @@
// Select all minus buttons
const minusButtons = document.querySelectorAll(".quantity .minus");
// Select all plus buttons
const plusButtons = document.querySelectorAll(".quantity .plus");
// Select all quantity input fields
const quantityInputs = document.querySelectorAll(".quantity .qty");
// Add click event listener to each minus button
minusButtons.forEach((button, index) => {
button.addEventListener("click", () => {
decreaseQuantity(index);
});
});
// Add click event listener to each plus button
plusButtons.forEach((button, index) => {
button.addEventListener("click", () => {
increaseQuantity(index);
});
});
// Function to decrease the quantity
function decreaseQuantity(index) {
let currentQuantity = parseInt(quantityInputs[index].value);
// Check if the current quantity is greater than 1
if (currentQuantity > 1) {
// Decrease the quantity by 1
quantityInputs[index].value = currentQuantity - 1;
}
}
// Function to increase the quantity
function increaseQuantity(index) {
let currentQuantity = parseInt(quantityInputs[index].value);
// Check if the current quantity is less than 100
if (currentQuantity < 100) {
// Increase the quantity by 1
quantityInputs[index].value = currentQuantity + 1;
}
}
@@ -0,0 +1,34 @@
jQuery(document).ready(function($) {
$('#quote-form').on('submit', function (e) {
e.preventDefault(); // Prevent the default form submission
var form = $(this);
var msgElement = form.find('#msg');
var submitBtn = form.find('#submit');
// Clear previous message and update button text
msgElement.html('').show();
submitBtn.html('Processing...').attr('disabled', true);
// Submit form data using AJAX
$.ajax({
url: '../../assets/php/quote.php',
type: 'post',
data: form.serialize(),
success: function (result) {
msgElement.html(result).fadeIn(); // Display success message
submitBtn.html('Submit').attr('disabled', false); // Reset button text and enable button
form[0].reset(); // Reset form fields
// Clear success message after 5 seconds
setTimeout(function () {
msgElement.fadeOut('slow'); // Fade out message
}, 4000); // 4 seconds delay
},
error: function () {
msgElement.html('<span style="color: red;">Error occurred. Please try again later.</span>').fadeIn(); // Display error message if AJAX request fails
submitBtn.html('Submit').attr('disabled', false); // Reset button text and enable button
}
});
});
});
@@ -0,0 +1,57 @@
$(document).ready(function(){
$('.scroll-top').hide(); // Hide the scroll-top button initially.
/*---------- Mobile-Navbar Toggler ----------*/
// Define variables to store references.
let searchBtn = document.querySelector("#search-btn"); // Search button.
let sideBar = document.querySelector('.mobile-menu'); // Mobile side menu bar.
let searchContainer = document.querySelector(".search-container"); // Search container.
let menuBar = document.querySelector(".header #menu-btn"); // Menu bar in the header.
// Open the mobile side menu bar, When the menuBar element is clicked.
menuBar.onclick = () =>{
searchContainer.classList.remove("active"); // Show the mobile side menu.
sideBar.classList.toggle('active');
menuBar.classList.toggle("fa-times");
$(".nav-link .main-nav-link").removeClass("active"); // Remove active class from main navigation links.
$(".nav-link .sub-nav-link").removeClass("active").slideUp(); // Remove active class from sub-navigation links and slide them up.
$(".nav-link .main-nav-link i").removeClass("fa-minus").addClass("fa-plus"); // Change icon to '+' for main navigation links.
}
/*--------------- Search-Toggler ---------------*/
// When the search button is clicked.
searchBtn.onclick = () => {
sideBar.classList.remove('active'); // Hide the mobile side menu
searchContainer.classList.toggle("active"); // Toggle the visibility of the search container
}
// On Load/Scroll
$(window).on('load scroll',function(){
sideBar.classList.remove('active'); // Hide the mobile side menu on load/scroll.
menuBar.classList.remove("fa-times");
searchContainer.classList.remove("active"); // Hide the search container on load/scroll.
$(".nav-link .main-nav-link").removeClass("active"); // Remove active class from main navigation links on load/scroll.
$(".nav-link .sub-nav-link").removeClass("active").slideUp(); // Remove active class from sub-navigation links and slide them up on load/scroll.
$(".nav-link .main-nav-link i").removeClass("fa-minus").addClass("fa-plus"); // Change icon to '+' for main navigation links on load/scroll.
/*--------------- Scroll-Top ---------------*/
if ($(this).scrollTop() > 100) {
$('.scroll-top').fadeIn(); // Show the scroll-to-top button when the page is scrolled down more than 100px.
} else {
$('.scroll-top').fadeOut(); // Hide the scroll-to-top button when the page is scrolled to the top.
}
/*--------------- Sticky Header ---------------*/
if($(window).scrollTop() > 68){
$('.header').addClass('active');
}else{
$('.header').removeClass('active');
}
});
});
@@ -0,0 +1,25 @@
/*--------------- Service Slider ---------------*/
var swiper = new Swiper(".service-slider", {
spaceBetween: 10, // Space between slides
loop:true, // Enable looping of slides
autoplay: {
delay: 5000, // Delay between slide transitions
disableOnInteraction: false, // Allow autoplay on user interaction
},
breakpoints: {
450: {
slidesPerView: 1,
},
768: {
slidesPerView: 2,
},
990: {
slidesPerView: 3,
},
},
});
@@ -0,0 +1,21 @@
/*---------- Tab Information ----------*/
// Select the tab buttons container.
var tabButtons = document.querySelector('.tab-info .tab-buttons');
// Add a click event listener to the tab buttons.
tabButtons.addEventListener('click', function (e) {
// Check if the clicked element has the 'button' class and is not already active.
if (e.target.classList.contains('button') && !e.target.classList.contains('active')) {
var target = e.target.getAttribute('data-target'); // Get the target data attribute from the clicked button
tabButtons.querySelector('.active').classList.remove('active'); // Remove the 'active' class from the currently active button
e.target.classList.add('active'); // Add the 'active' class to the clicked button
var tabSections = document.querySelector('.tab-info .tab-sections'); // Select the tab sections container.
tabSections.querySelector('.tab-section.active').classList.remove('active'); // Remove the 'active' class from the currently active tab section
tabSections.querySelector(target).classList.add('active'); // Add the 'active' class to the target section, making it visible.
}
});
@@ -0,0 +1,25 @@
/*--------------- Testimonial Slider ---------------*/
var swiper = new Swiper(".testimonial-slider", {
spaceBetween: 15,
loop:true,
autoplay: {
delay: 5000,
disableOnInteraction: false,
},
pagination: {
el: ".swiper-pagination3",
clickable:true,
},
breakpoints: {
450: {
slidesPerView: 1,
},
768: {
slidesPerView: 2,
},
},
});