javascriptreusability

How to use same JavaScript program multiple times on same website


I am working on my Portfolio project and for that I have made a International country code selector program for my phone number field. but the problem I'm facing right now is that I have two forms in my homepage one is Consultation Form and another one is Contact Form, and I want to use the same JS program for both Forms.

I don't want to rewrite the same type of program or functions again and again, because that negatively effects the performance of my website. but in the other hand I don't know how can I reuse the same code for two forms. It conflicts when I try to reuse the function.

I have a working dropdown menu for Contact Form, also I want to implement the same logic to Consultation Form by using the same program.

Please help me to figure out this problem.

// Cache the elements
const ccDiv = document.querySelector(".contact-frm-cc");
const ccButton = document.querySelector(".cc-telcode");
const ccContainer = document.querySelector(".cc-container");
const ccSearchInput = document.querySelector(".cc-search-box");
const ccList = document.querySelector(".cc-data-list");
var selectedCountry = ""; // saved by "code"

// Add event listeners to the button, input, and list
// We use a process called "event delegation" on the list
// to catch events from its children as they "bubble up" the DOM
// https://dmitripavlutin.com/javascript-event-delegation/
ccButton.addEventListener("click", handleButton);
ccSearchInput.addEventListener("input", handleInput);
ccList.addEventListener("click", handleListClick);
document.addEventListener("click", handleDocumentClick);

// All of the data held as objects within an array
const data = [
   { name: "Afganistan", code: "93", flag: "afg" },
   { name: "Albania", code: "355", flag: "alb" },
   { name: "Algeria", code: "213", flag: "dza" },
   { name: "American Samoa", code: "1-684", flag: "asm" },
   { name: "Andorra", code: "376", flag: "and" },
   { name: "Angola", code: "244", flag: "ago" },
   { name: "Anguilla", code: "1-264", flag: "aia" },
   { name: "Antarctica", code: "672", flag: "ata" },
   { name: "Antigua and Barbuda", code: "1-268", flag: "atg" },
   { name: "Argentina", code: "54", flag: "arg" },
   { name: "Armenia", code: "374", flag: "arm" },
   { name: "Aruba", code: "297", flag: "abw" },
   { name: "Australia", code: "61", flag: "aus" },
   { name: "Austria", code: "43", flag: "aut" },
   { name: "Azerbaijan", code: "994", flag: "aze" },
   { name: "Bahamas", code: "1-242", flag: "bhs" },
   { name: "Bahrain", code: "973", flag: "bhr" },
   { name: "Bangladesh", code: "880", flag: "bgd" },
   { name: "Barbados", code: "1-246", flag: "brb" },
   { name: "Belarus", code: "375", flag: "blr" },
   { name: "Belgium", code: "32", flag: "bel" },
   { name: "Belize", code: "501", flag: "blz" },
   { name: "Benin", code: "229", flag: "ben" },
   { name: "Bermuda", code: "1-441", flag: "bmu" },
   { name: "Bhutan", code: "975", flag: "btn" },
   { name: "Bolivia", code: "591", flag: "bol" },
   { name: "Bosnia and Herzegovina", code: "387", flag: "bih" },
   { name: "Botswana", code: "267", flag: "bwa" },
   { name: "Brazil", code: "55", flag: "bra" },
   { name: "British Indian Ocean Territory", code: "246", flag: "iot" },
   { name: "British Virgin Islands", code: "1-284", flag: "vgb" },
   { name: "Brunei", code: "673", flag: "brn" },
   { name: "Bulgaria", code: "359", flag: "bgr" },
   { name: "Burkina Faso", code: "226", flag: "bfa" },
   { name: "Burundi", code: "257", flag: "bdi" },
   { name: "Cambodia", code: "855", flag: "khm" },
   { name: "Cameroon", code: "237", flag: "cmr" },
   { name: "Canada", code: "1", flag: "can" },
   { name: "Cape Verde", code: "238", flag: "cpv" },
   { name: "Cayman Islands", code: "1-345", flag: "cym" },
   { name: "Central African Republic", code: "236", flag: "caf" },
   { name: "Chad", code: "235", flag: "tcd" },
   { name: "Chile", code: "56", flag: "chl" },
   { name: "China", code: "86", flag: "chn" },
   { name: "Christmas Island", code: "61", flag: "cxr" },
   { name: "Cocos Islands", code: "61", flag: "cck" },
   { name: "Colombia", code: "57", flag: "col" },
   { name: "Comoros", code: "269", flag: "com" },
   { name: "Cook Islands", code: "682", flag: "cok" },
   { name: "Costa Rica", code: "506", flag: "cri" },
   { name: "Croatia", code: "385", flag: "hrv" },
   //------- MORE COUNTRIES TO ADD LATER
];


// Handles the document click - it checks to see if the clicked
// part of the document has a parent element which is either
// `null` or is the HTML element, and then closes the container
// if it's open

function handleDocumentClick(e) {
  const { parentElement } = e.target;
document.addEventListener("click", (event) => {
  if (!ccDiv.contains(event.target)) {
   ccContainer.classList.remove("show-cc-list");
  }
});
}


// Filters the data based on the characters
// at the start of the provided name
function filterData(data, value) {
  return data.filter((obj) => {
    return (
      obj.name.toLowerCase().startsWith(value.toLowerCase()) ||
      obj.code.toLowerCase().startsWith(value.toLowerCase())
    );
  });
}

// Create a series of list items based on the
// data passed to it
function createListHtml(data) {
  return data.map((obj) => {
      const { name, code, flag } = obj;
      let isSelected = "";
      if (obj.code == selectedCountry) isSelected = "selected-country";
      return `
         <li class="cc-list-items ${isSelected}" data-name="${name}" data-code="${code}" data-flag="${flag}">
            <div class="flag-icon flag-icon-${flag}"></div>
            <div class="name">${name} (+${code})</div>
         </li>
      `;
   }).join("");
}

// Toggle the container on/off
function handleButton() {
  ccContainer.classList.toggle("show-cc-list");
  ccList.innerHTML = createListHtml(data);
}

// No data available list item
function createNoDataHtml() {
  return '<li class="nodata">No data available</li>';
}

// When the input is changed filter the data
// according to the current value, and then
// create some list items using that filtered data
function handleInput(e) {
  const { value } = e.target;
  if (value) {
    const filtered = filterData(data, value);
    if (filtered.length) {
        ccList.innerHTML = createListHtml(filtered);
    } else {
        ccList.innerHTML = createNoDataHtml();
    }
  } else {
    ccList.innerHTML = createListHtml(data);
  }
}

// Create some button HTML
function createButtonHtml(code, flag) {
  return `
    <div class="flag-icon flag-icon-${flag}"></div>
    <option class="cc-code" value="+${code}">+${code}</option>
  `;
}

// When an item is clicked, grab the relevant data
// attributes, create the new button HTML, and then
// close the container
function handleListClick(e) {
  const item = e.target.closest("li") || e.target;
  if (item.classList.contains("cc-list-items")) {
    const { code, flag } = item.dataset;
    selectedCountry = item.dataset.code;
    ccButton.innerHTML = createButtonHtml(code, flag);
    ccContainer.classList.remove("show-cc-list");
  }
}
.cc-telcode {
     margin-bottom: 1em;
     display: flex;
     justify-content: center;
     width: 100%;
}

 .cc-telcode div.cc-code, 
 .cc-list-items div.name {
     margin-left: 0.25em;
}
 .cc-container {
     display: none;
     width: 300px;
     position: absolute;
}
 .show-cc-list {
     display: block;
     z-index: +999;
}
 .cc-data-list {
     max-height: 100px;
     list-style: none;
     margin: 1em 0 0 0;
     padding: 0;
     overflow-y: scroll;
     border: 1px soldi darkgray;
}
 .cc-list-items {
     display: flex;
     padding: 0.25em;
     border: 1px solid lightgray;
}
 .cc-list-items:hover {
     cursor: pointer;
     background-color: lightyellow;
}

 .selected-country {
     cursor: pointer;
     background-color: rgb(73, 118, 241);
}

.contact-frm-cc {
   width:100px;
}
<link rel="stylesheet" href="https://amitdutta.co.in/flag/css/flag-icon.css">

<!------------- Working Dropdown Menu ------------>     
     <div class="contact-frm-cc">
         <button class="cc-telcode">Tel code</button>
         <section class="cc-container">
            <input type="text" class="cc-search-box" placeholder="Search for country" />
            <ul class="cc-data-list">
            </ul>
         </section>
      </div>
      
<!------------- Not-Working Dropdown Menu ------------>      
<!--
<div class="consult-frm-cc">
         <button class="cc-telcode">Tel code</button>
         <section class="cc-container">
            <input type="text" class="cc-search-box" placeholder="Search for country" />
            <ul class="cc-data-list">
            </ul>
         </section>
      </div>
-->


Solution

  • You can create a function to register your form logic, and just pass your root form element.

    here is a simple modification based on your code

    <!-- https://codepen.io/DlmaK/pen/dyjXYrm -->