Home > database >  How to set attributes to the other items in array besides the selected element (this)?
How to set attributes to the other items in array besides the selected element (this)?

Time:02-20

I would like to make buttons in my HTML while one of my JS classes is running and receives a response from the backend. I'm using jQuery and vanilla JS and created an example below. In this example, I'd like to dynamically disable the button that was not clicked to show the user that something is happening and that they should not click elsewhere until a response is returned.

Array.from(document.getElementsByClassName("upload-button")).forEach(button => {
    button.addEventListener("click",
        function(){
            let buttonSpinner = this.getElementsByTagName("span")[0];
            buttonSpinner.classList.remove("d-none");
            // here I would like to disable the button that wasn't selected
            let destination = this.value;
            uploadData(destination, buttonSpinner);
        }
    )
})

function uploadData(destination, buttonSpinner){
    let link = "https://www.google.com/";
    let description = "Stack Overflow";
    new Upload(link, description, destination, buttonSpinner)
}

class Upload {
  constructor(link=null, description=null, destination="submit", buttonSpinner=null){
    this.link = link;
    this.description = description;
    this.destination = destination;
    this.buttonSpinner = buttonSpinner;
    this.log();
    this.disableButtonSpinner();
  }

  log(){
    console.log(this.link)
   }
  
  wait(){
    return new Promise(resolve => setTimeout(resolve, 3000)); // wait for data to return from backend
  }
  
   async disableButtonSpinner(){
    await this.wait() // simulate backend returning data
    this.buttonSpinner.classList.add("d-none");
   }
}
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">

<div>
    <button  id="upload-user-data-button" value="data">
        Upload & View My Data
        <span  role="status" aria-hidden="true"></span>
        <span >Loading...</span>
    </button>
    <button  id="upload-submit-button" value="submit">
        Upload & Submit
        <span  role="status" aria-hidden="true"></span>
        <span >Loading...</span>
    </button>
</div>

CodePudding user response:

You can add a parameter in the function to access the click event I used e. Then You can loop through your buttons and disable other than events target. This is achieved by Array.from(document.getElementsByClassName("upload-button")).forEach(insideButton => { if(e.target !== insideButton) insideButton.disabled = true});

  Array.from(document.getElementsByClassName("upload-button")).forEach(button => {
        button.addEventListener("click",
            function(e){
                let buttonSpinner = this.getElementsByTagName("span")[0];
                buttonSpinner.classList.remove("d-none");
                // here I would like to disable the button that wasn't selected        
                 Array.from(document.getElementsByClassName("upload-button")).forEach(insideButton => {
                 if(e.target !== insideButton) 
                 insideButton.disabled = true});
                let destination = this.value;
                uploadData(destination, buttonSpinner);
            }
        )
    })

    function uploadData(destination, buttonSpinner){
        let link = "https://www.google.com/";
        let description = "Stack Overflow";
        new Upload(link, description, destination, buttonSpinner)
    }

    class Upload {
      constructor(link=null, description=null, destination="submit", buttonSpinner=null){
        this.link = link;
        this.description = description;
        this.destination = destination;
        this.buttonSpinner = buttonSpinner;
        this.log();
        this.disableButtonSpinner();
      }

      log(){
        console.log(this.link)
       }
      
      wait(){
        return new Promise(resolve => setTimeout(resolve, 3000)); // wait for data to return from backend
      }
      
       async disableButtonSpinner(){
        await this.wait() // simulate backend returning data
        this.buttonSpinner.classList.add("d-none");
       }
    }
    <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">

    <div>
        <button  id="upload-user-data-button" value="data">
            Upload & View My Data
            <span  role="status" aria-hidden="true"></span>
            <span >Loading...</span>
        </button>
        <button  id="upload-submit-button" value="submit">
            Upload & Submit
            <span  role="status" aria-hidden="true"></span>
            <span >Loading...</span>
        </button>
    </div>

CodePudding user response:

As a quick hack you could do something like that:

Array.from(document.getElementsByClassName("upload-button")).forEach((button, i) => {
    button.addEventListener("click",
        function(){
            let buttonSpinner = this.getElementsByTagName("span")[0];
            buttonSpinner.classList.remove("d-none");
            // here I would like to disable the button that wasn't selected
            let buttons = Array.from(document.getElementsByClassName("upload-button"))
            if(i==0) buttons[1].disabled=true;
            if(i==1) buttons[0].disabled=true;
            let destination = this.value;
            uploadData(destination, buttonSpinner);
        }
    )
})

function uploadData(destination, buttonSpinner){
    let link = "https://www.google.com/";
    let description = "Stack Overflow";
    new Upload(link, description, destination, buttonSpinner)
}

class Upload {
  constructor(link=null, description=null, destination="submit", buttonSpinner=null){
    this.link = link;
    this.description = description;
    this.destination = destination;
    this.buttonSpinner = buttonSpinner;
    this.log();
    this.disableButtonSpinner();
  }

  log(){
    console.log(this.link)
   }
  
  wait(){
    return new Promise(resolve => setTimeout(resolve, 3000)); // wait for data to return from backend
  }
  
   async disableButtonSpinner(){
    await this.wait() // simulate backend returning data
    this.buttonSpinner.classList.add("d-none");
    let buttons = Array.from(document.getElementsByClassName("upload-button"))
    buttons[0].disabled=false;
    buttons[1].disabled=false;
   }
}
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">

<div>
    <button  id="upload-user-data-button" value="data">
        Upload & View My Data
        <span  role="status" aria-hidden="true"></span>
        <span >Loading...</span>
    </button>
    <button  id="upload-submit-button" value="submit">
        Upload & Submit
        <span  role="status" aria-hidden="true"></span>
        <span >Loading...</span>
    </button>
</div>

CodePudding user response:

adding this solution to fix the issue with @Raven solution where the buttons remain disables even after the operation is done.

Array.from(document.getElementsByClassName("upload-button")).forEach(button => {
        button.addEventListener("click",
            async function(e){
                let buttonSpinner = this.getElementsByTagName("span")[0];
                buttonSpinner.classList.remove("d-none");
                // here I would like to disable the button that wasn't selected        
                 Array.from(document.getElementsByClassName("upload-button")).forEach(insideButton => {
                    if(e.target !== insideButton) 
                    insideButton.disabled = true}
                 );
                let destination = this.value;
                await uploadData(destination, buttonSpinner);
            }
        )
    })

    async function uploadData(destination, buttonSpinner){
        let link = "https://www.google.com/";
        let description = "Stack Overflow";
        await new Upload(link, description, destination, buttonSpinner)
    }

    class Upload {
      constructor(link=null, description=null, destination="submit", buttonSpinner=null){
        this.link = link;
        this.description = description;
        this.destination = destination;
        this.buttonSpinner = buttonSpinner;
        this.log();
        this.disableButtonSpinner();
      }

      log(){
        console.log(this.link)
       }
      
      wait(){
        return new Promise(resolve => setTimeout(resolve, 3000)); // wait for data to return from backend
      }
      
       async disableButtonSpinner(){
        await this.wait().then(()=>{
            Array.from(document.getElementsByClassName("upload-button")).forEach(insideButton => {    
                insideButton.disabled = false;
            }
             );
        }) // simulate backend returning data
        this.buttonSpinner.classList.add("d-none");
       }
    }
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">

    <div>
        <button  id="upload-user-data-button" value="data">
            Upload & View My Data
            <span  role="status" aria-hidden="true"></span>
            <span >Loading...</span>
        </button>
        <button  id="upload-submit-button" value="submit">
            Upload & Submit
            <span  role="status" aria-hidden="true"></span>
            <span >Loading...</span>
        </button>
    </div>

  • Related