Terms and Conditions

Product Specific Terms

Effective Date: August 1, 2020

These Product Specific Terms, along with our Terms of Service and any policies or other legal terms referenced herein or therein, apply to your access to and use of certain specific products or services available via the Services. These Product Specific Terms are incorporated by reference into our Terms of Service. Any capitalized terms (or lowercase terms specifically defined in our Terms of Service) not defined in these Product Specific Terms have the meanings set forth in our Terms of Service. Except as otherwise expressly set forth in these Product Specific Terms, in the event of a conflict or inconsistency, our Terms of Service shall govern, followed by these Product Specific Terms. If you have any comments or questions about these Product Specific Terms, feel free to contact us.

Table of Contents
  1. eCommerce
  2. Domains
  3. Oryxcloud Select
  4. Getty Images
  5. Term and Termination
  6. Modifications to the Product Specific Terms
  7. Appendix I - Consultative Services Schedule for Select Plans
1. eCommerce
  1. eCommerce Responsibilities : The Services include features that enable you to provide or sell products and services to, or otherwise collect payments from, your End Users (such activities, “Your eCommerce”). We’re not a party to, and we aren’t liable for, Your eCommerce. You're solely responsible for Your eCommerce, and compliance with any laws or regulations related to it, including without limitation the following:
    1. Taxes : You're solely responsible for: (a) all Taxes and fees associated with Your eCommerce, including without limitation any Taxes related to the purchase or sale of products or services in connection with Your eCommerce; (b) collecting, reporting and remitting required Taxes to relevant government authorities; (c) informing your End Users of required Taxes, and providing them with invoices as required by applicable law; (d) monitoring distance sales thresholds in the EU and other indirect Taxes (such as value-added tax or goods and services tax) and registration thresholds in the countries where you have customers or where you ship goods to or provide services to; and (e) registering for indirect Taxes in countries where you are required to register. You also agree that any tax estimates, reporting or related materials that we may provide via the Services are for illustration purposes only, and you may not rely on them to comply with your tax obligations. We do not give tax advice, and nothing we communicate should be interpreted as such.
    2. Fulfillment And Delivery : You're solely responsible for fulfilling and delivering your products and services to your End Users.
    3. Claims And Warranties : You're solely responsible for any claims or warranties you make in connection with Your eCommerce and any claims made by End Users against you.
    4. Customer Service : You're solely responsible for handling any comments or complaints related to Your eCommerce, including without limitation any issues related to payments, promotions, refunds or chargebacks. You agree to provide accurate and complete contact information on Your Sites so that your End Users can submit comments or complaints to you.
    5. Site Terms, Policies And Legal Compliance : In addition to your obligations set forth in the Terms of Service to provide certain policies, you agree to post and make clearly available on Your Sites, and any other terms or policies that may be required by applicable law, and you warrant that Your Sites and Your eCommerce and your conduct will comply with all applicable laws and regulations. You agree that we do not and will not provide any legal advice regarding such terms, policies or compliance.
    6. Consumer, eCommerce And Other Laws : You are also responsible for complying with any consumer, eCommerce, products, goods, services and related laws.
  2. eCommerce Restrictions : You may not offer or sell any products or services which, in our sole discretion: (a) we consider hazardous, counterfeit, stolen, fraudulent, abusive or adverse to our interests or reputation; (b) are prohibited for sale, distribution or use; or (c) otherwise fail to comply with any applicable laws or regulations, including without limitation with respect to intellectual property, trade secrets, privacy or publicity rights, consumer protection, shipping or transportation, product safety or trade regulations or export controls, regulations or sanctions.
  3. eCommerce Suspensions : While we’d prefer not to, we may, at any time and in our sole discretion, and without any notice to you, suspend, restrict or disable access to or remove your Account, Your Sites or Your eCommerce, without any liability to you or to any End Users, including without limitation for any loss of profits, revenue, data, goodwill or other intangible losses (except where prohibited by applicable law). For example, we may suspend Your eCommerce if you’re violating our Terms of Service.
  4. eCommerce Payment Processors : To accept payments from your End Users in connection with Your eCommerce, you may integrate Your Sites with third party payment processors (“eCommerce Payment Processors”). Your relationship with such eCommerce Payment Processors is governed by those eCommerce Payment Processors’ terms and policies. We don’t control and aren’t liable for any eCommerce Payment Processors, or for any transaction you may enter into with or through any eCommerce Payment Processors. eCommerce Payment Processors are a Third Party Service, as defined in our Terms of Service. While we will try to provide advance notice, you agree that we may, at any time and in our sole discretion, and without any notice to you, suspend, restrict or disable access to or remove from the Services, any eCommerce Payment Processors, without any liability to you or to any End Users, including without limitation for any loss of profits, revenue, data, goodwill or other intangible losses (except where prohibited by applicable law). Your eCommerce Payment Processors may provide invoices for any transaction fees associated with Your eCommerce transactions.
2. Domains
  1. Definitions
    1. “ICANN” means the Internet Corporation for Assigned Names and Numbers (https://icann.org).
    2. A “Registrar” under ICANN rules and policies means a company that offers domain name registration services to registrants in generic top-level domains (gTLDs). We, through our Oryx Cloud group company affiliate Oryxcloud Domains LLC, act as a Registrar under certain circumstances (as further described below).
    3. A “Reseller” under ICANN rules and policies means a company that offers domain name registration services through a third party Registrar. We act as a Reseller under certain circumstances (as further described below). When we act as a Reseller, (a) we are not acting as a Registrar, and (b) the third party Registrar with whom we work is a Third Party Service (as that term is defined in our Terms of Service), and is Tucows, Inc. (“Tucows”).
  2. Registrar ServicesWhere we act as a Registrar for your domain name registrations, renewals and transfers, you agree to the Oryxcloud Domain Registration Agreement (the “DRA”). Your breach of our DRA is a breach of our Terms of Service.
  3. Reseller Services : Where we act as a Reseller for your domain name registrations, renews and transfers, you are subject to the Tucows Terms and Conditions (the “Tucows Terms”). Your breach of the Tucows Terms is a breach of our Terms of Service.
  4. Applicability : We inform you whether we will act as a Registrar or Reseller for a domain name. You can also determine via the Services whether we act as a Registrar or Reseller for a particular domain name.
  5. ICANN : Your use of our domain services is subject to the policies, including without limitation the dispute resolution policies, of ICANN. Your rights and responsibilities as a domain name registrant under ICANN’s 2009 Registrar Accreditation Agreement are summarized here. You can learn more about domain name registration in general here. Country code top level domain names may not be subject to ICANN policies. In such cases, the applicable policies are set forth in our DRA or the Tucows Terms, as applicable.
  6. Transfers, Renewals And Refunds : You may not be able to transfer a domain name for the first sixty (60) days following registration. For renewals, we or our third party Registrar will try to provide you notice thirty (30) days before, five (5) days before and three (3) days after your scheduled domain renewal date. However, you agree that renewing your domain is solely your responsibility. If you cancel a domain name purchase within the first five (5) days following your purchase, if permitted by our DRA or the Tucows Terms, we may provide a full refund. However, we don't offer refunds for domain renewals or transfers.
3. Oryxcloud Select
  1. About the Select Services :
    1. Applicability : This Section 3 applies only to purchasers of our “Select” plan (the “Select Plan”) and cover your use of and access to the services provided under the Select Plan (the “Select Services”). The Select Services include the services listed in the Consultative Services Schedule in Appendix I below (the “Consultative Services”), which may be modified from time to time pursuant to these Product Specific Terms. Some or all Consultative Services may be limited by a fixed number of hours for a fixed period of time as specified in your Select Plan subscription. Hours not used during the applicable period of time will not carry over to the following period and will be forfeited, and you will not be entitled to any refund, discount or reimbursement for any such unused Consultative Services.
    2. Account Managers : We will assign an “Account Manager” that: (a) will serve as your primary point of contact at Oryxcloud for your Select Plan; (b) will provide certain Select Services; and (c) may provide or otherwise coordinate the Consultative Services. We may from time to time change the Account Manager assigned to your Select Plan.
    3. Account Representatives : Your “Account Representatives” are your employees or agents that you designate to be your primary points of contact for the Select Services. You may assign three (3) such Account Representatives. You agree to make all your communications with Oryxcloud regarding the Select Services through your Account Representatives. Use of certain Select Services may be limited to your Account Representatives (including access to the Consultative Services).
    4. User Content : Without limiting the generality of our Terms of Service, User Content includes information provided to us (whether through email, webforms or any other means) in connection with the Consultative Services.
  2. Your Responsibilities, Representations And Warranties :
    1. Your Select Services Responsibilities : You agree to: (a) provide in a timely manner and in the form requested by Oryxcloud all documents, materials and information reasonably required in connection with our provision of the Select Services to you; (b) ensure that all such documents, materials and information are accurate and complete; and (c) provide in a timely manner any other cooperation requested by Oryxcloud in connection with our provision of the Select Services to you. We are not liable for any delay in providing or failure to provide the Select Services to the extent caused, directly or indirectly, by your breach of the immediately preceding sentence or by any act or omission of you, your Account Representatives, your agents, subcontractors, consultants or employees.
    2. Your Select Services Representation and Warranties : You represent, warrant and covenant that: (a) if you are agreeing to the Product Specific Terms and the Terms of Service on behalf of an organization, then (i) you have all necessary right and authority to so bind that organization to the Product Specific Terms and Terms of Service, and (ii) you will provide any and all documentation we deem necessary to confirm the aforementioned right and authority; and (b) the Account Representatives can act on your behalf or otherwise represent you, and Oryxcloud may rely on the information and direction provided by any Account Representative.
  3. Disclaimer of Select Services : Without limiting the generality of any disclaimers in the Terms of Service: (a) Oryxcloud makes no warranty or representation regarding any results or outcomes that may be obtained through the Select Services, or that any result or outcome will meet your requirements, expectations or objectives; (b) Oryxcloud does not endorse any particular use, practice or course of action; (c) the Select Services are provided as an informational and educational resource, and on an “as is” and “as available” basis; and (d) you will not rely on advice or information provided through the Select Services.
  4. Modifications to the Services : The Select Services will evolve as we refine, add and potentially remove features and services with the needs of our users. Oryxcloud may update and/or discontinue certain features or other aspects of Select Services from time to time. We’ll try to inform you of any changes with reasonable notice so you can adjust your use of the Select Services, but you agree that we have no obligation to do so. In addition, to the extent that Oryxcloud discontinues or cancels any of the Services set out in the Consultative Services Schedule in Appendix I below, such discontinuation or cancellation shall take effect upon the renewal of your then-current subscription period, and in subsequent renewal periods, you will be automatically transferred to the then-current Select Plan of comparable scope.
  5. Additional Select Terms :
    1. Cancelling Automatic Subscription Renewals : Notwithstanding anything to the contrary in the Terms of Service or elsewhere in the Services, cancellation of auto-renewal of the Select Services can only be requested by contacting your Account Manager seven (7) business days prior to the end of your then-current subscription term.
    2. Minimum Commitment : Except otherwise expressly agreed upon by us in writing, the minimum subscription period for Select Plans shall be twelve (12) months.
    3. Publicity : We may ask you to participate in a case study or provide a testimonial relating to your use and/or experience with the Select Services. Such case study or testimonial may be accessible or distributed publicly, including on our websites, through our advertising partners, through marketing materials and/or in white paper form. Your participation in any such case study or testimonial is voluntary, and should you agree to participate, you will be able to approve the materials prior to their finalization, provided that your approval shall not be unreasonably delayed or withheld (which may be determined based, among other factors, on the circumstances of your agreement to participate, commitments or promises to participate and the extent of your involvement). For the avoidance of doubt, nothing in this section shall be construed to limit or derogate our rights set forth in the Terms of Service.
    4. Select Plans may not be eligible for all discounts, promotions or offers that we may advertise or otherwise provide to other subscription plans.
4. Getty Images

Our Image Terms apply if you license Getty Images via the Services and cover how you may use such licensed images with the Services.

5. Term and Termination.

These Product Specific Terms will remain in effect until our Terms of Service are terminated pursuant to the terms therein. All sections of these Product Specific Terms that by their nature should survive termination shall survive termination, including without limitation those sections relating to your responsibilities, your representations, your warranties, and disclaimers of any of the products or Services referred to herein.

6. Modifications to Product Specific Terms

We may modify these Product Specific Terms from time to time, and will post the most current version on our site. If a modification meaningfully reduces your rights, we may notify you in accordance with the procedures set forth in our Terms of Service. By continuing to use or access any of the products or Services referred to herein after any modifications come into effect, you agree to be bound by the modified Product Specific Terms and price changes. If you disagree with our changes, then you must stop using the applicable Services and cancel the applicable Paid Services.

Appendix I - Consultative Services Schedule for Select Plans
  • Tailored Onboarding
  • Private Product Trainings
  • Quarterly Site Reviews
  • SEO Consultations
  • Technical Consultations
  • Design Consultation
// LeadCenter.ai Quiz Application JavaScript class QuizApp { constructor() { this.currentStep = 0; this.totalSteps = 0; this.answers = {}; this.correctAnswerTriggered = false; this.currentQuestionAnsweredCorrectly = false; this.questions = [ // Personal Details Questions { id: 1, question: "Let's start with some basic information about you and your company", type: "personal_details", fields: [ { name: "name", label: "Name", type: "text", required: true, placeholder: "Enter your full name" }, { name: "email", label: "Email Address", type: "email", required: true, placeholder: "Enter your email address" }, { name: "phone", label: "Phone Number", type: "tel", required: true, placeholder: "Enter your phone number" }, { name: "company", label: "Company Name", type: "text", required: true, placeholder: "Enter your company name" }, { name: "employees", label: "Number of Employees", type: "select", required: true, options: [ "1-5", "6-10", "11-20", "20-50", "More than 50 employees" ] } ] }, // Business Questions { id: 2, question: "Which of the following AE Advisors use LeadCenter.AI?", options: [ "Oak Harvest Financial Group", "Howard Bailey", "West Advisory Group", "CA Educators", "Legato Financials", "Slagle Financials", "Freedom Financials", "Comprehensive Advisors", "Jehm Wealth", "Wealth Planning Network", ], type: "multiple" }, { id: 3, question: "Which challenges does LeadCenter.AI solve for financial advisors?", options: [ "Reducing manual data entry", "Breaking silos between marketing, sales, and operations", "Automating tasks to save valuable time", "Engaging more leads, faster", "Boosting lead-to-appointment conversions", "Driving higher revenue", "Simplifying reports and insights", ], type: "multiple" }, { id: 4, question: "Which of the following functions does LeadCenter.AI automate for financial advisors?", options: [ "Capturing leads from all sources (forms, phone calls, seminar registrations)", "Pushing leads to Redtail, Wealthbox, and Salesforce", "Verifying lead phone numbers and emails", "Transcribing calls and attaching them to contact records", "Creating landing pages and seminar forms on the advisor's website", "Sending client review reminders so clients can book their own appointments", "Producing advisor-specific reports (production reports, 1st appointment conversion, ROI, customer acquisition cost, etc.)", "Capturing notes & tasks from Zoom calls under the contact record", "Lead engagement in the sales funnel by triggering emails & texts based on lead criteria" ], type: "multiple" }, { id: 5, question: "How much can an RIA with 5 employees save, boost revenue, and cut software licensing costs by using LeadCenter.AI?", options: [ "Save $10K annually, does not boost revenue, and not cut in software costs", "Save $100K annually, boost revenue by 1x, and cut software costs by $5K", "Save $223K annually by reclaiming up to 434 workdays, boost revenue by up to 3x, and cut software licensing costs by up to $22K" ], type: "single" } ]; // Banner messages for each question this.bannerMessages = { 1: { success: "That's the correct answer! Great job!", wrong: "That is a wrong answer, please try again" }, 2: { success: "Correct! Well done! Today, more than 1,000 advisors rely on LeadCenter.AI. The platform achieved 950% year-over-year growth last year—clear proof of the value it delivers to advisors", wrong: "That is a wrong answer, please try again" }, 3: { success: "That’s correct! LeadCenter.AI was designed in collaboration with financial advisors, built around their feedback to directly address these challenges", wrong: "That is a wrong answer, please try again" }, 4: { success: "That’s correct! LeadCenter.AI streamlines over 400 processes, empowering financial advisors to save time and focus on their clients.", wrong: "That is a wrong answer, please try again" }, 5: { success: "That’s correct! With LeadCenter.AI, advisors eliminate manual work, freeing up valuable time to focus on driving revenue and serving their clients.", wrong: "That is a wrong answer, please try again" } }; this.init(); } init() { this.totalSteps = this.questions.length; this.renderQuestions(); this.updateProgress(); } renderQuestions() { const container = document.querySelector('.question-container'); container.innerHTML = ''; this.questions.forEach((question, index) => { const questionElement = this.createQuestionElement(question, index); container.appendChild(questionElement); }); } createQuestionElement(question, index) { const questionDiv = document.createElement('div'); questionDiv.className = `question-step ${index === 0 ? 'active' : ''}`; questionDiv.id = `question-${question.id}`; questionDiv.style.display = index === 0 ? 'block' : 'none'; const questionCard = document.createElement('div'); questionCard.className = 'question-card'; const questionTitle = document.createElement('h3'); questionTitle.className = 'question-title'; questionTitle.textContent = question.question; questionCard.appendChild(questionTitle); if (question.type === 'personal_details') { // Create form for personal details const formContainer = document.createElement('div'); formContainer.className = 'personal-details-form'; question.fields.forEach(field => { const fieldGroup = document.createElement('div'); fieldGroup.className = 'form-group mb-3'; const label = document.createElement('label'); label.className = 'form-label'; label.textContent = field.label; if (field.required) { label.innerHTML += ' *'; } let input; if (field.type === 'select') { input = document.createElement('select'); input.className = 'form-control'; input.name = `question-${question.id}-${field.name}`; input.id = `q${question.id}-${field.name}`; input.required = field.required; // Add default option const defaultOption = document.createElement('option'); defaultOption.value = ''; defaultOption.textContent = `Select ${field.label.toLowerCase()}`; input.appendChild(defaultOption); // Add options field.options.forEach(option => { const optionElement = document.createElement('option'); optionElement.value = option; optionElement.textContent = option; input.appendChild(optionElement); }); } else { input = document.createElement('input'); input.type = field.type; input.className = 'form-control'; input.name = `question-${question.id}-${field.name}`; input.id = `q${question.id}-${field.name}`; input.placeholder = field.placeholder; input.required = field.required; } fieldGroup.appendChild(label); fieldGroup.appendChild(input); // Add email validation for email field (after input is added to fieldGroup) if (field.type === 'email') { this.addEmailValidation(input, fieldGroup); } // Add phone formatting for phone field if (field.type === 'tel') { this.addPhoneFormatting(input); } // Add event listener to update Next button state for personal details if (question.type === 'personal_details') { input.addEventListener('input', () => { this.updateNavigationButtons(); }); input.addEventListener('change', () => { this.updateNavigationButtons(); }); } formContainer.appendChild(fieldGroup); }); questionCard.appendChild(questionTitle); questionCard.appendChild(formContainer); } else { // Create options for regular questions const optionsList = document.createElement('ul'); optionsList.className = 'question-options'; question.options.forEach((option, optionIndex) => { const optionItem = document.createElement('li'); optionItem.className = 'question-option'; const input = document.createElement('input'); input.type = question.type === 'multiple' ? 'checkbox' : 'radio'; input.className = 'option-input'; input.name = `question-${question.id}`; input.value = option; input.id = `q${question.id}-option${optionIndex}`; // Add event listener for answer detection (correct or wrong) input.addEventListener('change', (e) => { if (question.id === 2) { // Special handling for question 2 - multiple choice, all options must be selected this.checkQuestion2Completion(); } else if (question.id === 3) { // Special handling for question 3 - multiple choice, all options must be selected this.checkQuestion3Completion(); } else if (question.id === 4) { // Special handling for question 4 - multiple choice, all options must be selected this.checkQuestion4Completion(); } else { // Regular single choice questions if (e.target.checked) { // Check if this is a correct answer if (question.id === 5 && option === 'Save $223K annually by reclaiming up to 434 workdays, boost revenue by up to 3x, and cut software licensing costs by up to $22K') { // Correct answer console.log('Correct answer selected!', e.target.checked); this.currentQuestionAnsweredCorrectly = true; if (!this.correctAnswerTriggered) { this.correctAnswerTriggered = true; this.hideWrongAnswerBanner(); this.showSuccessBanner(); this.playFireworks(); } // Don't update navigation buttons - let popup handle progression } else { // Wrong answer console.log('Wrong answer selected!', option); this.currentQuestionAnsweredCorrectly = false; this.hideSuccessBanner(); this.showWrongAnswerBanner(); this.updateNavigationButtons(); } } } }); const label = document.createElement('label'); label.className = 'option-label'; label.htmlFor = `q${question.id}-option${optionIndex}`; label.textContent = option; // Add click listener to label for answer detection label.addEventListener('click', () => { setTimeout(() => { if (question.id === 2) { // Special handling for question 2 - multiple choice, all options must be selected this.checkQuestion2Completion(); } else if (question.id === 3) { // Special handling for question 3 - multiple choice, all options must be selected this.checkQuestion3Completion(); } else if (question.id === 4) { // Special handling for question 4 - multiple choice, all options must be selected this.checkQuestion4Completion(); } else { // Regular single choice questions if (input.checked) { // Check if this is a correct answer if (question.id === 5 && option === 'Save $223K annually by reclaiming up to 434 workdays, boost revenue by up to 3x, and cut software licensing costs by up to $22K') { // Correct answer console.log('Label clicked for correct answer'); this.currentQuestionAnsweredCorrectly = true; if (!this.correctAnswerTriggered) { console.log('Input is checked, triggering effects'); this.correctAnswerTriggered = true; this.hideWrongAnswerBanner(); this.showSuccessBanner(); this.playFireworks(); } // Don't update navigation buttons - let popup handle progression } else { // Wrong answer console.log('Label clicked for wrong answer'); this.currentQuestionAnsweredCorrectly = false; this.hideSuccessBanner(); this.showWrongAnswerBanner(); this.updateNavigationButtons(); } } } }, 100); }); optionItem.appendChild(input); optionItem.appendChild(label); optionsList.appendChild(optionItem); }); questionCard.appendChild(optionsList); // Add hint for specific questions (after options) // Hint removed as requested } questionDiv.appendChild(questionCard); return questionDiv; } updateProgress() { const progressBar = document.getElementById('progress-bar'); const progressText = document.getElementById('progress-text'); const percentage = ((this.currentStep + 1) / this.totalSteps) * 100; progressBar.style.width = `${percentage}%`; progressText.textContent = `Question ${this.currentStep + 1} of ${this.totalSteps}`; } showQuestion(step) { // Hide all questions document.querySelectorAll('.question-step').forEach(question => { question.style.display = 'none'; question.classList.remove('active'); }); // Show current question const currentQuestion = document.getElementById(`question-${this.questions[step].id}`); if (currentQuestion) { currentQuestion.style.display = 'block'; currentQuestion.classList.add('active'); } // Reset flags for new question this.correctAnswerTriggered = false; this.currentQuestionAnsweredCorrectly = false; // Hide any existing banners this.hideSuccessBanner(); this.hideWrongAnswerBanner(); // Update navigation buttons this.updateNavigationButtons(); // Scroll to top of the page window.scrollTo({ top: 0, behavior: 'smooth' }); } updateNavigationButtons() { const prevBtn = document.getElementById('prev-btn'); const nextBtn = document.getElementById('next-btn'); // Show/hide previous button if (this.currentStep === 0) { prevBtn.style.display = 'none'; } else { prevBtn.style.display = 'block'; } // Update next button text if (this.currentStep === this.totalSteps - 1) { nextBtn.innerHTML = 'Submit Quiz'; } else { nextBtn.innerHTML = 'Next'; } // Disable Next button if current question hasn't been answered correctly const currentQuestion = this.questions[this.currentStep]; if (currentQuestion && currentQuestion.type === 'personal_details') { // For personal details, check if all required fields are filled const allFieldsFilled = this.validateCurrentQuestion(); if (allFieldsFilled) { nextBtn.disabled = false; nextBtn.classList.remove('btn-disabled'); } else { nextBtn.disabled = true; nextBtn.classList.add('btn-disabled'); } } else if (currentQuestion && (currentQuestion.id === 2 || currentQuestion.id === 3 || currentQuestion.id === 4)) { // For questions 2, 3, and 4, enable when all options are selected if (this.currentQuestionAnsweredCorrectly) { nextBtn.disabled = false; nextBtn.classList.remove('btn-disabled'); } else { nextBtn.disabled = true; nextBtn.classList.add('btn-disabled'); } } else { // For other quiz questions, disable until correct answer is selected if (this.currentQuestionAnsweredCorrectly) { nextBtn.disabled = false; nextBtn.classList.remove('btn-disabled'); } else { nextBtn.disabled = true; nextBtn.classList.add('btn-disabled'); } } } saveAnswer() { const currentQuestion = this.questions[this.currentStep]; const questionId = currentQuestion.id; if (currentQuestion.type === 'personal_details') { this.answers[questionId] = {}; currentQuestion.fields.forEach(field => { const input = document.querySelector(`input[name="question-${questionId}-${field.name}"], select[name="question-${questionId}-${field.name}"]`); this.answers[questionId][field.name] = input ? input.value : ''; }); } else if (currentQuestion.type === 'multiple') { const checkboxes = document.querySelectorAll(`input[name="question-${questionId}"]:checked`); this.answers[questionId] = Array.from(checkboxes).map(cb => cb.value); } else { const radio = document.querySelector(`input[name="question-${questionId}"]:checked`); this.answers[questionId] = radio ? radio.value : null; } } loadAnswer() { const currentQuestion = this.questions[this.currentStep]; const questionId = currentQuestion.id; const savedAnswer = this.answers[questionId]; if (savedAnswer) { if (currentQuestion.type === 'personal_details') { currentQuestion.fields.forEach(field => { const input = document.querySelector(`input[name="question-${questionId}-${field.name}"], select[name="question-${questionId}-${field.name}"]`); if (input && savedAnswer[field.name]) { input.value = savedAnswer[field.name]; } }); } else if (currentQuestion.type === 'multiple') { savedAnswer.forEach(answer => { const checkbox = document.querySelector(`input[name="question-${questionId}"][value="${answer}"]`); if (checkbox) checkbox.checked = true; }); } else { const radio = document.querySelector(`input[name="question-${questionId}"][value="${savedAnswer}"]`); if (radio) radio.checked = true; } } } validateCurrentQuestion() { const currentQuestion = this.questions[this.currentStep]; const questionId = currentQuestion.id; if (currentQuestion.type === 'personal_details') { // Check all required fields are filled for (let field of currentQuestion.fields) { if (field.required) { const input = document.querySelector(`input[name="question-${questionId}-${field.name}"], select[name="question-${questionId}-${field.name}"]`); if (!input || !input.value.trim()) { return false; } // Validate email format if it's an email field if (field.type === 'email') { const emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/; if (!emailRegex.test(input.value.trim())) { return false; } } } } return true; } else if (currentQuestion.type === 'multiple') { if (questionId === 2 || questionId === 3 || questionId === 4) { // For questions 2, 3, and 4, only allow progression if all options are selected const allInputs = document.querySelectorAll(`input[name="question-${questionId}"]`); const checkedInputs = document.querySelectorAll(`input[name="question-${questionId}"]:checked`); return checkedInputs.length === allInputs.length; } else { // For other multiple choice questions, just check if at least one is selected const checkboxes = document.querySelectorAll(`input[name="question-${questionId}"]:checked`); return checkboxes.length > 0; } } else { const radio = document.querySelector(`input[name="question-${questionId}"]:checked`); return radio !== null; } } nextQuestion() { if (!this.validateCurrentQuestion()) { const currentQuestion = this.questions[this.currentStep]; // Don't show validation messages for questions 2, 3, and 4 if (currentQuestion.id === 2 || currentQuestion.id === 3 || currentQuestion.id === 4) { return; } let message = 'Please complete all required fields before proceeding.'; if (currentQuestion.type === 'personal_details') { message = 'Please fill in all required fields and check your email format.'; } else if (currentQuestion.type === 'multiple') { message = 'Please select at least one option before proceeding.'; } else { message = 'Please select an answer before proceeding.'; } this.showValidationMessage(message); return; } this.saveAnswer(); if (this.currentStep < this.totalSteps - 1) { this.currentStep++; this.showQuestion(this.currentStep); this.loadAnswer(); this.updateProgress(); } else { this.submitQuiz(); } } previousQuestion() { if (this.currentStep > 0) { this.saveAnswer(); this.currentStep--; this.showQuestion(this.currentStep); this.loadAnswer(); this.updateProgress(); } } showValidationMessage(message) { // Remove existing validation message const existingMessage = document.querySelector('.validation-message'); if (existingMessage) { existingMessage.remove(); } // Create new validation message const validationDiv = document.createElement('div'); validationDiv.className = 'alert alert-warning validation-message'; validationDiv.innerHTML = `${message}`; // Insert after current question const currentQuestion = document.querySelector('.question-step.active'); currentQuestion.appendChild(validationDiv); // Auto-remove after 3 seconds setTimeout(() => { if (validationDiv.parentNode) { validationDiv.remove(); } }, 3000); } submitQuiz() { this.saveAnswer(); // Show loading state const nextBtn = document.getElementById('next-btn'); const originalText = nextBtn.innerHTML; nextBtn.innerHTML = ' Submitting...'; nextBtn.disabled = true; // Simulate API call setTimeout(() => { this.showThankYouStep(); }, 2000); } showThankYouStep() { // Hide quiz steps document.getElementById('quiz-steps').style.display = 'none'; // Show thank you step document.getElementById('step-thankyou').style.display = 'block'; document.getElementById('step-thankyou').classList.add('active'); // Log answers for debugging console.log('Quiz Answers:', this.answers); } restartQuiz() { // Reset state this.currentStep = 0; this.answers = {}; this.correctAnswerTriggered = false; this.currentQuestionAnsweredCorrectly = false; // Hide thank you step document.getElementById('step-thankyou').style.display = 'none'; document.getElementById('step-thankyou').classList.remove('active'); // Show intro step document.getElementById('step-intro').style.display = 'block'; document.getElementById('step-intro').classList.add('active'); // Reset form document.querySelectorAll('.option-input').forEach(input => { input.checked = false; }); // Hide banners this.hideSuccessBanner(); this.hideWrongAnswerBanner(); this.updateProgress(); } showSuccessBanner() { console.log('Showing success popup...'); const popup = document.getElementById('success-popup'); if (popup) { // Get current question and update text dynamically const currentQuestion = this.questions[this.currentStep]; const message = this.bannerMessages[currentQuestion.id]?.success || "That's the correct answer! Great job!"; // Update the popup text const popupText = document.getElementById('success-popup-text'); if (popupText) { popupText.textContent = message; } // Update button text based on question number const nextButton = popup.querySelector('button[onclick="proceedToNextQuestion()"]'); if (nextButton) { if (currentQuestion.id === 5) { nextButton.innerHTML = 'Submit Quiz '; } else { nextButton.innerHTML = 'Next Question '; } } // Show the modal using Bootstrap const modal = new bootstrap.Modal(popup); modal.show(); console.log('Success popup displayed'); } else { console.error('Success popup element not found!'); } } hideSuccessBanner() { const popup = document.getElementById('success-popup'); if (popup) { const modal = bootstrap.Modal.getInstance(popup); if (modal) { modal.hide(); } } } showWrongAnswerBanner() { console.log('Showing wrong answer banner...'); const banner = document.getElementById('wrong-answer-banner'); if (banner) { // Get current question and update text dynamically const currentQuestion = this.questions[this.currentStep]; const message = this.bannerMessages[currentQuestion.id]?.wrong || "That is a wrong answer, please try again"; // Update the banner text const bannerText = banner.querySelector('strong'); if (bannerText) { bannerText.textContent = message; } banner.style.display = 'block'; console.log('Wrong answer banner displayed'); // Auto-hide after 3 seconds setTimeout(() => { this.hideWrongAnswerBanner(); }, 3000); } else { console.error('Wrong answer banner element not found!'); } } hideWrongAnswerBanner() { const banner = document.getElementById('wrong-answer-banner'); if (banner) { banner.style.display = 'none'; } } addEmailValidation(input, fieldGroup) { // Create error message element const errorElement = document.createElement('div'); errorElement.className = 'email-error text-danger small mt-1'; errorElement.style.display = 'none'; errorElement.textContent = 'Please enter a valid email address in the format name@company.com'; // Add error element after the input fieldGroup.appendChild(errorElement); // Email validation function const validateEmail = (email) => { const emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/; return emailRegex.test(email); }; // Add event listeners input.addEventListener('blur', () => { const email = input.value.trim(); if (email && !validateEmail(email)) { errorElement.style.display = 'block'; input.classList.add('is-invalid'); } else { errorElement.style.display = 'none'; input.classList.remove('is-invalid'); } }); input.addEventListener('input', () => { const email = input.value.trim(); if (email && !validateEmail(email)) { errorElement.style.display = 'block'; input.classList.add('is-invalid'); } else { errorElement.style.display = 'none'; input.classList.remove('is-invalid'); } }); } addPhoneFormatting(input) { // Set placeholder to show the expected format input.placeholder = '(XXX) XXX-XXXX'; // Add input event listener for formatting input.addEventListener('input', (e) => { let value = e.target.value.replace(/\D/g, ''); // Remove all non-digits // Limit to 10 digits if (value.length > 10) { value = value.substring(0, 10); } // Format the phone number let formattedValue = ''; if (value.length > 0) { if (value.length <= 3) { formattedValue = `(${value}`; } else if (value.length <= 6) { formattedValue = `(${value.substring(0, 3)}) ${value.substring(3)}`; } else { formattedValue = `(${value.substring(0, 3)}) ${value.substring(3, 6)}-${value.substring(6)}`; } } e.target.value = formattedValue; }); // Add keydown event listener to prevent non-numeric input input.addEventListener('keydown', (e) => { // Allow: backspace, delete, tab, escape, enter, home, end, left, right, up, down if ([8, 9, 27, 13, 46, 35, 36, 37, 38, 39, 40].indexOf(e.keyCode) !== -1 || // Allow: Ctrl+A, Ctrl+C, Ctrl+V, Ctrl+X (e.keyCode === 65 && e.ctrlKey === true) || (e.keyCode === 67 && e.ctrlKey === true) || (e.keyCode === 86 && e.ctrlKey === true) || (e.keyCode === 88 && e.ctrlKey === true)) { return; } // Ensure that it is a number and stop the keypress if ((e.shiftKey || (e.keyCode < 48 || e.keyCode > 57)) && (e.keyCode < 96 || e.keyCode > 105)) { e.preventDefault(); } }); // Add paste event listener to handle pasted content input.addEventListener('paste', (e) => { e.preventDefault(); const pastedData = e.clipboardData.getData('text'); const numbersOnly = pastedData.replace(/\D/g, ''); if (numbersOnly.length <= 10) { input.value = numbersOnly; input.dispatchEvent(new Event('input')); } }); } checkQuestion2Completion() { // Check if all options for question 2 are selected const question2Inputs = document.querySelectorAll('input[name="question-2"]'); const checkedInputs = document.querySelectorAll('input[name="question-2"]:checked'); console.log(`Question 2: ${checkedInputs.length} of ${question2Inputs.length} options selected`); if (checkedInputs.length === question2Inputs.length) { // All options selected - show success popup this.currentQuestionAnsweredCorrectly = true; if (!this.correctAnswerTriggered) { this.correctAnswerTriggered = true; this.hideWrongAnswerBanner(); this.showSuccessBanner(); this.playFireworks(); } // Don't update navigation buttons - let popup handle progression } else { // Not all options selected - hide success popup but don't show error this.currentQuestionAnsweredCorrectly = false; this.hideSuccessBanner(); this.hideWrongAnswerBanner(); // Don't show error message for question 2 this.updateNavigationButtons(); } } checkQuestion3Completion() { // Check if all options for question 3 are selected const question3Inputs = document.querySelectorAll('input[name="question-3"]'); const checkedInputs = document.querySelectorAll('input[name="question-3"]:checked'); console.log(`Question 3: ${checkedInputs.length} of ${question3Inputs.length} options selected`); if (checkedInputs.length === question3Inputs.length) { // All options selected - show success popup this.currentQuestionAnsweredCorrectly = true; if (!this.correctAnswerTriggered) { this.correctAnswerTriggered = true; this.hideWrongAnswerBanner(); this.showSuccessBanner(); this.playFireworks(); } // Don't update navigation buttons - let popup handle progression } else { // Not all options selected - hide success popup but don't show error this.currentQuestionAnsweredCorrectly = false; this.hideSuccessBanner(); this.hideWrongAnswerBanner(); // Don't show error message for question 3 this.updateNavigationButtons(); } } checkQuestion4Completion() { // Check if all options for question 4 are selected const question4Inputs = document.querySelectorAll('input[name="question-4"]'); const checkedInputs = document.querySelectorAll('input[name="question-4"]:checked'); console.log(`Question 4: ${checkedInputs.length} of ${question4Inputs.length} options selected`); if (checkedInputs.length === question4Inputs.length) { // All options selected - show success popup this.currentQuestionAnsweredCorrectly = true; if (!this.correctAnswerTriggered) { this.correctAnswerTriggered = true; this.hideWrongAnswerBanner(); this.showSuccessBanner(); this.playFireworks(); } // Don't update navigation buttons - let popup handle progression } else { // Not all options selected - hide success popup but don't show error this.currentQuestionAnsweredCorrectly = false; this.hideSuccessBanner(); this.hideWrongAnswerBanner(); // Don't show error message for question 4 this.updateNavigationButtons(); } } playFireworks() { console.log('Playing confetti celebration...'); // Use confetti library for celebration if (typeof confetti !== 'undefined') { try { // Multiple confetti bursts for better effect const duration = 3000; const animationEnd = Date.now() + duration; const defaults = { startVelocity: 30, spread: 360, ticks: 60, zIndex: 1000 }; function randomInRange(min, max) { return Math.random() * (max - min) + min; } const interval = setInterval(function() { const timeLeft = animationEnd - Date.now(); if (timeLeft <= 0) { return clearInterval(interval); } const particleCount = 50 * (timeLeft / duration); // Launch confetti from different positions confetti({ ...defaults, particleCount, origin: { x: randomInRange(0.1, 0.3), y: Math.random() - 0.2 } }); confetti({ ...defaults, particleCount, origin: { x: randomInRange(0.7, 0.9), y: Math.random() - 0.2 } }); }, 250); console.log('Confetti celebration started'); } catch (error) { console.error('Error with confetti:', error); this.showCelebrationFallback(); } } else { console.log('Confetti library not available, using fallback'); this.showCelebrationFallback(); } } showCelebrationFallback() { console.log('Showing celebration fallback...'); // Create a simple celebration overlay const celebration = document.createElement('div'); celebration.id = 'celebration-fallback'; celebration.style.position = 'fixed'; celebration.style.top = '0'; celebration.style.left = '0'; celebration.style.width = '100%'; celebration.style.height = '100%'; celebration.style.background = 'linear-gradient(45deg, #ff6b6b, #4ecdc4, #45b7d1, #96ceb4, #feca57)'; celebration.style.display = 'flex'; celebration.style.alignItems = 'center'; celebration.style.justifyContent = 'center'; celebration.style.zIndex = '9999'; celebration.style.fontSize = '3rem'; celebration.style.fontWeight = 'bold'; celebration.style.color = 'white'; celebration.style.textAlign = 'center'; celebration.style.animation = 'pulse 0.5s ease-in-out infinite alternate'; celebration.innerHTML = '🎉
CORRECT!
🎉'; document.body.appendChild(celebration); // Remove after 3 seconds setTimeout(() => { if (document.body.contains(celebration)) { document.body.removeChild(celebration); } }, 3000); } } // Global functions for button clicks let quizApp; function startQuiz() { // Hide intro step document.getElementById('step-intro').style.display = 'none'; document.getElementById('step-intro').classList.remove('active'); // Show quiz steps document.getElementById('quiz-steps').style.display = 'block'; // Scroll to top of the page window.scrollTo({ top: 0, behavior: 'smooth' }); // Initialize quiz app quizApp = new QuizApp(); } function nextQuestion() { if (quizApp) { quizApp.nextQuestion(); } } function previousQuestion() { if (quizApp) { quizApp.previousQuestion(); } } function restartQuiz() { if (quizApp) { quizApp.restartQuiz(); } } function proceedToNextQuestion() { if (quizApp) { // Hide the success popup quizApp.hideSuccessBanner(); // Proceed to next question quizApp.nextQuestion(); } } // Initialize when page loads document.addEventListener('DOMContentLoaded', function() { // Add smooth scrolling document.querySelectorAll('a[href^="#"]').forEach(anchor => { anchor.addEventListener('click', function (e) { e.preventDefault(); document.querySelector(this.getAttribute('href')).scrollIntoView({ behavior: 'smooth' }); }); }); // Add form validation styles const style = document.createElement('style'); style.textContent = ` .validation-message { margin-top: 1rem; animation: slideDown 0.3s ease; } @keyframes slideDown { from { opacity: 0; transform: translateY(-10px); } to { opacity: 1; transform: translateY(0); } } .option-label:focus-within { outline: 2px solid var(--primary-color); outline-offset: 2px; } `; document.head.appendChild(style); // Test function for debugging window.testFireworks = function() { console.log('Testing fireworks and banner...'); if (quizApp) { quizApp.showSuccessBanner(); quizApp.playFireworks(); } else { console.log('Quiz app not initialized yet'); } }; });