蜜桃传媒

Rental Agreement Termination Letter By Landlord Template for South Africa

A formal legal document used in South Africa by landlords or property owners to officially terminate a rental agreement with their tenant. This document must comply with South African rental laws, particularly the Rental Housing Act and the Prevention of Illegal Eviction Act. It serves as an official notice of termination, stating the legal grounds for ending the tenancy, specifying the notice period, and outlining the requirements for property vacation. The letter must include specific elements required by South African law and must be served in accordance with legal requirements to be considered valid.

Typically:
i
This cost is based on prices provided by
6 legal services in your market.
With 蜜桃传媒AI:

拢0

i
Generate and export your first
document completely free.
Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.
Get template free

Your data doesn't train 蜜桃传媒's AI

You keep IP ownership聽of your docs

4.6 / 5
4.6 / 5
4.8 / 5
Alternatively...

What is a Rental Agreement Termination Letter By Landlord?

The Rental Agreement Termination Letter By Landlord is a crucial legal document used in South African property law when a landlord wishes to end a tenancy agreement. It must be drafted in accordance with the Rental Housing Act 50 of 1999, the Prevention of Illegal Eviction Act, and other relevant South African legislation. This document is used in various situations, including lease expiration, breach of contract, property sale, or when the landlord requires the property for personal use. The letter must provide appropriate notice periods as specified by law, clearly state the grounds for termination, and include all legally required information such as property details, termination date, and vacation requirements. Proper documentation and delivery of this notice is essential for legal compliance and to avoid disputes in the eviction process.

What sections should be included in a Rental Agreement Termination Letter By Landlord?

1. Sender Details: Full name and address of the landlord/property owner or their authorized representative

2. Date: The date when the letter is written/sent

3. Recipient Details: Full name and address of the tenant

4. Property Details: Complete address and description of the rental property

5. Subject Line: Clear indication that this is a Notice of Termination of Lease Agreement

6. Reference Information: Lease agreement details including original signing date and property reference numbers

7. Notice of Termination: Clear statement of intention to terminate the lease agreement

8. Legal Grounds: Specific legal basis for termination under South African law

9. Notice Period: Clearly stated notice period and final date of tenancy

10. Vacating Instructions: Requirements for property inspection and handover of keys

11. Closing and Signature: Professional closing, landlord's signature and contact information

What sections are optional to include in a Rental Agreement Termination Letter By Landlord?

1. Breach Details: Used when termination is due to breach of contract, detailing specific violations

2. Remedy Options: Include when giving tenant opportunity to remedy breaches before termination takes effect

3. Security Deposit: Include when addressing the return or withholding of security deposit

4. Outstanding Payments: Used when there are pending rental payments or utility bills to be settled

5. Legal Consequences: Include when needing to outline potential legal action in case of non-compliance

6. Alternative Resolution: Used when offering options for dispute resolution or negotiation

What schedules should be included in a Rental Agreement Termination Letter By Landlord?

1. Proof of Delivery: Documentation showing the letter was properly served to tenant

2. Original Lease Agreement: Copy of the original lease agreement referenced in the termination

3. Property Inspection Report: If applicable, current condition report of the property

4. Evidence of Breach: If termination is due to breach, documentation supporting the claim

5. Payment Records: If relevant, records of outstanding payments or payment history

Authors

Alex Denne

Advisor @ 蜜桃传媒AI | 3 x UCL-Certified in Contract Law & Drafting | 4+ Years Managing 1M+ Legal Documents

Jurisdiction

South Africa

Cost

Free to use

Find the document you need

Notice To Vacate Lease

A formal legal notice used in South Africa to communicate the intention to terminate a lease agreement, complying with South African property law and lease requirements.

Download

Notice To Move Out Apartment

A formal notice document under South African law for tenants to communicate their intention to terminate a residential lease agreement and vacate a rental property.

Download

Notice Of Lease Ending

A formal South African legal document serving notice of lease termination, compliant with local property law requirements.

Download

Company Termination Letter For Employee

A South African law-compliant formal letter documenting employment termination, including notice period, final payments, and termination conditions.

Download

Rental Lease Termination Notice

A South African legal notice document for terminating a rental lease agreement, compliant with local property and consumer protection laws.

Download

Rental Agreement Termination Letter By Landlord

A formal notice compliant with South African law used by landlords to legally terminate a rental agreement with a tenant.

Download

Letter To Vacate Apartment

A formal notice document used in South Africa by tenants to inform landlords of their intention to vacate a residential property, complying with South African rental laws and notice requirements.

Download

Giving Notice Of Termination Of Employment

A formal South African employment termination notice that complies with local labor laws, specifying notice period and termination details.

Download

Landlord Ending Tenancy Letter

A formal notice under South African law from a landlord to a tenant indicating the termination of a lease agreement, including termination date and vacating requirements.

Download

Thirty Day Notice To Landlord

A formal 30-day notice of lease termination from tenant to landlord, compliant with South African rental law requirements.

Download

Notification Of Termination

A formal notice of employment termination compliant with South African labor laws, officially ending an employment relationship.

Download

Notice Of Intention To Terminate Building Contract

A formal notice under South African law declaring the intention to terminate a building contract due to breach of contract terms, specifying grounds and remedial actions required.

Download

Lease Cancellation Notice

A South African legal notice formally terminating a lease agreement, compliant with local property law and specifying termination terms and conditions.

Download

House Vacate Notice To Tenant

A formal notice under South African law requiring a tenant to vacate a residential property by a specified date, compliant with local housing legislation.

Download

30 Day Contract Termination Notice

A formal notice under South African law for terminating a contract with 30 days' notice, complying with local statutory and common law requirements.

Download

Termination Of House Contract Letter

A formal notice governed by South African law to terminate a residential lease agreement, ensuring legal compliance with local property legislation and maintaining professional communication between parties.

Download

Month To Month Lease Notice

A formal notice document used in South Africa to terminate a month-to-month rental agreement, complying with local property law requirements and standard notice periods.

Download

Company Separation Letter

A formal document used in South Africa to communicate and record employment termination, ensuring compliance with local labor laws and outlining separation terms.

Download

Termination Warning Letter To Employee

A formal warning document under South African labor law that notifies an employee of potential termination due to conduct or performance issues.

Download

End Contract Letter To Employer

A formal resignation letter compliant with South African employment law, serving as official notice of employment termination.

Download

Termination Letter For Not Reporting To Work

A South African law-compliant termination letter for cases of unauthorized work absence, following Labour Relations Act requirements.

Download

Rental Notice To Vacate

A South African legal notice document used by tenants to formally inform landlords of their intention to vacate a rental property.

Download

Non Performance Termination Letter

A formal letter terminating employment due to poor performance under South African labor law.

Download

Notice Of Temporary Layoff

A South African legal document notifying employees of a temporary work suspension or reduction, compliant with the Labour Relations Act.

Download

Intention To Vacate Notice

A formal notice document used in South Africa by tenants to inform landlords of their intention to end a lease agreement and vacate a property, compliant with South African rental housing laws.

Download

90 Day Contract Termination Notice

A formal South African legal document providing 90-day notice for contract termination, compliant with local legislation and common law requirements.

Download

Service Termination Letter To Vendor

A formal notice under South African law used to terminate an existing service agreement with a vendor, outlining termination details and next steps.

Download

Notice Of Termination Of Lease By Landlord

A formal notice document used in South Africa by landlords to legally terminate a lease agreement, complying with local property law requirements.

Download

Dismissal Notice Letter

A formal employment termination document compliant with South African labor law, providing official notice of dismissal and relevant termination details.

Download

Move Out Notice Letter

A formal notification document used in South African tenancies to communicate a tenant's intention to vacate a rental property, complying with local property law requirements.

Download

Exit Letter From Employee

A formal employee resignation letter compliant with South African labor law, providing official notice of employment termination.

Download

Notice Of Termination Of Tenancy

A legal notice under South African law used to formally terminate a rental agreement between a landlord and tenant, following statutory requirements and notice periods.

Download

Move Out Notice To Landlord

A formal notice document used in South Africa by tenants to inform landlords of their intention to vacate a rental property, complying with South African rental housing laws.

Download
See more related templates

骋别苍颈别鈥檚 Security Promise

蜜桃传媒 is the safest place to draft. Here鈥檚 how we prioritise your privacy and security.

Your data is private:

We do not train on your data; 骋别苍颈别鈥檚 AI improves independently

All data stored on 蜜桃传媒 is private to your organisation

Your documents are protected:

Your documents are protected by ultra-secure 256-bit encryption

We are ISO27001 certified, so your data is secure

Organizational security:

You retain IP ownership of your documents and their information

You have full control over your data and who gets to see it

/** * 蜜桃传媒AI Template Page Script (Algolia + CMS fallback) * - Efficient Algolia search (lazy-loaded libs, no initial queries, 250ms debounce, min 2 chars). * - Shows CMS list by default; swaps to Algolia results only while searching. * - 4-column responsive grid, clickable title, purple (#673AB7) pill CTA. * - Counter shows "X of 37,541 shown". Pagination hidden if 鈮 one page (鈮 16 hits) or 0 hits. * - Empty state: "Generate your bespoke document" with compact dashed bubble + subcopy. * - Keeps existing accordion, exit-intent, Segment events, and create-document button logic. */ if (!window.__genieTemplateInit) { window.__genieTemplateInit = true; function runIdle(fn, timeout){ (window.requestIdleCallback || function(cb){ setTimeout(cb, 1); }) (fn, timeout ? {timeout} : undefined); } // ---------- Config ---------- const ALGOLIA_APP_ID = 'ZJLTMPL15I'; const ALGOLIA_SEARCH_KEY = 'b76a4b392b5c3d5eaf3ccdbe3008327a'; const ALGOLIA_INDEX_NAME = 'New Document List'; const DISPLAY_TOTAL_TEXT = '37,541'; const HITS_PER_PAGE = 16; const MIN_CHARS = 2; // do not fire queries for < 2 chars const INPUT_DEBOUNCE_MS = 250; // reduce API calls // ---------- Utilities ---------- function trackOnce(eventName, data = {}) { try { const key = `segmentEventFired-${eventName}`; if (sessionStorage.getItem(key)) return; if (typeof analytics !== "undefined" && typeof analytics.track === "function") { analytics.track(eventName, data); sessionStorage.setItem(key, "true"); } } catch (_) {} } const CLICK_DEBOUNCE_MS = 800; // prevent double window.open function safeOpenOnce(sourceEl, url, tgt = "_blank") { try { if (sourceEl && sourceEl.dataset.opening === "1") return; if (sourceEl) { sourceEl.dataset.opening = "1"; setTimeout(() => { try { delete sourceEl.dataset.opening; } catch(_){} }, CLICK_DEBOUNCE_MS); } } catch(_) {} window.open(url, tgt); } function loadScriptOnce(src) { return new Promise((resolve, reject) => { if (document.querySelector(`script[src="${src}"]`)) return resolve(); const s = document.createElement('script'); s.src = src; s.async = true; s.onload = resolve; s.onerror = reject; document.head.appendChild(s); }); } // Helper 鈥 Title Case with small words kept lowercase (except first/last) function toTitleCase(str) { const SMALL = new Set([ "a","an","and","as","at","but","by","for","from","in","into","nor", "of","on","onto","or","over","per","the","to","vs","via","with","upon" ]); function cap(w) { return w ? w.charAt(0).toUpperCase() + w.slice(1).toLowerCase() : w; } function capCompound(w, isBoundary) { // Preserve delimiters, title-case segments; apply small-word rule to segments too return w.split(/([-_])/).map((seg, idx, arr) => { if (seg === "-" || seg === "_") return seg; const lower = seg.toLowerCase(); const firstSeg = idx === 0; const lastSeg = idx === arr.length - 1; if (!isBoundary && !firstSeg && !lastSeg && SMALL.has(lower)) return lower; // Preserve acronyms like NDA/LLC if (/^[A-Z0-9]{2,}$/.test(seg)) return seg; return cap(seg); }).join(""); } const words = (str || "").trim().split(/\s+/); return words.map((w, i) => { const lower = w.toLowerCase(); const isBoundary = (i === 0 || i === words.length - 1); // Preserve acronyms (e.g., NDA, USA) if (/^[A-Z0-9]{2,}$/.test(w)) return w; // Don鈥檛 capitalise 鈥渟mall words鈥 unless first/last if (!isBoundary && SMALL.has(lower)) return lower; // Handle hyphen/underscore compounds (e.g., non-compete, step-by-step) if (w.includes("-") || w.includes("_")) return capCompound(w, isBoundary); // Default case + apostrophes (e.g., it's -> It's) return cap(w); }).join(" "); } function showAlgoliaError(msg){ const el = document.createElement('div'); el.style.cssText='position:fixed;bottom:12px;left:12px;z-index:99999;background:#fff3f3;border:1px solid #ffc9c9;padding:8px 12px;border-radius:8px;color:#c00;font:14px/1.4 system-ui;box-shadow:0 2px 8px rgba(0,0,0,.08)'; el.textContent=msg; document.body.appendChild(el); setTimeout(()=>{ try{ el.remove(); }catch(_){} }, 8000); } // ---------- Main (load) ---------- window.addEventListener("load", function () { // --- Make the LCP H1 paint immediately on mobile (avoid fade-in delays) (function ensureImmediateH1Paint(){ if (!matchMedia('(max-width: 767px)').matches) return; var style = document.createElement('style'); style.textContent = ` /* If Webflow interactions set opacity/transform on header, override on mobile */ #heading-5 { opacity: 1 !important; transform: none !important; } `; document.head.appendChild(style); })(); injectAlgoliaStyles(); // --- Locale detection + strings (EN/PT/FR/IT/ES/DE) const htmlLang = (document.documentElement.lang || "").toLowerCase(); const pathLocale = (window.location.pathname.split("/")[1] || "").toLowerCase(); const langHint = (htmlLang || pathLocale || "").toLowerCase(); const isPT = langHint.includes("pt"); const isFR = langHint.includes("fr"); const isIT = langHint.includes("it"); const isES = langHint.includes("es"); const isDE = langHint.includes("de"); const currentLang = isPT ? "pt" : isFR ? "fr" : isIT ? "it" : isES ? "es" : isDE ? "de" : "en"; const I18N_MAP = { en: { searchPlaceholder: "Search templates鈥", noMatches: "No matches found.", generateBtn: "Generate your bespoke document", subcopy: "Let 蜜桃传媒's market-leading AI produce a new legally robust document in seconds.", getTemplate: "Get template", ariaSearch: "Search items", formatStats: (shown, total) => `${shown.toLocaleString()} of ${total} shown` }, pt: { searchPlaceholder: "Pesquisar modelos鈥", noMatches: "Nenhum resultado encontrado.", generateBtn: "Gerar o seu documento personalizado", subcopy: "Deixe a IA l铆der de mercado da 蜜桃传媒 criar, em segundos, um documento juridicamente s贸lido.", getTemplate: "Obter modelo", ariaSearch: "Pesquisar itens", formatStats: (shown, total) => `${shown.toLocaleString()} de ${total} mostrados` }, fr: { searchPlaceholder: "Rechercher des mod猫les鈥", noMatches: "Aucun r茅sultat.", generateBtn: "G茅n茅rez votre document sur mesure", subcopy: "L鈥橧A de pointe de 蜜桃传媒 cr茅e en quelques secondes un document juridiquement solide.", getTemplate: "Obtenir le mod猫le", ariaSearch: "Rechercher des 茅l茅ments", formatStats: (shown, total) => `${shown.toLocaleString()} sur ${total} affich茅s` }, it: { searchPlaceholder: "Cerca modelli鈥", noMatches: "Nessun risultato trovato.", generateBtn: "Genera il tuo documento su misura", subcopy: "L鈥橧A leader di 蜜桃传媒 crea in pochi secondi un documento giuridicamente solido.", getTemplate: "Ottieni il modello", ariaSearch: "Cerca elementi", formatStats: (shown, total) => `${shown.toLocaleString()} di ${total} visualizzati` }, es: { searchPlaceholder: "Buscar plantillas鈥", noMatches: "No se encontraron resultados.", generateBtn: "Genera tu documento a medida", subcopy: "La IA l铆der de 蜜桃传媒 crea en segundos un documento con solidez jur铆dica.", getTemplate: "Obtener plantilla", ariaSearch: "Buscar elementos", formatStats: (shown, total) => `${shown.toLocaleString()} de ${total} mostrados` }, de: { searchPlaceholder: "Vorlagen suchen鈥", noMatches: "Keine Ergebnisse gefunden.", generateBtn: "Individuelles Dokument erstellen", subcopy: "蜜桃传媒s f眉hrende KI erstellt in Sekunden ein rechtssicheres Dokument.", getTemplate: "Vorlage anzeigen", ariaSearch: "Elemente suchen", formatStats: (shown, total) => `${shown.toLocaleString()} von ${total} angezeigt` } }; const I18N = I18N_MAP[currentLang]; // --- Find CMS list and search input const cmsList = document.getElementById("post-list") || document.querySelector(".post_collection-wrapper"); let input = document.getElementById("post-search") || document.querySelector('#search-form_input\\ 2, .search-form_input-2'); // Create a minimal search input if none exists if (!input) { const bar = document.createElement("div"); bar.className = "search-bar"; bar.style.cssText = "display:flex;gap:.75rem;align-items:center;flex-wrap:wrap;justify-content:center;margin:0 0 .5rem 0;"; input = document.createElement("input"); input.id = "post-search"; input.type = "search"; input.placeholder = I18N.searchPlaceholder; input.setAttribute("aria-label", I18N.ariaSearch); input.style.cssText = "padding:.75rem 1rem;border:1px solid rgba(0,0,0,.12);border-radius:9999px;min-width:280px;max-width:720px;width:100%;"; bar.appendChild(input); (cmsList?.parentNode || document.body).insertBefore(bar, cmsList || null); } else { // Ensure placeholder respects locale if input already exists try { input.placeholder = I18N.searchPlaceholder; } catch(_) {} } // --- Stats line (centered) let statsEl = document.getElementById("search-count"); if (!statsEl) { statsEl = document.createElement("div"); statsEl.id = "search-count"; statsEl.style.cssText = "display:block;width:100%;text-align:center;margin-top:.5rem;"; input.parentNode.appendChild(statsEl); } // --- Governing law fallback const DEFAULT_GOV_LAW = 'United States'; function sanitizeGovLaw(v) { v = (v || '').trim(); return (!v || /^choose one\.{0,3}$/i.test(v)) ? DEFAULT_GOV_LAW : v; } // --- Prepare Algolia result containers just above CMS list const resultsParent = (cmsList && cmsList.parentNode) ? cmsList.parentNode : (statsEl.parentNode || document.body); let hitsEl = document.getElementById("algolia-hits"); if (!hitsEl) { hitsEl = document.createElement("div"); hitsEl.id = "algolia-hits"; hitsEl.style.cssText = "margin-top:1rem;width:100%;display:none;"; resultsParent.insertBefore(hitsEl, cmsList || null); } let paginationEl = document.getElementById("algolia-pagination"); if (!paginationEl) { paginationEl = document.createElement("div"); paginationEl.id = "algolia-pagination"; paginationEl.style.cssText = "margin:1rem 0;width:100%;display:none;"; resultsParent.insertBefore(paginationEl, cmsList || null); } // --- Toggle helpers const hasQuery = () => !!(input.value || "").trim(); function setCmsVisible(show) { if (!cmsList) return; cmsList.style.display = show ? "" : "none"; cmsList.setAttribute("aria-hidden", show ? "false" : "true"); } function setAlgoliaVisible(show) { hitsEl.style.display = show ? "" : "none"; paginationEl.style.display = show ? "" : "none"; } // Helper to ensure local empty UI never overlaps with Algolia view function hideLocalEmptyUI() { const createBtn = document.getElementById("no-results-create-btn"); const subcopy = document.getElementById("no-results-subcopy"); if (createBtn) createBtn.style.display = "none"; if (subcopy) subcopy.style.display = "none"; } // Initial: CMS visible; Algolia hidden; no counter setCmsVisible(true); setAlgoliaVisible(false); statsEl.textContent = ""; // --- Lazy Algolia bootstrap (only after user types 鈮 MIN_CHARS) let algoliaBootstrapped = false; let search = null; // --- Park InstantSearch CSS so it doesn't block first paint (function parkInstantSearchCSS(){ var link = Array.from(document.styleSheets || []) .map(function(s){return s.ownerNode;}) .find(function(n){ return n && n.tagName === 'LINK' && /instantsearch\.css/i.test(n.href); }); if (link && !link.dataset.parked) { link.media = 'print'; // non-matching media => not render-blocking link.dataset.parked = '1'; } // When/if we actually bootstrap Algolia, flip it back to 'all' window.__enableInstantSearchCSS = function(){ try { if (link) link.media = 'all'; } catch(_) {} }; })(); async function bootstrapAlgolia() { if (algoliaBootstrapped) return; algoliaBootstrapped = true; try { await loadScriptOnce("https://cdn.jsdelivr.net/npm/algoliasearch@4/dist/algoliasearch-lite.umd.js"); await loadScriptOnce("https://cdn.jsdelivr.net/npm/instantsearch.js@4/dist/instantsearch.production.min.js"); } catch (err) { console.error('Algolia libs failed to load', err); showAlgoliaError('Algolia libraries failed to load.'); return; } const searchClient = algoliasearch(ALGOLIA_APP_ID, ALGOLIA_SEARCH_KEY); // Build "create" URL from current controls + query function currentGovLaw() { const el = document.getElementById("governing-law-alt") || document.getElementById("governing-law"); return sanitizeGovLaw((el?.value || "").trim()); } function currentKeyInfo() { const el = document.getElementById("key-requirements-alt") || document.getElementById("key-requirements"); return (el?.value || "").trim(); } const pageContractType = "Notice of Termination".trim(); function buildCreateUrlFromQuery(q) { const appBaseURL = "https://app.genieai.co/create"; const url = `${appBaseURL}?contractType=${encodeURIComponent(pageContractType)}&governingLaw=${encodeURIComponent(currentGovLaw())}&keyInfo=${encodeURIComponent(currentKeyInfo())}&contractTitle=${encodeURIComponent(toTitleCase(q))}&showCFSModal=false`; return url; } // Debounce helper for input -> refine let inputTimer = null; function debouncedRefine(q) { if (!search) return; clearTimeout(inputTimer); inputTimer = setTimeout(() => { search.helper.setQuery(q).search(); }, INPUT_DEBOUNCE_MS); } // InstantSearch with a searchFunction to block empty/short queries search = instantsearch({ indexName: ALGOLIA_INDEX_NAME, searchClient, routing: false, searchFunction(helper) { const q = helper.state.query || ""; if (q.trim().length >= MIN_CHARS) { helper.search(); } else { // prevent network calls on start/short queries } } }); // Stats widget: update counter + pagination visibility const customStats = instantsearch.connectors.connectStats(({ nbHits }) => { const active = hasQuery(); statsEl.textContent = active ? I18N.formatStats(nbHits, DISPLAY_TOTAL_TEXT) : ''; if (paginationEl) { paginationEl.style.display = (active && nbHits > HITS_PER_PAGE) ? '' : 'none'; } }); search.addWidgets([ customStats({}), instantsearch.widgets.configure({ hitsPerPage: HITS_PER_PAGE, clickAnalytics: false }), instantsearch.widgets.hits({ container: hitsEl, templates: { item(hit) { const nameHtml = instantsearch.highlight({ attribute: 'Name', hit }); const bg = hit['Background'] || ''; const url = hit['CFS URL'] || '#'; return `

${nameHtml}

${bg}

${I18N.getTemplate}
`; }, empty: () => { const q = (input?.value || '').trim(); if (!q) return ''; const createhref = buildCreateUrlFromQuery(q); return `
${I18N.noMatches}
${I18N.generateBtn}
${I18N.subcopy}
`; } } }), instantsearch.widgets.pagination({ container: paginationEl, scrollTo: false }) ]); if (typeof window.__enableInstantSearchCSS === 'function') window.__enableInstantSearchCSS(); try { search.start(); } catch (err) { console.error('Algolia start failed', err); showAlgoliaError(err?.message || 'Algolia init failed. Check API key / referers / index.'); return; } // Hook input to debounced refine after bootstrap input.addEventListener('input', () => { const q = (input.value || '').trim(); if (q.length >= MIN_CHARS) { debouncedRefine(q); } }, { passive: true }); } // --- Lightweight local CMS filter (used only for < MIN_CHARS & as fallback) (function setupLocalCmsFilter() { if (!cmsList) return; let emptyEl = document.getElementById("no-results"); if (!emptyEl) { emptyEl = document.createElement("span"); emptyEl.id = "no-results"; emptyEl.style.display = "none"; input.parentNode?.appendChild(emptyEl); } let createBtn = document.getElementById("no-results-create-btn"); if (!createBtn) { createBtn = document.createElement("button"); createBtn.id = "no-results-create-btn"; createBtn.type = "button"; createBtn.textContent = I18N.generateBtn; createBtn.style.cssText = "display:none;margin:.5rem auto 0;padding:.6rem .9rem;border-radius:.5rem;border:1px solid rgba(0,0,0,.12);background:#fff;cursor:pointer;"; emptyEl.after(createBtn); } else { createBtn.textContent = I18N.generateBtn; createBtn.style.margin = ".5rem auto 0"; createBtn.style.display = "none"; } let subcopy = document.getElementById("no-results-subcopy"); if (!subcopy) { subcopy = document.createElement("div"); subcopy.id = "no-results-subcopy"; subcopy.textContent = I18N.subcopy; subcopy.style.cssText = "display:none;width:100%;text-align:center;margin-top:.5rem;font-family:'Roboto',system-ui,-apple-system,'Segoe UI',Roboto,'Helvetica Neue',Arial,'Noto Sans',sans-serif;font-size:.875rem;line-height:1.4;color:rgba(0,0,0,.65);"; createBtn.after(subcopy); } else { subcopy.textContent = I18N.subcopy; subcopy.style.display = "none"; subcopy.style.textAlign = "center"; } const items = Array.prototype.slice.call( cmsList.querySelectorAll(".post_collection-item, .w-dyn-item") ); if (!items.length) return; function norm(s) { return (s || "") .toLowerCase() .normalize("NFD").replace(/[\u0300-\u036f]/g, "") .replace(/[^a-z0-9\s]+/g, " ") .replace(/\s+/g, " ") .trim(); } function tokensOf(s) { return norm(s).split(" ").filter(Boolean); } function pickNameEl(item) { var el = item.querySelector("h1, h2, h3, h4, h5, h6") || item.querySelector('[class*="title" i]') || item.querySelector('[class*="name" i]'); if (el) return el; var nodes = Array.prototype.slice.call(item.querySelectorAll("*")); for (var i = 0; i < nodes.length; i++) { var n = nodes[i]; var tag = n.tagName && n.tagName.toLowerCase(); if (!tag || /^(svg|path|button|input|textarea|script|style|link|img)$/i.test(tag)) continue; var t = (n.textContent || "").trim(); if (!t) continue; var tl = t.toLowerCase(); if (tl.includes("find out more") || tl === "learn more" || tl === "read more") continue; if (t.length < 3 || t.length > 120) continue; return n; } return null; } items.forEach(function (item) { var nameEl = pickNameEl(item); var name = nameEl ? nameEl.textContent : ""; var tok = tokensOf(name); item.__nameTokens = tok; item.dataset.search = tok.join(" "); }); function setVisible(el, show) { el.style.display = show ? "" : "none"; el.setAttribute("aria-hidden", show ? "false" : "true"); } function applyFilter(q) { var qTokens = tokensOf(q); var visible = 0; if (!qTokens.length) { items.forEach((it) => setVisible(it, true)); if (emptyEl) emptyEl.style.display = "none"; createBtn.style.display = "none"; subcopy.style.display = "none"; return; } items.forEach(function (it) { var nameTokens = it.__nameTokens || []; var hit = qTokens.every(function (qt) { return nameTokens.some(function (nt) { return nt.indexOf(qt) !== -1; }); }); setVisible(it, hit); if (hit) visible++; }); const noResults = visible === 0; if (emptyEl) emptyEl.style.display = "none"; createBtn.style.display = (noResults && input.value.trim()) ? "block" : "none"; subcopy.style.display = (noResults && input.value.trim()) ? "block" : "none"; } // "Create" click (from local input) createBtn.addEventListener("click", function () { var searchTerm = (input.value || "").trim(); if (!searchTerm) return; var governingLaw = document.getElementById("governing-law-alt") || document.getElementById("governing-law"); var keyRequirements = document.getElementById("key-requirements-alt") || document.getElementById("key-requirements") || { value: "" }; var fallbackContractType = "Notice of Termination".trim(); var cType = (typeof contractType !== "undefined" && contractType) ? contractType : fallbackContractType; var encodedTitle = encodeURIComponent(toTitleCase(searchTerm)); handleFormAction( null, governingLaw, keyRequirements, null, cType, encodedTitle, createBtn ); }); // Local filtering is only active while query length < MIN_CHARS input.addEventListener('input', () => { const q = (input.value || '').trim(); if (q.length < MIN_CHARS) applyFilter(q); }, { passive: true }); // Initial local state applyFilter(""); })(); // --- Input events: swap CMS/Algolia & (lazy) bootstrap + refine input.addEventListener("input", function () { const q = (input.value || "").trim(); const useAlgolia = q.length >= MIN_CHARS; setCmsVisible(!useAlgolia); setAlgoliaVisible(useAlgolia); if (useAlgolia) { hideLocalEmptyUI(); // prevent duplicate empty state when Algolia is active bootstrapAlgolia().then(() => { // refinement handled by debouncedRefine inside bootstrap }); } else { statsEl.textContent = ""; } }, { passive: true }); input.addEventListener("keydown", function (e) { if (e.key === "Escape") { input.value = ""; setCmsVisible(true); setAlgoliaVisible(false); hideLocalEmptyUI(); // also hide local empty UI on clear statsEl.textContent = ""; } }); // --- Governing Law Sync from Breadcrumb const breadcrumb = document.getElementById("breadcrumb-1"); const breadcrumbText = (breadcrumb?.textContent || "").trim(); const governingLawDropdowns = [ document.getElementById("governing-law"), document.getElementById("governing-law-alt") ].filter(Boolean); if (governingLawDropdowns.length && breadcrumbText) { governingLawDropdowns.forEach((ddl) => { let matchFound = false; Array.from(ddl.options).forEach((opt) => { if (opt.textContent.trim() === breadcrumbText) { opt.selected = true; matchFound = true; } }); if (!matchFound) ddl.selectedIndex = 0; }); } // --- Prevent governing-law dropdown/options from appearing in search snippets (function addNoSnippetToGovLaw() { // Helper: choose the most likely wrapper safely (works across variants) function markWrapper(selectEl) { if (!selectEl) return; // Prefer a dedicated wrapper if present var wrap = selectEl.closest('.doc-gen_select-wrapper') || selectEl.closest('.doc-gen_component-content-block') || selectEl.parentElement || selectEl; wrap.setAttribute('data-nosnippet', ''); } var govPrimary = document.getElementById('governing-law'); var govAlt = document.getElementById('governing-law-alt'); markWrapper(govPrimary); markWrapper(govAlt); })(); // --- Document Generator Setup (existing "create" buttons) function resolvePageNameFromSlug() { try { var path = (window.location && window.location.pathname) ? window.location.pathname : ""; var m = path.match(/\/template\/([^\/?#]+)/i); if (m && m[1]) return decodeURIComponent(m[1]).replace(/-/g, " "); var canonical = document.querySelector('link[rel="canonical"]')?.href || ""; var ogUrl = document.querySelector('meta[property="og:url"]')?.getAttribute("content") || ""; var urlToParse = canonical || ogUrl || ""; if (urlToParse) { try { var u = new URL(urlToParse); var m2 = u.pathname.match(/\/template\/([^\/?#]+)/i); if (m2 && m2[1]) return decodeURIComponent(m2[1]).replace(/-/g, " "); } catch(e){} } } catch(e){} var headingEl = document.getElementById("heading-5"); var hText = (headingEl?.textContent || "").trim(); if (hText) return hText; return (document.title || "").trim(); } const contractType = "Notice of Termination".trim(); const rawContractTitle = resolvePageNameFromSlug(); const contractTitle = encodeURIComponent(toTitleCase(rawContractTitle)); const templateLinkEl = document.getElementById("template-link"); document.body.addEventListener("click", function (event) { let targetButton = event.target; while (targetButton && targetButton !== document.body) { if ( targetButton.id === "create-document" || targetButton.id === "create-document-alt" || targetButton.id === "create-document-alt-secondary" || targetButton.id === "create-document-image" || targetButton.id === "create-document-header" || targetButton.id === "create-document-header-primary" || targetButton.id === "create-document-header-secondary" ) { event.preventDefault(); event.stopImmediatePropagation(); let formId, governingLawId, keyRequirementsId; if (targetButton.id === "create-document") { formId = "document-generator"; governingLawId = "governing-law"; keyRequirementsId = "key-requirements"; } else { formId = "document-generator-alt"; governingLawId = "governing-law-alt"; keyRequirementsId = "key-requirements-alt"; } const form = document.getElementById(formId); const governingLaw = document.getElementById(governingLawId); const keyRequirements = document.getElementById(keyRequirementsId); if (form && governingLaw && keyRequirements) { handleFormAction( form, governingLaw, keyRequirements, templateLinkEl, contractType, contractTitle, targetButton ); } return; } targetButton = targetButton.parentElement; } }, false); function setupDocumentGeneratorForm(formId, governingLawId, keyRequirementsId) { const form = document.getElementById(formId); const governingLaw = document.getElementById(governingLawId); const keyRequirements = document.getElementById(keyRequirementsId); if (!form || !governingLaw || !keyRequirements) return; const observer = new IntersectionObserver( (entries, obs) => { if (entries[0]?.isIntersecting) obs.disconnect(); }, { threshold: 0.1 } ); observer.observe(form); form.setAttribute("data-wf-ignore", "true"); form.addEventListener("keydown", function (event) { if (event.key === "Enter") event.preventDefault(); }); } function handleFormAction( form, governingLaw, keyRequirements, templateLinkEl, contractType, contractTitle, sourceEl ) { const governingLawValue = governingLaw?.value?.trim?.() || ""; const gov = sanitizeGovLaw(governingLawValue); const keyInfoValue = keyRequirements?.value?.trim?.() || ""; if (!gov) return; setTimeout(() => { trackOnce("visitor website-generator hero-create submit-clicked", { keyRequirements: keyInfoValue, governingLaw: gov, contractType, contractTitle: decodeURIComponent(contractTitle), pageType: "Generator" }); }, 300); const appBaseURL = "https://app.genieai.co/create"; const templateLinkURL = templateLinkEl?.getAttribute?.("data-template-link"); if (templateLinkURL && templateLinkURL.trim() && !keyInfoValue && form) { safeOpenOnce(sourceEl, templateLinkURL.trim(), "_blank"); return; } const redirectURL = `${appBaseURL}?contractType=${encodeURIComponent( contractType )}&governingLaw=${encodeURIComponent( gov )}&keyInfo=${encodeURIComponent( keyInfoValue )}&contractTitle=${contractTitle}&showCFSModal=false`; safeOpenOnce(sourceEl, redirectURL, "_blank"); } setupDocumentGeneratorForm("document-generator", "governing-law", "key-requirements"); setupDocumentGeneratorForm("document-generator-alt", "governing-law-alt", "key-requirements-alt"); // --- Review Document Click Tracking const reviewDocumentEl = document.getElementById("review-document"); if (reviewDocumentEl) { reviewDocumentEl.addEventListener("click", function () { trackOnce("visitor website-generator hero-review upload-clicked"); }); } }); // --- CWV Improvement: Defer Webflow ix2 window.Webflow ||= []; window.Webflow.push(function () { (window.requestIdleCallback || function (cb) { setTimeout(cb, 1); })(() => { try { const ix2 = Webflow.require?.("ix2"); if (ix2?.init) ix2.init(); } catch (e) { console.warn("Webflow ix2 defer failed:", e); } }); }); // ---------- Styles ---------- function injectAlgoliaStyles() { if (document.getElementById("algolia-hit-styles")) return; const css = ` #algolia-hits { width: 100%; } /* Responsive 4-col grid on desktop */ #algolia-hits .ais-Hits-list { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 32px; list-style: none; padding: 0; margin: 0; } /* Remove Algolia theme wrapper spacing */ #algolia-hits .ais-Hits-item { width: 100% !important; margin: 0 !important; border: 0 !important; padding: 0 !important; background: transparent !important; box-shadow: none !important; } @media (max-width: 991px) { #algolia-hits .ais-Hits-list { grid-template-columns: repeat(2, minmax(0, 1fr)); } } @media (max-width: 599px) { #algolia-hits .ais-Hits-list { grid-template-columns: 1fr; } } /* Card */ .alg-card { border: 1px solid rgba(0,0,0,.08); border-radius: 12px; padding: 16px; background: #fff; box-shadow: 0 1px 2px rgba(0,0,0,.04); display: flex; flex-direction: column; height: 100%; } .alg-card h3 { margin: 0 0 8px 0; font-size: 1rem; line-height: 1.3; } .alg-card p { margin: .25rem 0 .9rem 0; color: rgba(0,0,0,.75); font-size: .95rem; line-height: 1.45; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 4; /* clamp to 4 lines */ overflow: hidden; } .alg-hit-title { color: inherit; text-decoration: none; } .alg-hit-title:hover { text-decoration: underline; } /* Purple pill button (#673AB7), left-aligned, not full-width */ .alg-btn-primary { display: inline-flex; align-items: center; justify-content: center; min-height: 44px; padding: .6rem 1.25rem; border-radius: 9999px; background: #673AB7; color: #fff !important; text-decoration: none; font-weight: 600; border: none; box-shadow: 0 1px 2px rgba(0,0,0,.06); transition: filter .15s ease, transform .02s ease; margin-top: auto; /* stick to bottom of card */ } .alg-btn-primary:hover { filter: brightness(0.95); } .alg-btn-primary:active { transform: translateY(1px); } .alg-btn-primary:focus { outline: 2px solid rgba(103,58,183,.35); outline-offset: 2px; } `; const style = document.createElement('style'); style.id = "algolia-hit-styles"; style.textContent = css; document.head.appendChild(style); } }