问:
How to fix: "Uncaught ReferenceError: loadRecords is not defined" with Google App Script
I have followed a tutorial "Create HTML Form that Moves through RecordSet on Google Sheets" done by  Code With Curt.
https://www.youtube.com/watch?v=V9ptq7tZV50&t=152s

The project doesn't look that complicated. It is a simple CRUD app that I want to run in a modal dialog in google sheets, I am a newbie, I really tried to understand the code that I was copying from the video and not make any typos. The form shows up OK from the custom menu but it is not populating with the data from the sheet. The only error I can see is in the console which says "Uncaught ReferenceError: loadRecords is not defined" I have double checked the variable and function names but just can't see the error.

Any help would be appreciated.

Code.gs

function getList()
{
  var url = 'https://docs.google.com/spreadsheets/d/1QkSdtybPHA9IrWH2VPw44WtQ9dN_-9KjRVNOuCylMCk/edit#gid=0';
  var ss= SpreadsheetApp.openByUrl(url);
  //var ss = SpreadsheetApp.getActiveSpreadsheet();
  var recordSheet = ss.getSheetByName("WebInscriptions");
  var getLastRow = recordSheet.getLastRow();
  return recordSheet.getRange(2, 1, getLastRow -1, 9).getValues();
}

function startForm()
{
  var form = HtmlService.createHtmlOutputFromFile("Modal");
  SpreadsheetApp.getUi().showModalDialog(form, 'Manage New Submissions');
}

function addMenu()
{
  var ui = SpreadsheetApp.getUi()
  ui.createMenu('HR-Recruitment')
    .addItem('New Submissions','startForm')
    .addItem('Manage Recruits','startForm')
    .addToUi();
}

function onOpen(e)
{
  addMenu;
}
```
<p>Modal.html</p>
<pre class="lang-html prettyprint-override"><code><!DOCTYPE html>
<html>
  <head>
    <base target="_top">

      <script>
        function loadRecords(record)
          {
            google.script.run.withSuccessHandler
              (function(ar)
                {
                  var record = document.getElementById("record").value;
                    //console.log (ar);
                    //console.log (record);

                  var recordCount = 0;

                  ar.forEach(function(item, index)
                      {
                        if(index == record - 1)
                            {
                              document.getElementById("inscriptionDate").value = item[0];
                              document.getElementById("firstName").value = item[1];
                              document.getElementById("lastName").value = item[2];
                              document.getElementById("gender").value = item[3];
                              document.getElementById("email").value = item[4];
                              document.getElementById("telNumWhatsApp").value = item[5];
                              document.getElementById("location").value = item[6];
                              document.getElementById("visaImageUpload").value = item[7];
                              document.getElementById("commentMessage").value = item[8];
                              document.getElementById("referrer").value = item[9];
                            }
                        recordCount ++;
                      });

                      console.log (recordCount);
                      document.getElementById("maxRecord").value = recordCount;
                }).getList();
          }

          function NextRecord()
            {
              var record = document.getElementById("record").value;
              var maxRecord = document.getElementById("maxRecord").value;
              var nextRecord = Number record + 1;

              if(nextRecord <= maxRecord)
              {
                document.getElementById ("record").value  = nextRecord;
                loadRecords();
              }
            }

          function PreviousRecord()
            {
              var record = document.getElementById("record").value;
              var previousRecord = Number record - 1;

              if(previousRecord >= 1)
              {
                document.getElementById ("record").value  = previousRecord;
                loadRecords();
              }
            }

        //loadRecords();

      </script>

  </head>
  <body>
    Inscription Date: <input type="text" id="inscriptionDate"/><br>
    First Name: <input type="text" id="firstName"/><br>
    Last Name: <input type="text" id="lastName"/><br>
    Gender: <input type="text" id="gender"/><br>
    Email: <input type="text" id="email"/><br>
    Telephone Number (WhatsApp): <input type="text" id="telNumWhatsApp"/><br>
    Location: <input type="text" id="location"/><br>
    VISA Image Upload: <input type="text" id="visaImageUpload"/><br>
    Comment or Message: <input type="text" id="commentMessage"/><br>
    Referrer: <input type="text" id="referrer"/><br>

    <input type="button" value = "PREVIOUS" onclick="PreviousRecord"/>
    <input type="text" value="1" id="record" size="2px"/>
    <input type="hidden" id="maxRecord"/>
    <input type="button" value = "NEXT" onclick="NextRecord"/>

  <script>loadRecords();</script>

  </body>
</html>
</code>```

Google Sheet image

答:
Given that the youtube guy removed his code and doesn't answer on comments it's obviously that there is something terribly wrong with his code.

As far as I can tell the main problem was that you can't return an array from the function getList() into the HTML form. You need to convert it into a string with return JSON.stringify(array) and then (within HTML form) to convert it back into an array with var array = JSON.parse(array).

Basically, if you add the JSON.stringify and JSON.parse and add the brackets as @Rubén said, it should work.

Just in case, here is my a bit rewritten code:

Modal.html

<!DOCTYPE html>

    <base target="_top">

    Inscription Date:            <input type="text" id="inscriptionDate"/>

    First Name:                  <input type="text" id="firstName"/>

    Last Name:                   <input type="text" id="lastName"/>

    Gender:                      <input type="text" id="gender"/>

    Email:                       <input type="text" id="email"/>

    Telephone Number (WhatsApp): <input type="text" id="telNumWhatsApp"/>

    Location:                    <input type="text" id="location"/>

    VISA Image Upload:           <input type="text" id="visaImageUpload"/>

    Comment or Message:          <input type="text" id="commentMessage"/>

    Referrer:                    <input type="text" id="referrer"/>

    <input type="button" value = "PREVIOUS" onClick="PreviousRecord()"/> // <-- don't forget the brackets here
    <input type="text"   value = "1" id = "record" size = "2px"/>
    <input type="hidden" value = ""  id = "maxRecord"/>
    <input type="button" value = "NEXT" onClick="NextRecord()"/> // <-- don't forget the brackets here

```
<p><strong>Code.gs</strong></p>
<pre class="lang-js prettyprint-override"><code>function getList(){
  var url = 'https://docs.google.com/spreadsheets/d/1QkSdtybPHA9IrWH2VPw44WtQ9dN_-9KjRVNOuCylMCk/edit#gid=0';
  var ss= SpreadsheetApp.openByUrl(url);
  // var ss = SpreadsheetApp.getActiveSpreadsheet();
  var recordSheet = ss.getSheetByName("WebInscriptions");
  var lastRow = recordSheet.getLastRow();
  var list = recordSheet.getRange(2, 1, lastRow-1, 10).getValues();
  return JSON.stringify(list); // <--- here we return a string instead of the array
}

function startForm() {
  var form = HtmlService.createHtmlOutputFromFile("Modal.html");
  SpreadsheetApp.getUi().showModalDialog(form, 'Manage New Submissions');
}

function addMenu() {
  var ui = SpreadsheetApp.getUi()
  ui.createMenu('HR-Recruitment')
    .addItem('New Submissions','startForm')
    .addItem('Manage Recruits','startForm')
    .addToUi();
}

function onOpen(e) { addMenu() }
</code>```

Body:
I have followed a tutorial "Create HTML Form that Moves through RecordSet on Google Sheets" done by  Code With Curt.
https://www.youtube.com/watch?v=V9ptq7tZV50&t=152s

The project doesn't look that complicated. It is a simple CRUD app that I want to run in a modal dialog in google sheets, I am a newbie, I really tried to understand the code that I was copying from the video and not make any typos. The form shows up OK from the custom menu but it is not populating with the data from the sheet. The only error I can see is in the console which says "Uncaught ReferenceError: loadRecords is not defined" I have double checked the variable and function names but just can't see the error.

Any help would be appreciated.

Code.gs

function getList()
{
  var url = 'https://docs.google.com/spreadsheets/d/1QkSdtybPHA9IrWH2VPw44WtQ9dN_-9KjRVNOuCylMCk/edit#gid=0';
  var ss= SpreadsheetApp.openByUrl(url);
  //var ss = SpreadsheetApp.getActiveSpreadsheet();
  var recordSheet = ss.getSheetByName("WebInscriptions");
  var getLastRow = recordSheet.getLastRow();
  return recordSheet.getRange(2, 1, getLastRow -1, 9).getValues();
}

function startForm()
{
  var form = HtmlService.createHtmlOutputFromFile("Modal");
  SpreadsheetApp.getUi().showModalDialog(form, 'Manage New Submissions');
}

function addMenu()
{
  var ui = SpreadsheetApp.getUi()
  ui.createMenu('HR-Recruitment')
    .addItem('New Submissions','startForm')
    .addItem('Manage Recruits','startForm')
    .addToUi();
}

function onOpen(e)
{
  addMenu;
}

Modal.html

<!DOCTYPE html>

    <base target="_top">

    Inscription Date: <input type="text" id="inscriptionDate"/>

    First Name: <input type="text" id="firstName"/>

    Last Name: <input type="text" id="lastName"/>

    Gender: <input type="text" id="gender"/>

    Email: <input type="text" id="email"/>

    Telephone Number (WhatsApp): <input type="text" id="telNumWhatsApp"/>

    Location: <input type="text" id="location"/>

    VISA Image Upload: <input type="text" id="visaImageUpload"/>

    Comment or Message: <input type="text" id="commentMessage"/>

    Referrer: <input type="text" id="referrer"/>

    <input type="button" value = "PREVIOUS" onclick="PreviousRecord"/>
    <input type="text" value="1" id="record" size="2px"/>
    <input type="hidden" id="maxRecord"/>
    <input type="button" value = "NEXT" onclick="NextRecord"/>

Google Sheet image

Body:
Given that the youtube guy removed his code and doesn't answer on comments it's obviously that there is something terribly wrong with his code.

As far as I can tell the main problem was that you can't return an array from the function getList() into the HTML form. You need to convert it into a string with return JSON.stringify(array) and then (within HTML form) to convert it back into an array with var array = JSON.parse(array).

Basically, if you add the JSON.stringify and JSON.parse and add the brackets as @Rubén said, it should work.

Just in case, here is my a bit rewritten code:

Modal.html

<!DOCTYPE html>
<html>
  <head>
    <base target="_top">

    <script>

      function NextRecord() {
        var record = document.getElementById("record").value;
        var maxRecord = document.getElementById("maxRecord").value;
        var nextRecord = +record + 1;
        if(nextRecord <= maxRecord) {
          document.getElementById ("record").value = nextRecord;
          google.script.run.withSuccessHandler(loadRecords).getList();
        }
      }

      function PreviousRecord() {
        var record = document.getElementById("record").value;
        var previousRecord = +record - 1;
        if(previousRecord >= 1) {
          document.getElementById ("record").value = previousRecord;
          google.script.run.withSuccessHandler(loadRecords).getList();
        }
      }

      function loadRecords(ar) {
        ar = JSON.parse(ar); // <--- here we parse the string back into an array
        var record = document.getElementById("record").value;
        document.getElementById("maxRecord").value = ar.length;

        var item = ar[+record-1];
        document.getElementById("inscriptionDate").value = item[0];
        document.getElementById("firstName").value       = item[1];
        document.getElementById("lastName").value        = item[2];
        document.getElementById("gender").value          = item[3];
        document.getElementById("email").value           = item[4];
        document.getElementById("telNumWhatsApp").value  = item[5];
        document.getElementById("location").value        = item[6];
        document.getElementById("visaImageUpload").value = item[7];
        document.getElementById("commentMessage").value  = item[8];
        document.getElementById("referrer").value        = item[9];
      }

      google.script.run.withSuccessHandler(loadRecords).getList();

    </script>

  </head>

  <body>

    Inscription Date:            <input type="text" id="inscriptionDate"/><br>
    First Name:                  <input type="text" id="firstName"/><br>
    Last Name:                   <input type="text" id="lastName"/><br>
    Gender:                      <input type="text" id="gender"/><br>
    Email:                       <input type="text" id="email"/><br>
    Telephone Number (WhatsApp): <input type="text" id="telNumWhatsApp"/><br>
    Location:                    <input type="text" id="location"/><br>
    VISA Image Upload:           <input type="text" id="visaImageUpload"/><br>
    Comment or Message:          <input type="text" id="commentMessage"/><br>
    Referrer:                    <input type="text" id="referrer"/><br>

    <input type="button" value = "PREVIOUS" onClick="PreviousRecord()"/> // <-- don't forget the brackets here
    <input type="text"   value = "1" id = "record" size = "2px"/>
    <input type="hidden" value = ""  id = "maxRecord"/>
    <input type="button" value = "NEXT" onClick="NextRecord()"/> // <-- don't forget the brackets here

  </body>
</html>

Code.gs

function getList(){
  var url = 'https://docs.google.com/spreadsheets/d/1QkSdtybPHA9IrWH2VPw44WtQ9dN_-9KjRVNOuCylMCk/edit#gid=0';
  var ss= SpreadsheetApp.openByUrl(url);
  // var ss = SpreadsheetApp.getActiveSpreadsheet();
  var recordSheet = ss.getSheetByName("WebInscriptions");
  var lastRow = recordSheet.getLastRow();
  var list = recordSheet.getRange(2, 1, lastRow-1, 10).getValues();
  return JSON.stringify(list); // <--- here we return a string instead of the array
}

function startForm() {
  var form = HtmlService.createHtmlOutputFromFile("Modal.html");
  SpreadsheetApp.getUi().showModalDialog(form, 'Manage New Submissions');
}

function addMenu() {
  var ui = SpreadsheetApp.getUi()
  ui.createMenu('HR-Recruitment')
    .addItem('New Submissions','startForm')
    .addItem('Manage Recruits','startForm')
    .addToUi();
}

function onOpen(e) { addMenu() }


来源: stackexchange

问:
Getting script component from a clicked object
I'm trying to get the script component of an object once it has been clicked by a player, then run a specific function from the script when clicked. What I want to go is ether find the script based of the clicked objects name, or just a general way of getting scripts without the class name as it changes with each script. I've looked for way to do both but none work. I may just be implementing it bad so would love some help.</p>

答:
If you are just after a method of identifying a specific component then I'd recommend adding an identifier into the component to search for such as a public variable.

That way you can easily get all the scripts on a GameObject and iterate through them checking for that public variable.

ContentLicense: CC BY-SA 4.0


问:
Connect Android Studio and Wear 3.0 smartwatch via wi-fi
ADB debugging needs connection between Android Studio and Wear 3.0 smartwatch (Samsung Galaxy SW 4). How make them work together?</p>

答:
Switch ON Developer Mode on your Smartwatch, including A) Activation Developer Mode in Settings (in most cases push many times on Settings-> About watch -> Software -> Software Version) B) Set ON ADB Debugging C) Set ON Wi-Fi Debugging

Connect work station with Android Studio and smartwatch wear 3.0 to the same wi-fi network

Connect smartwatch via usb charger with workstation (obligatory in most cases at least once)

Send the command in Terminal - adb connect XXX.YYY.Z.A:5555, where XXX.YYY.Z.A - address of your Wi-fi - find it in settings of wifi in smartwatch or workstation

Accept the request on the smartwatch (always allow / always trust);

Check in Studio the change from No Device to your smartwatch.

Notes:

sometimes it's obligatory to turn on \ off ADB Debugging and Wi-Fi Debugging on smartwatch and try again;

sometimes the connection between smartwatch and Studio is working without USB connection at all (but mostly one time and you need to repeat "adb connect XXX.YYY.Z.A:5555";

sometimes you need smartphone in the same Wi Fi network with workstation and smartwatch, sometimes it works well without smartphone.


问:
Is there a way to get corresponding index value in a 2nd array using the 1st array as a reference in Javascript?
I am very new to algorithm and programming in general. I may require more explanation than an average fellow. Apologies in advance.

My aim is to Create a function that returns a number, based on the string provided. I have been told that this can be done using loops. I believe my errors lies in the if statement. However, cant seem to figure it out. I would be glad if somebody could help.

```<code>function word(s) {
  let str = ["one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "zero"];
  let int = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0];

  for (let j = 0; j < int.length; j++) {
    for (let i = 0; i < str.length; i++) {
      if (s === str[i]) {
        return int[j]
      }
    }
  }
}
</code>```

答:
Actually, You dont need loop also. You can rearrange the strings and return the index based on the arrangement of the word in array.

const str = ["zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine"];

function word(s) {
  return str.indexOf(s);
}
console.log(word("five"))

// In case you dont want to change order

function word1(s) {
  const str = ["one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "zero"];
  const index = str.indexOf(s);
  return index < 9 ? index+1 : 0
}

console.log(word1("five"))
console.log(word1("zero"))

// Other way get index ussing findIndex

function word2(s) {
  return str.findIndex(item => item === s);
}
console.log(word2("five"))

// Other using single loop

function word3(s) {
  for (let i in str) {
    if (str[i] === s) return i;
  }
  // Incase not found
  return -1;
}
console.log(word3("five"))```

Body:
I am very new to algorithm and programming in general. I may require more explanation than an average fellow. Apologies in advance.

My aim is to Create a function that returns a number, based on the string provided. I have been told that this can be done using loops. I believe my errors lies in the if statement. However, cant seem to figure it out. I would be glad if somebody could help.

function word(s) {
  let str = ["one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "zero"];
  let int = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0];

  for (let j = 0; j < int.length; j++) {
    for (let i = 0; i < str.length; i++) {
      if (s === str[i]) {
        return int[j]
      }
    }
  }
}


问:
How to use htpasswd protection in Tomcat?
I have already created a user database file using Apache's htpasswd command. This file is now used by several other application like apache and subversion.

Users in are created like this:

```<code>htpasswd /path/to/users.htpasswd peter
</code>```

This user file is global, not per directory.

How I can make Tomcat 6 use this same file as a security realm?

答:
There are two options:

Use Apache as a front end to the tomcat (using either mod_jk or mod_proxy_ajp) and the Apache do the authentication. You can find details on how to do so here

If you want the tomcat to do the authentication, then you need ot use something else than the htpasswd file. There are 4 ways to save the users' credentials - using database, JNDI/LDAP, an XML file or a JAAS provider. You can read about all the options in the Realm Configuration HOW-TO.

OwnerDisplayName: Juha

ContentLicense: CC BY-SA 3.0

Body:
I have already created a user database file using Apache's htpasswd command. This file is now used by several other application like apache and subversion.

Users in are created like this:

htpasswd /path/to/users.htpasswd peter

This user file is global, not per directory.

How I can make Tomcat 6 use this same file as a security realm?

LastEditorDisplayName: Juha

OwnerDisplayName: David Rabinowitz

ContentLicense: CC BY-SA 2.5


问:
How to unit test repository method
I have this method to unit test:

```<code>public virtual TEntity Get(int id)
        {
            return _db.Set<TEntity>().Find(id);
        }
</code>```

Could someone please tell me how to unit test this?

I'm thinking what I need to test is that Find is called with the correct id?

First I was trying to mock the context _db using Moq. Set isn't virtual though so can't use Verify.

Could someone please suggest an alternative method of testing this?

答:
I put a generic repository implementation on github that allows easy testing. You can check it out here:

https://github.com/rcravens/GenericRepository

The repository implementation itself is tested and there is also a fake (in memory) repository implementation that you can inject in to test higher level code.

Bob

Title: How to unit test repository method

Body:
I have this method to unit test:

public virtual TEntity Get(int id)
        {
            return _db.Set<TEntity>().Find(id);
        }

Could someone please tell me how to unit test this?

I'm thinking what I need to test is that Find is called with the correct id?

First I was trying to mock the context _db using Moq. Set isn't virtual though so can't use Verify.

Could someone please suggest an alternative method of testing this?


问:
How to install Google chrome in a docker container
I'm trying to install chrome in a docker container. I execute:

```<code>RUN apt-get install -y wget
RUN wget -q https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
RUN dpkg -i google-chrome-stable_current_amd64.deb  # problem here
RUN apt -f install -y
</code>```

The problem is that dpkg -i fails because of missing dependencies. In principle this is not a big problem, as the next command should fix this, and indeed it does it when run interactively from within the container. But the problem is that when building a docker container this error makes the build process to stop:

```<code>dpkg: error processing package google-chrome-stable (--install):
 dependency problems - leaving unconfigured
Errors were encountered while processing:
 google-chrome-stable
root@78b45ab9aa33:/#
exit
</code>```

How can I overcome this problem? Isn't there a simpler way to install chrome without provoking the dependence problem? I can't find the repository to add so I can run a regular apg-get install google-chrome, that is what I'd like to do. In the google linux repository they just mention that the "the packages will automatically configure the repository settings necessary". Which is not exactly what I get...

答:
After the comment by @Facty and some more search, I found two solutions to install Google Chrome without raising this error. I'll post it below for future references or people having the same issue.

There are actually two ways to install Chrome on a docker container:

If you download the deb file manually, you can install it with apt-get instead of dpkg. This will automatically install the dependencies without having to call apt -f install -y later :

```<code>RUN apt-get install -y wget
RUN wget -q https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
RUN apt-get install ./google-chrome-stable_current_amd64.deb
</code>```

The other solution is to add the repositories (installing the gpg key) and install from them directly, skipping the manual download:

```<code>RUN apt-get install -y wget
RUN wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - \
    && echo "deb http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list
RUN apt-get update && apt-get -y install google-chrome-stable
</code>```

Body:
I'm trying to install chrome in a docker container. I execute:

RUN apt-get install -y wget
RUN wget -q https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
RUN dpkg -i google-chrome-stable_current_amd64.deb  # problem here
RUN apt -f install -y

The problem is that dpkg -i fails because of missing dependencies. In principle this is not a big problem, as the next command should fix this, and indeed it does it when run interactively from within the container. But the problem is that when building a docker container this error makes the build process to stop:

dpkg: error processing package google-chrome-stable (--install):
 dependency problems - leaving unconfigured
Errors were encountered while processing:
 google-chrome-stable
root@78b45ab9aa33:/#
exit

How can I overcome this problem? Isn't there a simpler way to install chrome without provoking the dependence problem? I can't find the repository to add so I can run a regular apg-get install google-chrome, that is what I'd like to do. In the google linux repository they just mention that the "the packages will automatically configure the repository settings necessary". Which is not exactly what I get...

Body:
After the comment by @Facty and some more search, I found two solutions to install Google Chrome without raising this error. I'll post it below for future references or people having the same issue.

There are actually two ways to install Chrome on a docker container:

If you download the deb file manually, you can install it with apt-get instead of dpkg. This will automatically install the dependencies without having to call apt -f install -y later :

RUN apt-get install -y wget
RUN wget -q https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
RUN apt-get install ./google-chrome-stable_current_amd64.deb

The other solution is to add the repositories (installing the gpg key) and install from them directly, skipping the manual download:

RUN apt-get install -y wget
RUN wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - \
    && echo "deb http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list
RUN apt-get update && apt-get -y install google-chrome-stable


问:
Java and spring boot: Can you automatically generate dependencies in eclipse or another program?
I have a problem with an application built in java and spring boot.

1/ How can to generate eclipse project from only src folder? Is it possible to somehow automatically generate dependencies (pom.xml etc.)? I don't have a pom.xml file, just a src folder? Is there any way to automatically generate project from src folder in e.g. eclipse and generate dependencies automatically?

2/ Second question: I would like to move a java application from one server to new another server. I don't have project files. I have the structure as below in Tomcat webapps:

Is it possible to generate a project from this strukture in eclipse or intelliJ?
I am asking for help and some step-by-step instructions. I'm just learning java

答:
Maven is Separate from Java, Maven is used to inject dependencies into your application so that you may import them freely in your project.

If you are using Spring, you may use the initializer to add dependencies and create a pom.xml , that in the end you may import to eclipse in order to get your project started.

Spring Initializr


问:
How can I get a --version to the root of a typer.Typer application?
My CLI applications typically have subcommands. I want to have the --version flag at the root of my CLI applications, but with Typer I've only seen ways to put it to a command. I want to add it to the typer.Typer object (the root) itself. How can I do that?

What I've tried

import typer
from typing import Optional

__version__ = "0.1.0"

def version_callback(value: bool):
    if value:
        typer.echo(f"Awesome CLI Version: {__version__}")
        raise typer.Exit()

app = typer.Typer(
    add_completion=False,
)

@app.command()
def main(
    version: Optional[bool] = typer.Option(
        None, "--version", callback=version_callback
    ),
) -> None:
    pass

@app.command()
def foo() -> None:
    pass

if __name__ == "__main__":
    app()
```
<p>This gives</p>
```$ python cli.py --help
Usage: cli.py [OPTIONS] COMMAND [ARGS]...

Options:
  --help  Show this message and exit.

Commands:
  foo
  main

$ python cli.py main --help
Usage: cli.py main [OPTIONS]

Options:
  --version
  --help     Show this message and exit.
```
<p>What I wanted:</p>
```$ python cli.py --help
Usage: cli.py [OPTIONS] COMMAND [ARGS]...

Options:
  --version
  --help  Show this message and exit.

Commands:
  foo
```

答:
This is addressed in the documentation:

But as those CLI parameters are handled by each of those commands, they don't allow us to create CLI parameters for the main CLI application itself.

But we can use @app.callback() for that.

It's very similar to @app.command(), but it declares the CLI parameters for the main CLI application (before the commands):

To do what you want, you could write something like this:

```<code>import typer
from typing import Optional

__version__ = "0.1.0"

def version_callback(value: bool):
    if value:
        typer.echo(f"Awesome CLI Version: {__version__}")
        raise typer.Exit()

app = typer.Typer(
    add_completion=False,
)

@app.callback()
def common(
    ctx: typer.Context,
    version: bool = typer.Option(None, "--version", callback=version_callback),
):
    pass

@app.command()
def main() -> None:
    pass

@app.command()
def foo() -> None:
    pass

if __name__ == "__main__":
    app()
</code>```

Which gives us:

```<code>$ python typertest.py --help
Usage: typertest.py [OPTIONS] COMMAND [ARGS]...

Options:
  --version
  --help     Show this message and exit.

Commands:
  foo
  main
</code>```

Body:
My CLI applications typically have subcommands. I want to have the --version flag at the root of my CLI applications, but with Typer I've only seen ways to put it to a command. I want to add it to the typer.Typer object (the root) itself. How can I do that?

What I've tried

import typer
from typing import Optional

__version__ = "0.1.0"

def version_callback(value: bool):
    if value:
        typer.echo(f"Awesome CLI Version: {__version__}")
        raise typer.Exit()

app = typer.Typer(
    add_completion=False,
)

@app.command()
def main(
    version: Optional[bool] = typer.Option(
        None, "--version", callback=version_callback
    ),
) -> None:
    pass

@app.command()
def foo() -> None:
    pass

if __name__ == "__main__":
    app()

This gives

$ python cli.py --help
Usage: cli.py [OPTIONS] COMMAND [ARGS]...

Options:
  --help  Show this message and exit.

Commands:
  foo
  main

$ python cli.py main --help
Usage: cli.py main [OPTIONS]

Options:
  --version
  --help     Show this message and exit.

What I wanted:

$ python cli.py --help
Usage: cli.py [OPTIONS] COMMAND [ARGS]...

Options:
  --version
  --help  Show this message and exit.

Commands:
  foo

Body:
This is addressed in the documentation:

But as those CLI parameters are handled by each of those commands, they don't allow us to create CLI parameters for the main CLI application itself.

But we can use @app.callback() for that.

It's very similar to @app.command(), but it declares the CLI parameters for the main CLI application (before the commands):

To do what you want, you could write something like this:

import typer
from typing import Optional

__version__ = "0.1.0"

def version_callback(value: bool):
    if value:
        typer.echo(f"Awesome CLI Version: {__version__}")
        raise typer.Exit()

app = typer.Typer(
    add_completion=False,
)

@app.callback()
def common(
    ctx: typer.Context,
    version: bool = typer.Option(None, "--version", callback=version_callback),
):
    pass

@app.command()
def main() -> None:
    pass

@app.command()
def foo() -> None:
    pass

if __name__ == "__main__":
    app()

Which gives us:

$ python typertest.py --help
Usage: typertest.py [OPTIONS] COMMAND [ARGS]...

Options:
  --version
  --help     Show this message and exit.

Commands:
  foo
  main


问:
Input from jtextfield doesnt get read while in a for loop
My problem is that I have a for loop and while this loop is running I still want inputs from JTextField to get read and not interrupt the loop or timing when the line gets printed.</p>
```<code>public class test {

    public void Play() {

        JTextField textField = new JTextField();
        textField.addKeyListener(new KeyChecker());
        JFrame jframe = new JFrame();
        jframe.add(textField);
        jframe.setSize(200, 30);
        jframe.setVisible(true);
    }
}

class KeyChecker extends KeyAdapter {

    @Override
    public void keyPressed(KeyEvent event)
    {
        for(int i = 0; i < 1; i = 0)
        {
            char Input = event.getKeyChar();
            if(Input == 'a')
            {
                System.out.println("working");
            } else {
                System.out.println("not working");
            }
            try
            {
                Thread.sleep(1000);
            }
            catch(InterruptedException ex)
            {
                Thread.currentThread().interrupt();
            }
        }
    }
}
</code>```

答:
In your code, the keyPressed method gets called by the Event Dispatch Thread (https://docs.oracle.com/javase/tutorial/uiswing/concurrency/dispatch.html) every time you press a key in the textfield.

In this context the KeyEvent event parameter represents a sing key press event, so it makes no sense to create a loop inside an event method, as maloomeister correctly pointed out.

Instead you should perform your logic using the state of your classes, either KeyChecker or test.
I don't really understand why you should regularly check for a key being pressed (and the purpose of a textfield BTW), anyway the following is a possible solution using a separate thread.
Of course you can also do the loop in the main thread (which is not the EDT), but in a non-trivial application you should never do that.

```<code>import java.awt.event.KeyEvent;

import javax.swing.JFrame;
import javax.swing.JTextField;

public class Test {
    public static void main(String[] args) {
        KeyChecker keyChecker = new KeyChecker();
        JTextField textField = new JTextField(40);
        textField.addKeyListener(keyChecker);
        JFrame jframe = new JFrame();
        jframe.add(textField);
        jframe.pack();
        jframe.setVisible(true);

        Thread t = new Thread(() -> {
            while(true) {
                char currentKey = keyChecker.getCurrentPressedKey();
                switch (currentKey) {
                    case 'a':
                        System.out.println("working");
                        break;
                    default:
                        System.out.println("not working");
                }

                try {
                    Thread.sleep(1000);
                } catch (InterruptedException ex) {
                    break;
                }
            }
        });

        t.start();
    }
}

class KeyChecker extends KeyAdapter {
    private char currentPressedKey = 0;

    @Override
    public void keyPressed(KeyEvent event) {
        currentPressedKey = event.getKeyChar();
    }

    @Override
    public void keyReleased(KeyEvent e) {
        currentPressedKey=0;
    }

    public char getCurrentPressedKey() {
        return currentPressedKey;
    }
}
</code>```

Body:
My problem is that I have a for loop and while this loop is running I still want inputs from JTextField to get read and not interrupt the loop or timing when the line gets printed.

public class test {

    public void Play() {

        JTextField textField = new JTextField();
        textField.addKeyListener(new KeyChecker());
        JFrame jframe = new JFrame();
        jframe.add(textField);
        jframe.setSize(200, 30);
        jframe.setVisible(true);
    }
}

class KeyChecker extends KeyAdapter {

    @Override
    public void keyPressed(KeyEvent event)
    {
        for(int i = 0; i < 1; i = 0)
        {
            char Input = event.getKeyChar();
            if(Input == 'a')
            {
                System.out.println("working");
            } else {
                System.out.println("not working");
            }
            try
            {
                Thread.sleep(1000);
            }
            catch(InterruptedException ex)
            {
                Thread.currentThread().interrupt();
            }
        }
    }
}

Body:
In your code, the keyPressed method gets called by the Event Dispatch Thread (https://docs.oracle.com/javase/tutorial/uiswing/concurrency/dispatch.html) every time you press a key in the textfield.

In this context the KeyEvent event parameter represents a sing key press event, so it makes no sense to create a loop inside an event method, as maloomeister correctly pointed out.

Instead you should perform your logic using the state of your classes, either KeyChecker or test.
I don't really understand why you should regularly check for a key being pressed (and the purpose of a textfield BTW), anyway the following is a possible solution using a separate thread.
Of course you can also do the loop in the main thread (which is not the EDT), but in a non-trivial application you should never do that.

import java.awt.event.KeyEvent;

import javax.swing.JFrame;
import javax.swing.JTextField;

public class Test {
    public static void main(String[] args) {
        KeyChecker keyChecker = new KeyChecker();
        JTextField textField = new JTextField(40);
        textField.addKeyListener(keyChecker);
        JFrame jframe = new JFrame();
        jframe.add(textField);
        jframe.pack();
        jframe.setVisible(true);

        Thread t = new Thread(() -> {
            while(true) {
                char currentKey = keyChecker.getCurrentPressedKey();
                switch (currentKey) {
                    case 'a':
                        System.out.println("working");
                        break;
                    default:
                        System.out.println("not working");
                }

                try {
                    Thread.sleep(1000);
                } catch (InterruptedException ex) {
                    break;
                }
            }
        });

        t.start();
    }
}

class KeyChecker extends KeyAdapter {
    private char currentPressedKey = 0;

    @Override
    public void keyPressed(KeyEvent event) {
        currentPressedKey = event.getKeyChar();
    }

    @Override
    public void keyReleased(KeyEvent e) {
        currentPressedKey=0;
    }

    public char getCurrentPressedKey() {
        return currentPressedKey;
    }
}


问:
jQuery .click() event for multiple div's
I have some search results that I'm outputting that are of this form:

```<code>  <div id="result" title="nCgQDjiotG0"><img src="http://i.ytimg.com/vi/nCgQDjiotG0/default.jpg"></div>
</code>```

There is one of these for each result. I'm trying to detect which one is clicked and then do some stuff. Each result has a unique title, but the same id. How do I use .click() to know which one was clicked so I can get it's ID and use it?

Here's how I'm getting the HTML from above:

```<code>$.each(response.data.items, function(i,data)
{
var video_id=data.id;
var video_title=data.title;
var video_thumb=data.thumbnail.sqDefault;

var search_results="<div id='result' title='"+video_id+"'><img src='"+video_thumb+"'></div>";
$("#searchresults").append($(search_results));
</code>```

I tried

```<code> $('div').click(function(){
    alert(this.id);
});
</code>```

and the alert says "searchresults" (no quotes).

答:
You can't have the same ID on multiple tags.  You will have to fix that.  You can use the same class, but there can only be one object in the page with a given ID value.

this.id will fetch the id value of the item clicked on and this should work fine once you get rid of conflicting IDs:

```<code>$('div').click(function(){
    alert(this.id);
});
</code>```

This code should be something this:

```<code>var search_results="<div id='result'" + video_id + " title='"+video_id+"'><img src='"+video_thumb+"'></div>";
$("#searchresults").append(search_results);
</code>```

to coin a unique id value for each incarnation and append will just take the string - you don't need to turn it into a jQuery object.

Body:
I have some search results that I'm outputting that are of this form:

There is one of these for each result. I'm trying to detect which one is clicked and then do some stuff. Each result has a unique title, but the same id. How do I use .click() to know which one was clicked so I can get it's ID and use it?

Here's how I'm getting the HTML from above:

$.each(response.data.items, function(i,data)
{
var video_id=data.id;
var video_title=data.title;
var video_thumb=data.thumbnail.sqDefault;

var search_results="

";
$("#searchresults").append($(search_results));

I tried

 $('div').click(function(){
    alert(this.id);
});

and the alert says "searchresults" (no quotes).

Body:
You can't have the same ID on multiple tags.  You will have to fix that.  You can use the same class, but there can only be one object in the page with a given ID value.

this.id will fetch the id value of the item clicked on and this should work fine once you get rid of conflicting IDs:

$('div').click(function(){
    alert(this.id);
});

This code should be something this:

var search_results="<div id='result'" + video_id + " title='"+video_id+"'><img src='"+video_thumb+"'></div>";
$("#searchresults").append(search_results);

to coin a unique id value for each incarnation and append will just take the string - you don't need to turn it into a jQuery object.


问:
Execute action without redirecting(Add to wishlist)
So, I have some product cards that I'm displaying with a foreach loop. When I click a link, I want to add that product to my wishlist (Session["wishList"]). That calls a function and redirects me to /product/wishlist/01, where 01 is the product id.

My temporary fix is return Content(""); but no reloading would be better.

My code:

```<code><code>
 <a href="@Url.Action("AddToWishList", "Product", new {id = item.Id})"><i class="far fa-heart"></i></a>
</code>
</code>```

Controller:

```<code><code>
public ActionResult AddToWishList(int id)
        {
            if (Session["email"] != null && Session["role"] != null && (WebApplication1.Models.RoleType)Session["role"] == Models.RoleType.User)
            {
                var wishList = (List<int>)Session["wishList"];
                if (wishList.Contains(id))
                {
                    wishList.Remove(id);
                }
                else
                {
                    wishList.Add(id);
                }
                Session["wishList"] = wishList;
            }
            return Content("<script type='text/javascript'>window.history.back();</script>");
        }</code>
</code>```

答:
Implementing callbacks in your page could work:

ASP.Net : https://learn.microsoft.com/en-us/previous-versions/aspnet/ms366518(v=vs.100)

ASP.Net MVC : https://docs.devexpress.com/AspNetMvc/9052/common-features/callback-based-functionality

Body:
So, I have some product cards that I'm displaying with a foreach loop. When I click a link, I want to add that product to my wishlist (Session["wishList"]). That calls a function and redirects me to /product/wishlist/01, where 01 is the product id.

My temporary fix is return Content(""); but no reloading would be better.

My code:

Controller:

public ActionResult AddToWishList(int id)
        {
            if (Session["email"] != null && Session["role"] != null && (WebApplication1.Models.RoleType)Session["role"] == Models.RoleType.User)
            {
                var wishList = (List<int>)Session["wishList"];
                if (wishList.Contains(id))
                {
                    wishList.Remove(id);
                }
                else
                {
                    wishList.Add(id);
                }
                Session["wishList"] = wishList;
            }
            return Content("");
        }


问:
Is it possible to answer dialog questions when installing under docker?
Is it possible to somehow answer the questions that are presented as dialogs when installing some packages using apt-get?

For instance I'm trying to setup a container containing the mail-stack-delivery package with:

```<code>FROM ubuntu

RUN apt-get install -y mail-stack-delivery
</code>```

However that dockerfile generates dozens of errors when built that are along the lines of:

```<code>debconf: unable to initialize frontend: Dialog
debconf: (TERM is not set, so the dialog frontend is not usable.)
debconf: falling back to frontend: Readline
debconf: unable to initialize frontend: Readline
debconf: (Can't locate Term/ReadLine.pm in @INC (@INC contains: /etc/perl /usr/local/lib/perl/5.14.2 /usr/local/share/perl/5.14.2 /usr/lib/perl5 /usr/share/perl5 /usr/lib/perl/5.14 /usr/share/perl/5.14 /usr/local/lib/site_perl .) at /usr/share/perl5/Debconf/FrontEnd/Readline.pm line 7, <> line 11.)
debconf: falling back to frontend: Teletype
dpkg-preconfigure: unable to re-open stdin:
</code>```

From what I understand I just simply can't respond to the dialogs, but is there some way that I can pass a parameter to answer each question in advance? I know that it's just changing some configurations, so I could do it after the fact, but presumably it's better to let the install scripts do it so everything gets set properly.

答:
The reason why ENV DEBIAN_FRONTEND=noninteractive (or the legacy syntax ENV DEBIAN_FRONTEND noninteractive) sometimes works and sometimes does not has to do with the usage of sudo. By default sudo ignores the environment of the current user and uses a clean one. This can be controlled via the sudo --preserve-env flag. Obviously adding this to every sudo invocation is cumbersome, but it is easy to make the entire system for every user non-interactive by adding the environment variable to the /etc/environment file of the operating system.

```<code>RUN set -a \
 && eval "$(sudo tee --append /etc/environment <<<'DEBIAN_FRONTEND=noninteractive')" \
 && set +a \
 && sudo apt-get update \
 && sudo apt-get install mail-stack-delivery
</code>```

Quickly dissecting the important snippet in isolation:

# export every variable that follows
set -a

# appends the given string to the `/etc/environment` file as root
# tee prints its input to standard out
# eval interprets the output of tee
eval "$(sudo tee --append /etc/environment <<<'DEBIAN_FRONTEND=noninteractive')"

# stop exporting everything
set +a
```

It was mentioned before the DEBIAN_FRONTEND=noninteractive should not be set in such a global fashion. This depends on what the intend of your image is. If it is meant for automation and not for humans then it is totally fine to set it globally.

Body:
Is it possible to somehow answer the questions that are presented as dialogs when installing some packages using apt-get?

For instance I'm trying to setup a container containing the mail-stack-delivery package with:

FROM ubuntu

RUN apt-get install -y mail-stack-delivery

However that dockerfile generates dozens of errors when built that are along the lines of:

debconf: unable to initialize frontend: Dialog
debconf: (TERM is not set, so the dialog frontend is not usable.)
debconf: falling back to frontend: Readline
debconf: unable to initialize frontend: Readline
debconf: (Can't locate Term/ReadLine.pm in @INC (@INC contains: /etc/perl /usr/local/lib/perl/5.14.2 /usr/local/share/perl/5.14.2 /usr/lib/perl5 /usr/share/perl5 /usr/lib/perl/5.14 /usr/share/perl/5.14 /usr/local/lib/site_perl .) at /usr/share/perl5/Debconf/FrontEnd/Readline.pm line 7, <> line 11.)
debconf: falling back to frontend: Teletype
dpkg-preconfigure: unable to re-open stdin:

From what I understand I just simply can't respond to the dialogs, but is there some way that I can pass a parameter to answer each question in advance? I know that it's just changing some configurations, so I could do it after the fact, but presumably it's better to let the install scripts do it so everything gets set properly.

Body:
The reason why ENV DEBIAN_FRONTEND=noninteractive (or the legacy syntax ENV DEBIAN_FRONTEND noninteractive) sometimes works and sometimes does not has to do with the usage of sudo. By default sudo ignores the environment of the current user and uses a clean one. This can be controlled via the sudo --preserve-env flag. Obviously adding this to every sudo invocation is cumbersome, but it is easy to make the entire system for every user non-interactive by adding the environment variable to the /etc/environment file of the operating system.

RUN set -a \
 && eval "$(sudo tee --append /etc/environment <<<'DEBIAN_FRONTEND=noninteractive')" \
 && set +a \
 && sudo apt-get update \
 && sudo apt-get install mail-stack-delivery

Quickly dissecting the important snippet in isolation:

# export every variable that follows
set -a

# appends the given string to the `/etc/environment` file as root
# tee prints its input to standard out
# eval interprets the output of tee
eval "$(sudo tee --append /etc/environment <<<'DEBIAN_FRONTEND=noninteractive')"

# stop exporting everything
set +a

It was mentioned before the DEBIAN_FRONTEND=noninteractive should not be set in such a global fashion. This depends on what the intend of your image is. If it is meant for automation and not for humans then it is totally fine to set it globally.


问:
How can I console log my sum from the function below?
I have been trying to display the sum with console.log, it seems not to be working.
Can anyone assist?

```<code>var result = document.getElementById('result');
var firstNum = document.getElementById('number1');
var secondNum = document.getElementById('number2');

firstNum.addEventListener('keyup', sum);
secondNum.addEventListener('keyup', sum);

function sum(e){

    var mySum = firstNum + secondNum;
    console.log(mySum);
}
</code>```

答:
Assuming that firstNum and secondNum are input fields you would need to get the value of these inputs. Input values are string so you also would need to cast the values to numbers.

```<code>var result = document.getElementById('result');
var firstNum = document.getElementById('number1');
var secondNum = document.getElementById('number2');

firstNum.addEventListener('keyup', sum);
secondNum.addEventListener('keyup', sum);

function sum(e){

    var mySum = Number(firstNum.value) + Number(secondNum.value);
    console.log(mySum);
}
</code>```

Body:
I have been trying to display the sum with console.log, it seems not to be working.
Can anyone assist?

var result = document.getElementById('result');
var firstNum = document.getElementById('number1');
var secondNum = document.getElementById('number2');

firstNum.addEventListener('keyup', sum);
secondNum.addEventListener('keyup', sum);

function sum(e){

    var mySum = firstNum + secondNum;
    console.log(mySum);
}

Body:
Assuming that firstNum and secondNum are input fields you would need to get the value of these inputs. Input values are string so you also would need to cast the values to numbers.

var result = document.getElementById('result');
var firstNum = document.getElementById('number1');
var secondNum = document.getElementById('number2');

firstNum.addEventListener('keyup', sum);
secondNum.addEventListener('keyup', sum);

function sum(e){

    var mySum = Number(firstNum.value) + Number(secondNum.value);
    console.log(mySum);
}


问:
Check if two hours are between a time range
I allow myself to ask my question here, because after several hours of trying to make my code work, it still does not work!
So I would simply like to check if two times (For example 8:00 and 10:00) are included between a time range (For example between 8:00 and 9:00). I have already tried several combinations, it seems to work from time to time, but when I check if 9:00 and 10:00 is between 8:00 and 9:00, it returns that the time is not included in the time slot when it is supposed to be!
Here is my code for the moment: (all data has been transformed into strtotime())

```<code>if ((($hdebut >= $ihdebutcours) && ($hdebut <= $ihfincours)) && (($hfin >= $ihdebutcours) && ($hfin >= $ihfincours))) {
    $f++;
}
</code>```

For example :

$hdebut = 9:00

$hfin = 11:15

$ihdebutcours = 9:00

$ihfincours = 10:00

Thank you very much to the people who will help me, it will help me enormously to continue my project, and sorry for my bad English! Good day to you !

答:
Try PHP's DateTime...

```<code><?php

$hdebut = '9:00';
$hfin = '11:15';
$ihdebutcours = '9:00';
$ihfincours = '10:00';

$hdebutDT = new DateTime($hdebut);
$hfinDT = new DateTime($hfin);
$ihdebutcoursDT = new DateTime($ihdebutcours );
$ihfincoursDT = new DateTime($ihfincours);

if ((($hdebutDT >= $ihdebutcoursDT) && ($hdebutDT <= $ihfincoursDT)) && (($hfinDT >= $ihdebutcoursDT) && ($hfinDT >= $ihfincoursDT))) {
    $f++;
}
</code>```

You could even shorten all this by using DateTime::diff also perhaps.

Body:
I allow myself to ask my question here, because after several hours of trying to make my code work, it still does not work!
So I would simply like to check if two times (For example 8:00 and 10:00) are included between a time range (For example between 8:00 and 9:00). I have already tried several combinations, it seems to work from time to time, but when I check if 9:00 and 10:00 is between 8:00 and 9:00, it returns that the time is not included in the time slot when it is supposed to be!
Here is my code for the moment: (all data has been transformed into strtotime())

if ((($hdebut >= $ihdebutcours) && ($hdebut <= $ihfincours)) && (($hfin >= $ihdebutcours) && ($hfin >= $ihfincours))) {
    $f++;
}

For example :

$hdebut = 9:00

$hfin = 11:15

$ihdebutcours = 9:00

$ihfincours = 10:00

Thank you very much to the people who will help me, it will help me enormously to continue my project, and sorry for my bad English! Good day to you !

Body:
Try PHP's DateTime...

<?php

$hdebut = '9:00';
$hfin = '11:15';
$ihdebutcours = '9:00';
$ihfincours = '10:00';

$hdebutDT = new DateTime($hdebut);
$hfinDT = new DateTime($hfin);
$ihdebutcoursDT = new DateTime($ihdebutcours );
$ihfincoursDT = new DateTime($ihfincours);

if ((($hdebutDT >= $ihdebutcoursDT) && ($hdebutDT <= $ihfincoursDT)) && (($hfinDT >= $ihdebutcoursDT) && ($hfinDT >= $ihfincoursDT))) {
    $f++;
}

You could even shorten all this by using DateTime::diff also perhaps.


答:
Repository implementation is usually full of calls to ORM API. There is nothing to unit test here. You should write an integration test instead. Use in memory database like SQLite. Read this or this. This way you will cover your mappings, criteria, HQL etc. I know that you are using EF but I think that principle is the same as NHibernate.

Regarding mocking _db. There is a very good guideline: Don't mock types you don't own.

Title: How to unit test repository method


问:
Why can't I remove an object from a class?
I tried to remove the banana from the method remove_by_value, but it was unable to remove.

```<code>class LinkedList:
    def __init__(self):
        self.head = None
    def insert_at_end(self, data):
        if self.head is None:
            self.head = Node(data, None)
            return

        itr = self.head
        while itr.next:
            itr = itr.next
        itr.next = Node(data, None)

    def insert_values(self, data_list):
        self.head = None
        for data in data_list:
            self.insert_at_end(data)

    def remove_by_value(self,data):
        itr = self.head
        if itr is None:
            return

        if itr.data == data:
            itr.next = itr.next
            return

        while itr:
            if itr.next.data == data:
                itr.next = itr.next.next
                break
            itr = itr.next

if __name__ == '__main__':
    ll = LinkedList()
    ll.insert_values(["banana","mango","grapes","orange"])
    ll.print() # from method to show all object.
    ll.remove_by_value2("banana")
    ll.print()
</code>```

output:

banana=>mango=>grapes=>orange=>

banana=>mango=>grapes=>orange=>

答:
please look here at the part of the remove node:
https://www.tutorialspoint.com/python_data_structure/python_linked_lists.htm

this is how you suppose to implement a linked list in python :)
let me know if you have more questions about it

Body:
I tried to remove the banana from the method remove_by_value, but it was unable to remove.

class LinkedList:
    def __init__(self):
        self.head = None
    def insert_at_end(self, data):
        if self.head is None:
            self.head = Node(data, None)
            return

        itr = self.head
        while itr.next:
            itr = itr.next
        itr.next = Node(data, None)

    def insert_values(self, data_list):
        self.head = None
        for data in data_list:
            self.insert_at_end(data)

    def remove_by_value(self,data):
        itr = self.head
        if itr is None:
            return

        if itr.data == data:
            itr.next = itr.next
            return

        while itr:
            if itr.next.data == data:
                itr.next = itr.next.next
                break
            itr = itr.next

if __name__ == '__main__':
    ll = LinkedList()
    ll.insert_values(["banana","mango","grapes","orange"])
    ll.print() # from method to show all object.
    ll.remove_by_value2("banana")
    ll.print()

output:

banana=>mango=>grapes=>orange=>

banana=>mango=>grapes=>orange=>


问:
How to Validate InputQuery user input before the user clicks OK?
In a 32-bit VCL Application in Windows 10 in Delphi 11 Alexandria, I show an INPUT DIALOG to the user:

```<code>  var aNewFolderName: string := 'New Project Folder';
  if Vcl.Dialogs.InputQuery('New Project Folder', 'Enter the name of the new Project Folder:', aNewFolderName) then
  begin
    // Todo: Create the folder if everything went OK, ELSE REPEAT the input action :-(
  end;
</code>```

Is there a way to VALIDATE the user's input BEFORE he clicks the OK button? (E.g., checking for not allowed characters, existing folder, etc.). Just repeating the whole input action in the case of invalid input AFTER the user clicked OK is not very smart and efficient:

```<code>  var aNewFolderName: string := 'New Project Folder';
  var InputIsValid: Boolean;
  repeat
    if Vcl.Dialogs.InputQuery('New Project Folder', 'Enter the name of the new Project Folder:', aNewFolderName) then
    begin
      InputIsValid := CheckInput(aNewFolderName);
      if InputIsValid then CreateTheFolder(aNewFolderName);
    end
    else
      BREAK;
  until InputIsValid;
</code>```

Also, with this method, there is no feedback for the user about the specific cause of any invalid input.

答:
Although it is possible to solve this problem by using repeated dialogs, I don't think that is a particularly elegant solution from a UX perspective.

I'd rather make my own dialog and do something like this:

procedure TForm1.btnSetPasswordClick(Sender: TObject);
begin
  var psw := '';
  if SuperInput(
    Self,
    'Frog Simulator',
    'Please enter the new frog password:',
    psw,
    function(const Text: string; out AErrorMessage: string): Boolean
    begin
      if Text.Length < 8 then
      begin
        AErrorMessage := 'The password''s length must be at least 8 characters.';
        Exit(False);
      end;
      if not StrHasChrOfType(Text, TCharacter.IsLetter) then
      begin
        AErrorMessage := 'The password must contain at least one letter.';
        Exit(False);
      end;
      if not StrHasChrOfType(Text, TCharacter.IsDigit) then
      begin
        AErrorMessage := 'The password must contain at least one digit.';
        Exit(False);
      end;
      if not StrHasChrOfType(Text, TCharacter.IsPunctuation) then
      begin
        AErrorMessage := 'The password must contain at least one punctuation character.';
        Exit(False);
      end;
      Result := True;
    end)
  then
    lblNewPassword.Caption := psw;
end;
```
<p><img src="https://i.stack.imgur.com/C5fc8.gif" alt="Screen recording of this "Super Input Dialog" in action, validating my passoword at real time." /></p>
<p>Here's the code:</p>
<pre class="lang-pascal prettyprint-override"><code>unit SuperInputDlg;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ExtCtrls;

type
  TValidator = reference to function(const Text: string;
    out AErrorMessage: string): Boolean;
  TSuperInputForm = class(TForm)
    lblCaption: TLabel;
    shClient: TShape;
    Edit: TEdit;
    pbErrorIcon: TPaintBox;
    lblError: TLabel;
    Validator: TTimer;
    btnOK: TButton;
    btnCancel: TButton;
    procedure FormCreate(Sender: TObject);
    procedure pbErrorIconPaint(Sender: TObject);
    procedure EditChange(Sender: TObject);
    procedure ValidatorTimer(Sender: TObject);
    procedure btnOKClick(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    FErrorIcon: HICON;
    FLIWSD: Boolean;
    FValidator: TValidator;
    function DoValidate: Boolean;
  public
  end;

function SuperInput(AOwnerForm: TCustomForm; const ACaption, AMainInstruction: string;
  var AText: string; AValidator: TValidator = nil): Boolean;

implementation

{$R *.dfm}

function Scale(X: Integer): Integer;
begin
  Result := MulDiv(X, Screen.PixelsPerInch, 96);
end;

procedure TSuperInputForm.btnOKClick(Sender: TObject);
begin
  if DoValidate then
    ModalResult := mrOK;
end;

function TSuperInputForm.DoValidate: Boolean;
begin

  var LErrMsg: string;
  var LIsValid := not Assigned(FValidator) or FValidator(Edit.Text, LErrMsg);

  btnOK.Enabled := LIsValid;

  if not LIsValid then
    lblError.Caption := LErrMsg;

  pbErrorIcon.Visible := not LIsValid;
  lblError.Visible := not LIsValid;

  Result := LIsValid;

end;

procedure TSuperInputForm.EditChange(Sender: TObject);
begin
  Validator.Enabled := False;
  Validator.Enabled := True;
end;

procedure TSuperInputForm.FormCreate(Sender: TObject);
var
  ComCtl: HMODULE;
  LoadIconWithScaleDown: function(hinst: HINST; pszName: LPCWSTR; cx: Integer;
    cy: Integer; var phico: HICON): HResult; stdcall;
begin

  ComCtl := LoadLibrary('ComCtl32.dll');
  if ComCtl <> 0 then
  begin
    try
      LoadIconWithScaleDown := GetProcAddress(ComCtl, 'LoadIconWithScaleDown');
      if Assigned(LoadIconWithScaleDown) then
        LoadIconWithScaleDown(0, IDI_ERROR, Scale(16), Scale(16), FErrorIcon);
    finally
      FreeLibrary(ComCtl);
    end;
  end;

  FLIWSD := FErrorIcon <> 0;
  if FErrorIcon = 0 then
    FErrorIcon := LoadIcon(0, IDI_ERROR);

end;

procedure TSuperInputForm.FormDestroy(Sender: TObject);
begin
  if FLIWSD then
    DestroyIcon(FErrorIcon);
end;

procedure TSuperInputForm.pbErrorIconPaint(Sender: TObject);
begin
  if FErrorIcon <> 0 then
    DrawIconEx(pbErrorIcon.Canvas.Handle, 0, 0, FErrorIcon,
      Scale(16), Scale(16), 0, 0, DI_NORMAL);
end;

procedure TSuperInputForm.ValidatorTimer(Sender: TObject);
begin
  DoValidate;
end;

function SuperInput(AOwnerForm: TCustomForm; const ACaption, AMainInstruction: string;
  var AText: string; AValidator: TValidator = nil): Boolean;
begin
  var LFrm := TSuperInputForm.Create(AOwnerForm);
  try
    LFrm.Caption := ACaption;
    LFrm.lblCaption.Caption := AMainInstruction;
    LFrm.Edit.Text := AText;
    LFrm.FValidator := AValidator;
    LFrm.DoValidate;
    Result := LFrm.ShowModal = mrOk;
    if Result then
      AText := LFrm.Edit.Text;
  finally
    LFrm.Free;
  end;
end;

end.
</code>```

and DFM:

object SuperInputForm: TSuperInputForm
  Left = 0
  Top = 0
  Caption = 'Input Box'
  ClientHeight = 166
  ClientWidth = 469
  Color = clBtnFace
  Constraints.MaxHeight = 204
  Constraints.MinHeight = 204
  Constraints.MinWidth = 400
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -12
  Font.Name = 'Segoe UI'
  Font.Style = []
  OldCreateOrder = False
  Position = poOwnerFormCenter
  OnCreate = FormCreate
  OnDestroy = FormDestroy
  DesignSize = (
    469
    166)
  PixelsPerInch = 96
  TextHeight = 15
  object shClient: TShape
    Left = 0
    Top = 0
    Width = 468
    Height = 127
    Anchors = [akLeft, akTop, akRight, akBottom]
    Pen.Style = psClear
    ExplicitWidth = 499
    ExplicitHeight = 175
  end
  object lblCaption: TLabel
    Left = 24
    Top = 24
    Width = 65
    Height = 21
    Caption = 'Input Box'
    Font.Charset = DEFAULT_CHARSET
    Font.Color = 10040064
    Font.Height = -16
    Font.Name = 'Segoe UI'
    Font.Style = []
    ParentFont = False
  end
  object pbErrorIcon: TPaintBox
    Left = 24
    Top = 88
    Width = 16
    Height = 16
    OnPaint = pbErrorIconPaint
  end
  object lblError: TLabel
    Left = 50
    Top = 88
    Width = 3
    Height = 15
  end
  object Edit: TEdit
    Left = 24
    Top = 51
    Width = 418
    Height = 23
    Anchors = [akLeft, akTop, akRight]
    TabOrder = 0
    OnChange = EditChange
    ExplicitWidth = 449
  end
  object btnOK: TButton
    Left = 286
    Top = 133
    Width = 75
    Height = 25
    Anchors = [akRight, akBottom]
    Caption = 'OK'
    Default = True
    TabOrder = 1
    OnClick = btnOKClick
    ExplicitLeft = 317
    ExplicitTop = 181
  end
  object btnCancel: TButton
    Left = 367
    Top = 133
    Width = 75
    Height = 25
    Anchors = [akRight, akBottom]
    Cancel = True
    Caption = 'Cancel'
    ModalResult = 2
    TabOrder = 2
    ExplicitLeft = 398
    ExplicitTop = 181
  end
  object Validator: TTimer
    OnTimer = ValidatorTimer
    Left = 136
    Top = 120
  end
end
```
<p>Please note that this is only a sketch I did in ten minutes -- in a real app, you'd spend a bit more time on this one.</p>
<p><strong>Appendix 1</strong></p>
<pre class="lang-pascal prettyprint-override"><code>type
  TChrTestFcn = function(C: Char): Boolean;

function StrHasChrOfType(const AText: string; ATestFcn: TChrTestFcn): Boolean;
begin
  for var S in AText do
    if ATestFcn(S) then
      Exit(True);
  Result := False;
end;
</code>```

Body:
In a 32-bit VCL Application in Windows 10 in Delphi 11 Alexandria, I show an INPUT DIALOG to the user:

  var aNewFolderName: string := 'New Project Folder';
  if Vcl.Dialogs.InputQuery('New Project Folder', 'Enter the name of the new Project Folder:', aNewFolderName) then
  begin
    // Todo: Create the folder if everything went OK, ELSE REPEAT the input action :-(
  end;

Is there a way to VALIDATE the user's input BEFORE he clicks the OK button? (E.g., checking for not allowed characters, existing folder, etc.). Just repeating the whole input action in the case of invalid input AFTER the user clicked OK is not very smart and efficient:

  var aNewFolderName: string := 'New Project Folder';
  var InputIsValid: Boolean;
  repeat
    if Vcl.Dialogs.InputQuery('New Project Folder', 'Enter the name of the new Project Folder:', aNewFolderName) then
    begin
      InputIsValid := CheckInput(aNewFolderName);
      if InputIsValid then CreateTheFolder(aNewFolderName);
    end
    else
      BREAK;
  until InputIsValid;

Also, with this method, there is no feedback for the user about the specific cause of any invalid input.

Body:
Although it is possible to solve this problem by using repeated dialogs, I don't think that is a particularly elegant solution from a UX perspective.

I'd rather make my own dialog and do something like this:

procedure TForm1.btnSetPasswordClick(Sender: TObject);
begin
  var psw := '';
  if SuperInput(
    Self,
    'Frog Simulator',
    'Please enter the new frog password:',
    psw,
    function(const Text: string; out AErrorMessage: string): Boolean
    begin
      if Text.Length < 8 then
      begin
        AErrorMessage := 'The password''s length must be at least 8 characters.';
        Exit(False);
      end;
      if not StrHasChrOfType(Text, TCharacter.IsLetter) then
      begin
        AErrorMessage := 'The password must contain at least one letter.';
        Exit(False);
      end;
      if not StrHasChrOfType(Text, TCharacter.IsDigit) then
      begin
        AErrorMessage := 'The password must contain at least one digit.';
        Exit(False);
      end;
      if not StrHasChrOfType(Text, TCharacter.IsPunctuation) then
      begin
        AErrorMessage := 'The password must contain at least one punctuation character.';
        Exit(False);
      end;
      Result := True;
    end)
  then
    lblNewPassword.Caption := psw;
end;

Here's the code:

unit SuperInputDlg;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ExtCtrls;

type
  TValidator = reference to function(const Text: string;
    out AErrorMessage: string): Boolean;
  TSuperInputForm = class(TForm)
    lblCaption: TLabel;
    shClient: TShape;
    Edit: TEdit;
    pbErrorIcon: TPaintBox;
    lblError: TLabel;
    Validator: TTimer;
    btnOK: TButton;
    btnCancel: TButton;
    procedure FormCreate(Sender: TObject);
    procedure pbErrorIconPaint(Sender: TObject);
    procedure EditChange(Sender: TObject);
    procedure ValidatorTimer(Sender: TObject);
    procedure btnOKClick(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    FErrorIcon: HICON;
    FLIWSD: Boolean;
    FValidator: TValidator;
    function DoValidate: Boolean;
  public
  end;

function SuperInput(AOwnerForm: TCustomForm; const ACaption, AMainInstruction: string;
  var AText: string; AValidator: TValidator = nil): Boolean;

implementation

{$R *.dfm}

function Scale(X: Integer): Integer;
begin
  Result := MulDiv(X, Screen.PixelsPerInch, 96);
end;

procedure TSuperInputForm.btnOKClick(Sender: TObject);
begin
  if DoValidate then
    ModalResult := mrOK;
end;

function TSuperInputForm.DoValidate: Boolean;
begin

  var LErrMsg: string;
  var LIsValid := not Assigned(FValidator) or FValidator(Edit.Text, LErrMsg);

  btnOK.Enabled := LIsValid;

  if not LIsValid then
    lblError.Caption := LErrMsg;

  pbErrorIcon.Visible := not LIsValid;
  lblError.Visible := not LIsValid;

  Result := LIsValid;

end;

procedure TSuperInputForm.EditChange(Sender: TObject);
begin
  Validator.Enabled := False;
  Validator.Enabled := True;
end;

procedure TSuperInputForm.FormCreate(Sender: TObject);
var
  ComCtl: HMODULE;
  LoadIconWithScaleDown: function(hinst: HINST; pszName: LPCWSTR; cx: Integer;
    cy: Integer; var phico: HICON): HResult; stdcall;
begin

  ComCtl := LoadLibrary('ComCtl32.dll');
  if ComCtl <> 0 then
  begin
    try
      LoadIconWithScaleDown := GetProcAddress(ComCtl, 'LoadIconWithScaleDown');
      if Assigned(LoadIconWithScaleDown) then
        LoadIconWithScaleDown(0, IDI_ERROR, Scale(16), Scale(16), FErrorIcon);
    finally
      FreeLibrary(ComCtl);
    end;
  end;

  FLIWSD := FErrorIcon <> 0;
  if FErrorIcon = 0 then
    FErrorIcon := LoadIcon(0, IDI_ERROR);

end;

procedure TSuperInputForm.FormDestroy(Sender: TObject);
begin
  if FLIWSD then
    DestroyIcon(FErrorIcon);
end;

procedure TSuperInputForm.pbErrorIconPaint(Sender: TObject);
begin
  if FErrorIcon <> 0 then
    DrawIconEx(pbErrorIcon.Canvas.Handle, 0, 0, FErrorIcon,
      Scale(16), Scale(16), 0, 0, DI_NORMAL);
end;

procedure TSuperInputForm.ValidatorTimer(Sender: TObject);
begin
  DoValidate;
end;

function SuperInput(AOwnerForm: TCustomForm; const ACaption, AMainInstruction: string;
  var AText: string; AValidator: TValidator = nil): Boolean;
begin
  var LFrm := TSuperInputForm.Create(AOwnerForm);
  try
    LFrm.Caption := ACaption;
    LFrm.lblCaption.Caption := AMainInstruction;
    LFrm.Edit.Text := AText;
    LFrm.FValidator := AValidator;
    LFrm.DoValidate;
    Result := LFrm.ShowModal = mrOk;
    if Result then
      AText := LFrm.Edit.Text;
  finally
    LFrm.Free;
  end;
end;

end.

and DFM:

object SuperInputForm: TSuperInputForm
  Left = 0
  Top = 0
  Caption = 'Input Box'
  ClientHeight = 166
  ClientWidth = 469
  Color = clBtnFace
  Constraints.MaxHeight = 204
  Constraints.MinHeight = 204
  Constraints.MinWidth = 400
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -12
  Font.Name = 'Segoe UI'
  Font.Style = []
  OldCreateOrder = False
  Position = poOwnerFormCenter
  OnCreate = FormCreate
  OnDestroy = FormDestroy
  DesignSize = (
    469
    166)
  PixelsPerInch = 96
  TextHeight = 15
  object shClient: TShape
    Left = 0
    Top = 0
    Width = 468
    Height = 127
    Anchors = [akLeft, akTop, akRight, akBottom]
    Pen.Style = psClear
    ExplicitWidth = 499
    ExplicitHeight = 175
  end
  object lblCaption: TLabel
    Left = 24
    Top = 24
    Width = 65
    Height = 21
    Caption = 'Input Box'
    Font.Charset = DEFAULT_CHARSET
    Font.Color = 10040064
    Font.Height = -16
    Font.Name = 'Segoe UI'
    Font.Style = []
    ParentFont = False
  end
  object pbErrorIcon: TPaintBox
    Left = 24
    Top = 88
    Width = 16
    Height = 16
    OnPaint = pbErrorIconPaint
  end
  object lblError: TLabel
    Left = 50
    Top = 88
    Width = 3
    Height = 15
  end
  object Edit: TEdit
    Left = 24
    Top = 51
    Width = 418
    Height = 23
    Anchors = [akLeft, akTop, akRight]
    TabOrder = 0
    OnChange = EditChange
    ExplicitWidth = 449
  end
  object btnOK: TButton
    Left = 286
    Top = 133
    Width = 75
    Height = 25
    Anchors = [akRight, akBottom]
    Caption = 'OK'
    Default = True
    TabOrder = 1
    OnClick = btnOKClick
    ExplicitLeft = 317
    ExplicitTop = 181
  end
  object btnCancel: TButton
    Left = 367
    Top = 133
    Width = 75
    Height = 25
    Anchors = [akRight, akBottom]
    Cancel = True
    Caption = 'Cancel'
    ModalResult = 2
    TabOrder = 2
    ExplicitLeft = 398
    ExplicitTop = 181
  end
  object Validator: TTimer
    OnTimer = ValidatorTimer
    Left = 136
    Top = 120
  end
end

Please note that this is only a sketch I did in ten minutes -- in a real app, you'd spend a bit more time on this one.

Appendix 1

type
  TChrTestFcn = function(C: Char): Boolean;

function StrHasChrOfType(const AText: string; ATestFcn: TChrTestFcn): Boolean;
begin
  for var S in AText do
    if ATestFcn(S) then
      Exit(True);
  Result := False;
end;


问:
How can I set button positions from preference screen?
Hello StackOverflow users!

I'm trying to do someting complicated (for a noob like me XD) and I have some questions.

How can I set my main screen buttons position form a preference screen? Like, if I have 2 buttons to inverse their position...

I tried to do with the code below in kotlin (please don't judge me, already told u I'm noob af) but I wanna have an idea how to make this wotk. XD

```<code>         findPreference<Preference>("buttonpositions")!!.onPreferenceChangeListener = Preference.OnPreferenceChangeListener { preference: Preference, _: Any? ->
                val checked = (preference as CheckBoxPreference).isChecked
                if(!checked) {
                    val myBtn = R.id.cleanBtn as Button
                    myBtn.setPadding(0, 100, 0, 0)
                }
                true
            }
</code>```

and the buttons is something like this:

```<code>        <com.google.android.material.button.MaterialButton
            style="@style/Widget.Material3.Button.UnelevatedButton"
            android:id="@+id/cleanBtn"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:layout_columnWeight="1"
            android:minWidth="0dp"
            app:layout_rowWeight="1"
            android:tooltipText="@string/tooltip_clean_button"
            app:iconGravity="top"
            app:icon="@drawable/ic_broom"
            app:iconTint="@android:color/system_accent1_400"
            android:textColor="@android:color/system_accent1_400"
            android:text="@string/clean"/>
        <com.google.android.material.button.MaterialButton
            style="@style/Widget.Material3.Button.UnelevatedButton"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:layout_columnWeight="1"
            app:layout_rowWeight="1"
            android:id="@+id/analyzeBtn"
            app:iconGravity="top"
            app:icon="@drawable/ic_search"
            android:tooltipText="@string/analyze_tooltip"
            app:iconTint="@android:color/system_accent1_700"
            android:textColor="@android:color/system_accent1_700"
            android:text="@string/analyze"
            android:minWidth="0dp"
            app:backgroundTint="@android:color/transparent"/>
</code>```

First. I'm preety sure my "code" isn't right composed + idk if I need to add someting to buttons itself.

Thanks for your time :D

答:
Why your code won't work:

R.id.cleanBtn is an Int ID, not a button. Trying to cast an Int into a Button will crash the app. (Casting is not the same thing as converting--it's promising the compiler that something is also something else already.) IDs are used to search existing view hierarchies for the actual view you want by using something like rootView.findViewById<Button>(R.id.cleanBtn), but this strategy isn't practical here since you don't have direct access to the view hierarchy.

Trying to change the button from the preference listener would only work when you change it. If the user rotates the screen or the exits the app and comes back, the main screen's view will be recreated back in the original position.

The right way to do this is not on the settings screen, but on the main screen. Preferences that are set on a preference screen by default are saved to the "default" shared preferences, and they are saved persistently, so they can be read from anywhere else in your app.

What I would do is read the current value of the preference in the onResume() function of the activity or fragment of your main screen. onResume() will get called every time that screen reappears, so it gives it an opportunity to check and apply the setting the first time the view appears and every time you return from the preferences screen, where the value may have changed.

```<code>//in main screen class

private var isButtonPositionFlipped = false

// Only need this function if in a Fragment
// Need to reset the property in case Fragment has recreated its view
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    //...
    isButtonPositionFlipped = false
}

override fun onResume() {
    super.onResume()
    val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this)
        // use requireContext() instead of this if we're in a Fragment class
    val shouldFlipButtonPosition = sharedPreferences.getBoolean("buttonpositions", false)

    if (isButtonPositionFlipped != shouldFlipButtonPosition) {
        isButtonPositionFlipped = shouldFlipButtonPosition

        val cleanBtn = findViewById<Button>(R.id.cleanBtn)
        val analyzeBtn = findViewById<Button>(R.id.analyzeBtn)
            // use requireView().findViewByID if in a Fragment class

        if (isButtonPositionFlipped) {
            // swap the buttons here
        } else {
            // swap them back here
        }
    }
}
</code>```

As for how to swap them, that depends on the type of layout they're in. If they're in a ConstraintLayout, I think it will be pretty complicated, but I haven't tried it before. You might try putting each of the two buttons inside FrameLayouts. Then you could get the FrameLayout views and swap the view children between them.

Edit: Actually, I think it would be easier in this case to just make your buttons more generically named. Instead of swapping them, just change their text and click listeners to the opposites.

Body:
Hello StackOverflow users!

I'm trying to do someting complicated (for a noob like me XD) and I have some questions.

How can I set my main screen buttons position form a preference screen? Like, if I have 2 buttons to inverse their position...

I tried to do with the code below in kotlin (please don't judge me, already told u I'm noob af) but I wanna have an idea how to make this wotk. XD

         findPreference<Preference>("buttonpositions")!!.onPreferenceChangeListener = Preference.OnPreferenceChangeListener { preference: Preference, _: Any? ->
                val checked = (preference as CheckBoxPreference).isChecked
                if(!checked) {
                    val myBtn = R.id.cleanBtn as Button
                    myBtn.setPadding(0, 100, 0, 0)
                }
                true
            }

and the buttons is something like this:

        <com.google.android.material.button.MaterialButton
            style="@style/Widget.Material3.Button.UnelevatedButton"
            android:id="@+id/cleanBtn"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:layout_columnWeight="1"
            android:minWidth="0dp"
            app:layout_rowWeight="1"
            android:tooltipText="@string/tooltip_clean_button"
            app:iconGravity="top"
            app:icon="@drawable/ic_broom"
            app:iconTint="@android:color/system_accent1_400"
            android:textColor="@android:color/system_accent1_400"
            android:text="@string/clean"/>
        <com.google.android.material.button.MaterialButton
            style="@style/Widget.Material3.Button.UnelevatedButton"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:layout_columnWeight="1"
            app:layout_rowWeight="1"
            android:id="@+id/analyzeBtn"
            app:iconGravity="top"
            app:icon="@drawable/ic_search"
            android:tooltipText="@string/analyze_tooltip"
            app:iconTint="@android:color/system_accent1_700"
            android:textColor="@android:color/system_accent1_700"
            android:text="@string/analyze"
            android:minWidth="0dp"
            app:backgroundTint="@android:color/transparent"/>

First. I'm preety sure my "code" isn't right composed + idk if I need to add someting to buttons itself.

Thanks for your time :D

Body:
Why your code won't work:

R.id.cleanBtn is an Int ID, not a button. Trying to cast an Int into a Button will crash the app. (Casting is not the same thing as converting--it's promising the compiler that something is also something else already.) IDs are used to search existing view hierarchies for the actual view you want by using something like rootView.findViewById<Button>(R.id.cleanBtn), but this strategy isn't practical here since you don't have direct access to the view hierarchy.

Trying to change the button from the preference listener would only work when you change it. If the user rotates the screen or the exits the app and comes back, the main screen's view will be recreated back in the original position.

The right way to do this is not on the settings screen, but on the main screen. Preferences that are set on a preference screen by default are saved to the "default" shared preferences, and they are saved persistently, so they can be read from anywhere else in your app.

What I would do is read the current value of the preference in the onResume() function of the activity or fragment of your main screen. onResume() will get called every time that screen reappears, so it gives it an opportunity to check and apply the setting the first time the view appears and every time you return from the preferences screen, where the value may have changed.

//in main screen class

private var isButtonPositionFlipped = false

// Only need this function if in a Fragment
// Need to reset the property in case Fragment has recreated its view
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    //...
    isButtonPositionFlipped = false
}

override fun onResume() {
    super.onResume()
    val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this)
        // use requireContext() instead of this if we're in a Fragment class
    val shouldFlipButtonPosition = sharedPreferences.getBoolean("buttonpositions", false)

    if (isButtonPositionFlipped != shouldFlipButtonPosition) {
        isButtonPositionFlipped = shouldFlipButtonPosition

        val cleanBtn = findViewById<Button>(R.id.cleanBtn)
        val analyzeBtn = findViewById<Button>(R.id.analyzeBtn)
            // use requireView().findViewByID if in a Fragment class

        if (isButtonPositionFlipped) {
            // swap the buttons here
        } else {
            // swap them back here
        }
    }
}

As for how to swap them, that depends on the type of layout they're in. If they're in a ConstraintLayout, I think it will be pretty complicated, but I haven't tried it before. You might try putting each of the two buttons inside FrameLayouts. Then you could get the FrameLayout views and swap the view children between them.

Edit: Actually, I think it would be easier in this case to just make your buttons more generically named. Instead of swapping them, just change their text and click listeners to the opposites.


问:
Property Names of MultiDimensional array
I am new to JS. Programmatically I need to find propery names of multidimensional array. Expected Output -  ["name", "position", "salary", etc.]

When I am using map I am getting values of "name" data.map(item => item.name).

```<code>var data = [
        {
            "name": "Tiger Nixon",
            "position": "System Architect",
            "salary": "320800",
            "start_date": "2011\/04\/25",
            "office": "Edinburgh",
            "rating": "5421"
        },
        {
            "name": "Garrett Winters",
            "position": "Accountant",
            "salary": "170750",
            "start_date": "2011\/07\/25",
            "office": "Tokyo",
            "rating": "8422"
        },
        {
            "name": "Ashton Cox",
            "position": "Junior Technical Author",
            "salary": "86000",
            "start_date": "2009\/01\/12",
            "office": "San Francisco",
            "rating": "1562"
        },
        {
            "name": "Cedric Kelly",
            "position": "Senior Javascript Developer",
            "salary": "433060",
            "start_date": "2012\/03\/29",
            "office": "Edinburgh",
            "rating": "6224"
        }]
</code>```

答:
Using Object#keys:

const getPropertyNames = (arr = []) => arr.length > 0 ? Object.keys(arr[0]) : [];

const data = [ { "name": "Tiger Nixon", "position": "System Architect", "salary": "320800", "start_date": "2011\/04\/25", "office": "Edinburgh", "rating": "5421" }, { "name": "Garrett Winters", "position": "Accountant", "salary": "170750", "start_date": "2011\/07\/25", "office": "Tokyo", "rating": "8422" }, { "name": "Ashton Cox", "position": "Junior Technical Author", "salary": "86000", "start_date": "2009\/01\/12", "office": "San Francisco", "rating": "1562" }, { "name": "Cedric Kelly", "position": "Senior Javascript Developer", "salary": "433060", "start_date": "2012\/03\/29", "office": "Edinburgh", "rating": "6224" } ];
console.log( getPropertyNames(data) );```

Body:
I am new to JS. Programmatically I need to find propery names of multidimensional array. Expected Output -  ["name", "position", "salary", etc.]

When I am using map I am getting values of "name" data.map(item => item.name).

var data = [
        {
            "name": "Tiger Nixon",
            "position": "System Architect",
            "salary": "320800",
            "start_date": "2011\/04\/25",
            "office": "Edinburgh",
            "rating": "5421"
        },
        {
            "name": "Garrett Winters",
            "position": "Accountant",
            "salary": "170750",
            "start_date": "2011\/07\/25",
            "office": "Tokyo",
            "rating": "8422"
        },
        {
            "name": "Ashton Cox",
            "position": "Junior Technical Author",
            "salary": "86000",
            "start_date": "2009\/01\/12",
            "office": "San Francisco",
            "rating": "1562"
        },
        {
            "name": "Cedric Kelly",
            "position": "Senior Javascript Developer",
            "salary": "433060",
            "start_date": "2012\/03\/29",
            "office": "Edinburgh",
            "rating": "6224"
        }]


问:
There should be only two results, but why is it repeated three times?
```<code>select a.m_num,a.filename,a.title,a.price,a.stock
from newboard a , cart b
where a.m_num = b.m_num and a.board_num = ANY(select board_num from cart where m_num = '82');
</code>```

The result

FIELD1
FIELD2
FIELD3
FIELD4
FIELD5

82
NO1.png
car
39000
1

82

0
0

82
NO1.png
car
39000
1

82

0
0

82
NO1.png
car
39000
1

Why is it repeating?

答:
Since inner join is working as Cartesian Product. To get distinct rows either use distinct keyword after select or use group by.

Example:

```<code>select a.m_num,a.filename,a.title,a.price,a.stock
from newboard a , cart b
where a.m_num = b.m_num
and a.board_num = ANY(select board_num from cart where m_num = '82')
 group by a.m_num,a.filename,a.title,a.price,a.stock;
</code>```

Body:
select a.m_num,a.filename,a.title,a.price,a.stock
from newboard a , cart b
where a.m_num = b.m_num and a.board_num = ANY(select board_num from cart where m_num = '82');

The result

FIELD1
FIELD2
FIELD3
FIELD4
FIELD5

82
NO1.png
car
39000
1

82

0
0

82
NO1.png
car
39000
1

82

0
0

82
NO1.png
car
39000
1

Why is it repeating?

Body:
Since inner join is working as Cartesian Product. To get distinct rows either use distinct keyword after select or use group by.

Example:

select a.m_num,a.filename,a.title,a.price,a.stock
from newboard a , cart b
where a.m_num = b.m_num
and a.board_num = ANY(select board_num from cart where m_num = '82')
 group by a.m_num,a.filename,a.title,a.price,a.stock;


问:
Garbage collection implementation in compiled languages
When implementing precise garbage collection, there is always the issue of figuring out which words on the stack are pointers and which are other kinds of data such as integers or floating point numbers. Interpreted languages typically solve this problem by making everything a pointer; compilers for some languages such as Lisp typically solve it by using tag bits to distinguish between pointers and integers.

But what about JIT compilers for languages such as Java and C# that support full unboxed machine word integers and floating-point numbers? How do they tell which of the contents of the stack and CPU registers are pointers?

答: Languages like Java and C# are specified in such a way that they do not require precise collection. An implementation might use a conservative collector, where patterns of bits that appear to look like a pointer are treated like a pointer (but might really be an integer or float). For example, the Boehm collector is a conservative collector that could be used for JIT-ed languages.


问:
Passing a list of dataframe column names to Plotly Express Treemap
I'm trying to create a a treemap in Plotly Express. If I manually enter the column names, the treemap is created. Passing a list of the same column names throws a ValueError.

Essentially I have a dataframe with column names 3,4,5,6,7,8,9,10

Because these column names will vary depending on the data, I'd like to pass these as a list to Plotly express.

Manually entering them as per below, will work

```<code>treemap_fig = px.treemap(df_split_folders, path=[px.Constant("Chart Title"), 3,4,5,6,7,8,9,10],values='count', color_discrete_sequence=px.colors.qualitative.Antique)
</code>```

but passing them as a list does not. E.g

```<code># create list of column names from dataframe
total_cols = df_split_folders.columns.values.tolist()

#pass as a list
treemap_fig = px.treemap(df_split_folders, path=[px.Constant("Chart Title"), 3,4,5,6,7,8,9,10],values='count', color_discrete_sequence=px.colors.qualitative.Antique)
</code>```

I've also tried converting the column name list to a string, but no dice.

Edit: Here is a Minimum Reproducible Example:

```<code>import pandas as pd
import plotly.express as px

# dictionary with list object in values
details = {
    'url' : ['/category', '/category', '/product', '/product'],
    'folder' : ['/games', '/playstation', '/cars', '/cycling'],
    'type' : ['adventure', 'action', 'action', 'adventure'],
}

df = pd.DataFrame(details, index = ['a', 'b', 'c', 'd'])
df['count'] = 1

treemap_fig = px.treemap(df, path=[px.Constant("Discovered / Crawled Not Indexed"), 'url', 'folder', 'type'], values='count', color_discrete_sequence=px.colors.qualitative.Antique)
treemap_fig.show()
</code>```

this code works as expected and produces a treemap, however - if I try and pass the column names as a variable, it no longer references the dataframe column names. e.g.

```<code>cols = 'url', 'folder', 'type'

treemap_fig = px.treemap(df, path=[px.Constant("Discovered / Crawled Not Indexed"), **cols**], values='count', color_discrete_sequence=px.colors.qualitative.Antique)
    treemap_fig.show()
</code>```

答:
To expand a column variable, you can use an asterisk to expand it. Please refer to the official reference for details.</p>
```<code>cols = 'url', 'folder', 'type'

treemap_fig = px.treemap(df,
                         path=[px.Constant("Discovered / Crawled Not Indexed"), *cols],
                         values='count',
                         color_discrete_sequence=px.colors.qualitative.Antique)

treemap_fig.show()
</code>```

Body:
I'm trying to create a a treemap in Plotly Express. If I manually enter the column names, the treemap is created. Passing a list of the same column names throws a ValueError.

Essentially I have a dataframe with column names 3,4,5,6,7,8,9,10

Because these column names will vary depending on the data, I'd like to pass these as a list to Plotly express.

Manually entering them as per below, will work

treemap_fig = px.treemap(df_split_folders, path=[px.Constant("Chart Title"), 3,4,5,6,7,8,9,10],values='count', color_discrete_sequence=px.colors.qualitative.Antique)

but passing them as a list does not. E.g

# create list of column names from dataframe
total_cols = df_split_folders.columns.values.tolist()

#pass as a list
treemap_fig = px.treemap(df_split_folders, path=[px.Constant("Chart Title"), 3,4,5,6,7,8,9,10],values='count', color_discrete_sequence=px.colors.qualitative.Antique)

I've also tried converting the column name list to a string, but no dice.

Edit: Here is a Minimum Reproducible Example:

import pandas as pd
import plotly.express as px

# dictionary with list object in values
details = {
    'url' : ['/category', '/category', '/product', '/product'],
    'folder' : ['/games', '/playstation', '/cars', '/cycling'],
    'type' : ['adventure', 'action', 'action', 'adventure'],
}

df = pd.DataFrame(details, index = ['a', 'b', 'c', 'd'])
df['count'] = 1

treemap_fig = px.treemap(df, path=[px.Constant("Discovered / Crawled Not Indexed"), 'url', 'folder', 'type'], values='count', color_discrete_sequence=px.colors.qualitative.Antique)
treemap_fig.show()

this code works as expected and produces a treemap, however - if I try and pass the column names as a variable, it no longer references the dataframe column names. e.g.

cols = 'url', 'folder', 'type'

treemap_fig = px.treemap(df, path=[px.Constant("Discovered / Crawled Not Indexed"), **cols**], values='count', color_discrete_sequence=px.colors.qualitative.Antique)
    treemap_fig.show()

Body:
To expand a column variable, you can use an asterisk to expand it. Please refer to the official reference for details.

cols = 'url', 'folder', 'type'

treemap_fig = px.treemap(df,
                         path=[px.Constant("Discovered / Crawled Not Indexed"), *cols],
                         values='count',
                         color_discrete_sequence=px.colors.qualitative.Antique)

treemap_fig.show()