Implementation steps of js object-oriented encapsulation cascading drop-down menu list

Implementation steps of js object-oriented encapsulation cascading drop-down menu list

The cascading drop-down menu developed in this example is a DOM element created based on existing JSON data. After clicking the text box, a first-level menu is displayed. If a menu contains submenus, there will be an arrow to the right of the menu indicating this. After clicking the menu, the next level menu will be displayed, and so on. When there is no submenu under the menu, it will be displayed in the text box after selecting the menu.

The effect of the cascading menu after opening is as shown in the figure:

Using the plug-in packaged in the example, you only need an input element to automatically generate a cascading drop-down menu through the plug-in. The HTML code is as follows:

 <div style="margin-top:100px;text-align:center;">
  <input type="text" id="input">
 </div>

Next, let's see how to implement the specific encapsulated js code.

1. Declare the constructor of the cascading menu

The constructor needs to pass in two parameters: a text box element and menu associated data.

 //elem is a text box, data is menu-related data function CascadeMenu(elem,data){

 }

2. Create cascading menu related elements in the constructor and put them on the page. The specific code is as follows:

function CascadeMenu(elem,data){
  //Get the text box this.eInput = elem;
  //Set the text box to read-only this.eInput.setAttribute('readonly',true);
  //Set the text box prompt this.eInput.placeholder = 'Please select';
  //Get the parent element of the text box var eInputParent = this.eInput.parentNode;
  //Create a cascading menu container this.eCascade = document.createElement('div');
  this.eCascade.className = 'cascade_container';
  //Create a menu drop-down list container this.eCascadeInto = document.createElement('div');
  this.eCascadeInto.className = 'cascade_into';
  //The drop-down list container is hidden by default this.eCascadeInto.style.display = 'none';
  //Put each element into the page this.eCascade.appendChild(this.eInput);
  this.eCascade.appendChild(this.eCascadeInto);
  eInputParent.appendChild(this.eCascade);
  //Get menu data this.aData = data;
  //Record the selected menu data this.aSelected = [];
  //Menu open state, default is false, means hidden this.bShow = false;
 }

3. Bind click events to text boxes to generate cascading drop-down menus

Now that you have placed all the required elements on the page, you can show and hide the cascading menu elements by clicking the text box;
When displaying a cascading menu element, the cascading drop-down menu should be generated by data.
Because each click needs to be generated, you can add a method to the constructor's prototype. As shown below:

function CascadeMenu(elem,data){
  /*…*/

  this.eInput.addEventListener('click',()=>{
   //Judge the menu opening status if(this.bShow){ 
    //If it is open, hide the menu this.eCascadeInto.style.display = 'none';
    //Modify the menu opening status this.bShow = false;
   }else{
    //Display cascade menu elements this.eCascadeInto.style.display = 'none';
    //Save the selected menu data this.aSelected = this.eInput.value.split('>');
    //Generate cascading menu this.generateMenu();
   }
  });
 }
 //Generate cascading menu based on dataCascadeMenu.prototype.generateMenu = function(){
  //When calling the instance object in fnCreatHTML, you need to declare a variable pointing to this
  var _self = this;
  //Because we are not sure how many groups of submenus there are, we need to declare a function to call recursively //data: incoming data, step: current level function fnCreatHTML(data,step){
   //Used to store submenu data var aChildArr = null;
   //Generate menu DOM string var sHTML = '<ul>';
   //Loop data for(let i=0;i<data.length;i++){
    //Judge if there is a submenu and add the child class to display the arrow on the right side of the menu if (data[i].child) { 
     //Judge whether it is the current selection. If so, add cur class and store submenu data if(data[i].name==this.aSelected[step]){
      aChildArr = data[i].child;
      sHTML += '<li class="child cur" data-po="'+step+'">';
     }else{
      sHTML += '<li class="child" data-po="'+step+'">';
     }
    }else{ 
     //If there is no submenu, add it directly to the menu list sHTML += data[i].name == this.aSelected[step]?
                  '<li class="cur" data-po="'+step+'">':
                  '<li data-po="'+step+'">';
    }
    //Add menu name sHTML += data[i].name;
    //End the current menu sHTML += '</li>';
   }
   sHTML += '</ul>';
   //If multiple menus are selected, recursively call the function to generate submenus if(this.aSelected.length>step+1){
    sHTML += fnCreateHTML(aChildArr,step+1);
   }
   return sHTML;
  }
  this.eCascadeInto.innerHTML = fnCreatHTML(this.aData,0);
 }

4. Bind events on the menu to select the menu

There are two types of cascading menus: one with a sub-menu that is displayed when clicked;
One type has no sub-menus. When clicked, the menu is directly selected and the selected menu is displayed in the text box by level. The code looks like this:

function CascadeMenu(elem,data){
  /*…*/

  //Use event delegation to select the menu this.eCascadeInto.addEventListener('click',(event)=>{
   //Get the menu var eTarget = event.target;
   //Get the selected level var po = +eTarget.dataset.po;
   //Delete the data after the current selection level this.aSelected.splice(po+1,this.aSelected.length-(po+1));
   //Modify the current selected data this.aSelected[po] = eTarget.innerHTML;
   //Judge whether there is a submenu if(eTarget.className.indexOf('child')==-1){ //If there is no submenu, select directly this.eInput.value = this.aSelected.join('>');
    this.eCascadeInto.style.display = 'none';
    this.bShow = false;
   }else{ //If there is a submenu, display the next level. //Regenerate the DOM element and add an empty string to the array to display the next level. this.aSelected.push('')
    //Regenerate the cascading menu this.generateMenu();
   }  
  });
 }

5. Hide the menu when clicking on a blank area of ​​the page

Now you can only show and hide the menu by clicking on the text box. Generally speaking, any open pop-up window is expected to be closed outside the pop-up window. This requires modifying the click event function on the text box: when opening the menu, bind the click event on the document element to close the menu; when hiding the menu, cancel the click event bound to the document. As shown below:

function CascadeMenu(elem,data){
  /*…*/

  this.eInput.addEventListener('click',()=>{
   //Judge the menu opening status if(this.bShow){ 
    //If it is open, hide the menu this.eCascadeInto.style.display = 'none';
    //Modify the menu opening status this.bShow = false;
    //Cancel the event on document document.onclick = null;
   }else{
    //Display cascade menu elements this.eCascadeInto.style.display = 'none';
    //Save the selected menu data this.aSelected = this.eInput.value.split('>');
    //Generate cascading menu this.generateMenu();
    document.onclick = () => {
     //Hide the menu this.eCascadeInto.style.display = 'none';
     //Modify the menu opening status this.bShow = false;
     //Cancel the event on document document.onclick = null;
    }
   }
  });
  //Prevent bubbling this.eCascade.addEventListener('click',(event)=>{
   event.stopPropagation();
  });

  /*…*/
 }

6. Finally, prepare the data, call the constructor, and generate a cascading drop-down menu as shown below:

var json = [
  {
   "name":"北京","id":"110000","child":[
    {"name":"city district","id":"110100","child":[
     : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : :
    },
    {"name":"北京","id":"110000","child":null}
   ]
  },
  {
   "name":"Hebei Province","id":"130000","child":[
    {"name":"Shijiazhuang City","id":"130100","child":[
     : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : :
    },
    {"name":"Tangshan City","id":"130200","child":[
     : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : :
    },
    {"name":"Qinhuangdao City","id":"130300","child":[
     {"name":"Municipal District","id":"130301","child":null},{"name":"Haigang District","id":"130302","child":null},{"name":"Shanhaiguan District","id":"130303","child":null},{"name":"Beidaihe District","id":"130304","child":null},{"name":"Funing District","id":"130306","child":null},{"name":"Qinglong Manchu Autonomous County","id":"130321","child":null},{"name":"Changli County","id":"130322","child":null},{"name":"Lulong County","id":"130324","child":null}]
    },
    {"name":"Handan City","id":"130400","child":[
     : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : :
    }
   ]
  },
  {
   "name":"Hunan Province","id":"430000","child":[
    {"name":"Changsha City","id":"430100","child":[
     : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : :
    },
    {"name":"Zhuzhou City","id":"430200","child":[
     : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : :
    },
    {"name":"Xiangtan City","id":"430300","child":[
     {"name":"District","id":"430301","child":null},{"name":"Yuhu District","id":"430302","child":null},{"name":"Yuetang District","id":"430304","child":null},{"name":"Xiangtan County","id":"430321","child":null},{"name":"Xiangxiang City","id":"430381","child":null},{"name":"Shaoshan City","id":"430382","child":null}]
    },
    {"name":"Hengyang City","id":"430400","child":[
     {"name":"Districts under the jurisdiction of the city","id":"430401","child":null},{"name":"Zhuhui District","id":"430405","child":null},{"name":"Yanfeng District","id":"430406","child":null},{"name":"Shigu District","id":"430407","child":null},{"name":"Zhengxiang District","id":"430408","child":null},{"name":"Nanyue District","id":"430412","child":null},{"name":"Hengyang County","id":"430421","child":null},{"name":"Hengnan County","id":"430422","child":[
      {"name":"Santang Town",id:"430422",child:null},{"name":"Chejiang Town",id:"430422",child:null}
     ]},{"name":"Hengshan County","id":"430423","child":null},{"name":"Hengdong County","id":"430424","child":null},{"name":"Qidong County","id":"430426","child":null},{"name":"Leiyang City","id":"430481","child":null},{"name":"Changning City","id":"430482","child":null}]
    }
   ]
  },
  {
   "name":"Guangdong Province","id":"440000","child":[
    {"name":"Guangzhou","id":"440100","child":[
     : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : :
    },
    {"name":"Shaoguan City","id":"440200","child":[
     : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : :
    },
    {"name":"深圳","id":"440300","child":[
     {"name":"District","id":"440301","child":null},{"name":"Luohu District","id":"440303","child":null},{"name":"Futian District","id":"440304","child":null},{"name":"Nanshan District","id":"440305","child":null},{"name":"Baoan District","id":"440306","child":null},{"name":"Longgang District","id":"440307","child":null},{"name":"Yantian District","id":"440308","child":null}]
    },
    {"name":"Zhuhai City","id":"440400","child":[
     {"name":"District","id":"440401","child":null},{"name":"Xiangzhou District","id":"440402","child":null},{"name":"Doumen District","id":"440403","child":null},{"name":"Jinwan District","id":"440404","child":null}]
    }
   ]
  },
  {
   "name":"Nansha Islands","id":"900001","child":null
  }
 ];

 var eText = document.getElementById('input');
 new CascadeMenu(eText,json);

A packaged js cascade drop-down function is completed, and you can write your own CSS style according to the picture to achieve the desired effect.

The above is the detailed content of the implementation steps of js object-oriented encapsulation cascading drop-down menu list. For more information about js encapsulation drop-down menu, please pay attention to other related articles on 123WORDPRESS.COM!

You may also be interested in:
  • Implementing HTML navigation bar drop-down menu with JavaScript
  • JavaScript to achieve the effect of web page drop-down menu
  • Detailed explanation of how to use the Vue.js drop-down menu component
  • js drop-down menu clicks next to collapse implementation (pitfall record)
  • A brief discussion on how to implement custom drop-down menu instructions in Vue.js
  • js realizes the effect of button switch stand-alone drop-down menu
  • js dynamically sets the default selected item in the select drop-down menu
  • Pure JS to achieve the birth date [year, month, day] drop-down menu effect
  • JS implements an example of clicking the drop-down menu to synchronize the selected content to the input box
  • js prevents the default right-click drop-down menu method

<<:  MySQL-group-replication configuration steps (recommended)

>>:  Detailed description of nginx from compilation and installation to configuration file description in Chinese

Recommend

Mysql database recovery actual record by time point

Introduction: MySQL database recovery by time poi...

In-depth analysis of MySQL query interception

Table of contents 1. Query Optimization 1. MySQL ...

How to implement logic reuse with Vue3 composition API

Composition API implements logic reuse steps: Ext...

What codes should I master when learning web page design?

This article introduces in detail some of the tech...

12 Javascript table controls (DataGrid) are sorted out

When the DataSource property of a DataGrid control...

React internationalization react-intl usage

How to achieve internationalization in React? The...

Three ways to copy MySQL tables (summary)

Copy table structure and its data The following s...

Introduction to MySQL Connection Control Plugin

Table of contents 1. Introduction to the connecti...

MySql Sql optimization tips sharing

One day I found that the execution speed of a SQL...

HTML simple shopping quantity applet

This article shares a simple HTML shopping quanti...

Solution to JS out-of-precision number problem

The most understandable explanation of the accura...

Nginx cache configuration example

When developing and debugging a web application, ...