答:
If you want to keep the content of the textarea even after the form submission use the code:</p>

```<code><?php
$theData = '';
if(isset($_POST['data'])) {

// here is assigning the content to be displayed on form submit
$theData = $_POST['data'];
$myFile = "/var/www/vhosts/domain/subdomain/index.php";
$fh = fopen($myFile, 'w');
fwrite($fh, $_POST['data']);
} else {
$myFile = "/var/www/vhosts/domain/subdomain/index.php";
$fh = fopen($myFile, 'r');
$theData = fread($fh, filesize($myFile));
}
fclose($fh);
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Untitled Document</title>
</head>

<body>
<form name="test" method="post" action="">
<textarea name="data"><?php echo $theData; ?></textarea>
<input type="submit" name="submit" value="Update File" />
</form>
</body>
</html>
</code>```

Title: How To Keep textarea content

Body:
I have a code :

<?php
    if(isset($_POST['data'])) {
        $myFile = "/var/www/vhosts/domain/subdomain/index.php";
        $fh = fopen($myFile, 'w');
        fwrite($fh, $_POST['data']);
    } else {
        $myFile = "/var/www/vhosts/domain/subdomain/index.php";
        $fh = fopen($myFile, 'r');
        $theData = fread($fh, filesize($myFile));
    }
    fclose($fh);
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

        <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
        <title>Untitled Document</title>

        <form name="test" method="post" action="">
            <textarea name="data"><?php echo $theData; ?></textarea>
            <input type="submit" name="submit" value="Update File" />
        </form>

When I click submit content of the textarea is lost.
How can I solve this?

Body:
If you want to keep the content of the textarea even after the form submission use the code:

<?php
$theData = '';
if(isset($_POST['data'])) {

// here is assigning the content to be displayed on form submit
$theData = $_POST['data'];
$myFile = "/var/www/vhosts/domain/subdomain/index.php";
$fh = fopen($myFile, 'w');
fwrite($fh, $_POST['data']);
} else {
$myFile = "/var/www/vhosts/domain/subdomain/index.php";
$fh = fopen($myFile, 'r');
$theData = fread($fh, filesize($myFile));
}
fclose($fh);
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Untitled Document</title>
</head>

<body>
<form name="test" method="post" action="">
<textarea name="data"><?php echo $theData; ?></textarea>
<input type="submit" name="submit" value="Update File" />
</form>
</body>
</html>


来源: stackexchange

问:
Python Iterating over lists in lists with map()
So my intention is to iterate over lists in lists with map, filter and lambda
e.g.:

[ [33,3,3,0] , [34,1,0,4] ]  should result in [ [33,3,3] , [34,1,4] ]

```<code>   def no_zeros(lst):
      a=map(filter(lambda x:(y==0 for y in x) ,lst),lst)
      print (list(a))
      #(says that filter is not callable)
</code>```

I know that this code won't work but i do not know what exactly i do wrong since i'm still kind of new to lambda,etc.I already tried different stuff , like moving the filter after the lambda,but that did not seem to work either . Im gratefull for any kind of tipps or help.

答:
```<code>lst = list(map(lambda k: list(filter(lambda l: l != 0, k)), lst))
</code>```

This should do the trick. You need apply a lambda on each element in the list through a filter. Be aware nested lambdas are ugly.

ContentLicense: CC BY-SA 3.0

Body:
So my intention is to iterate over lists in lists with map, filter and lambda
e.g.:

[ [33,3,3,0] , [34,1,0,4] ]  should result in [ [33,3,3] , [34,1,4] ]

   def no_zeros(lst):
      a=map(filter(lambda x:(y==0 for y in x) ,lst),lst)
      print (list(a))
      #(says that filter is not callable)

I know that this code won't work but i do not know what exactly i do wrong since i'm still kind of new to lambda,etc.I already tried different stuff , like moving the filter after the lambda,but that did not seem to work either . Im gratefull for any kind of tipps or help.

Body:
lst = list(map(lambda k: list(filter(lambda l: l != 0, k)), lst))

This should do the trick. You need apply a lambda on each element in the list through a filter. Be aware nested lambdas are ugly.


问:
TWebBrowser - Does it only work when its Delphi parent form is showing?
I have a form, call it FrmCheck, with a Twebbrowser on it.
The webbrowser does not need to be shown but I an using it (instead of Indy or dynamically creating the Twebbrowser) for convenience.
The only public function on FrmCheck is function CheckIP(TheIP:string):boolean; that navigates to a few web pages, does some processing to do with IP addresses, sets a boolean retun value and exits.

The function works correctly.

However, I've noticed that when function CheckIP is called from another form, it only returns if FrmCheck (the form containing the TWebBrowser) is showing at the time.

ie this works

```<code>procedure TForm1.TestMyIPaddress(Sender: TObject);
var
    myIP : string;
begin
myIP := GetExternalIPAddress;
FrmCheck.Show;

if FrmCheck.CheckIP(myIP) then
   ShowMessage('New IP address ' + myIP +' added to those allowed access')
else
    ShowMessage('IP address already there') ;
end;
</code>```

But with the FrmCheck.Show; commented out the function doesn't return.

ie this does not work

```<code>procedure TForm1.TestMyIPaddress(Sender: TObject);
var
    myIP : string;
begin
myIP := GetExternalIPAddress;
 //FrmCheck.Show;

if FrmCheck.CheckIP(myIP) then
   ShowMessage('New IP address ' + myIP +' added to those allowed access')
else
    ShowMessage('IP address already there') ;
end;
</code>```

As a work around I found I could show the form but immediately make it invisible

ie this does work and does not show the form on the screen, the desired behaviour

```<code>procedure TForm1.TestMyIPaddress(Sender: TObject);
var
    myIP : string;
begin
myIP := GetExternalIPAddress;
FrmCheck.Show;
FrmCheck.Visible := False;

if FrmCheck.CheckIP(myIP) then
   ShowMessage('New IP address ' + myIP +' added to those allowed access')
else
    ShowMessage('IP address already there') ;
end;
</code>```

Is this expected behaviour?

Does a TWebBrowser only operate correctly when it is on a form that is being shown (even if the form is invisible), or should I be looking elsewhere for an explanation?

In deference to MartynA, here is the code of the form, using the real function names instead of the simplified ones I used to make the point of my question clear.

I am still only asking the question 'Does a TWebBrowser only operate correctly when it is on a form that is being shown'? and not what is wrong with my code.

```<code>unit U_FrmCheckIPaddressIsInAllowedHosts;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, OleCtrls,
  MSHTML,    //to access the ole bits of twebrowser
  StrUtils,  //for 'containstext' function
  IdHTTP,   //for GetExtenalIPAddress function
  SHDocVw,   //to get to the Twebbroswer Class so we can extend it
  ActiveX // For IOleCommandTarget   when adding extensions to Twebbrowser
  ;

type

//override Twebbrowser to add functionality to suppres js errors yet keep running code
//from https://stackoverflow.com/questions/8566659/how-do-i-make-twebbrowser-keep-running-javascript-after-an-error
  TWebBrowser = class(SHDocVw.TWebBrowser, IOleCommandTarget)
  private
    function QueryStatus(CmdGroup: PGUID; cCmds: Cardinal; prgCmds: POleCmd;
      CmdText: POleCmdText): HRESULT; stdcall;

    function Exec(CmdGroup: PGUID; nCmdID, nCmdexecopt: DWORD;
      const vaIn: OleVariant; var vaOut: OleVariant): HRESULT; stdcall;
  end;
  ////////////////////////////////////////////////////

  TFrmCheckIPaddressIsInAllowedHosts = class(TForm)
    WebBrowser1: TWebBrowser;
    procedure WebBrowser1BeforeNavigate2(ASender: TObject;
      const pDisp: IDispatch; var URL, Flags, TargetFrameName, PostData,
      Headers: OleVariant; var Cancel: WordBool);
    procedure WebBrowser1DocumentComplete(ASender: TObject;
      const pDisp: IDispatch; var URL: OleVariant);
    procedure WebBrowser1NavigateComplete2(ASender: TObject;
      const pDisp: IDispatch; var URL: OleVariant);
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);

  private      { Private declarations }
    CurDispatch: IDispatch;  //used to wait until document is loaded
    FDocLoaded: Boolean;     //flag to indicate when document is loaded
    addresses : TStringList;  //to hold the list of IP addresses already in hosts list
    TheIPAddress:string;
    AddressAdded : Boolean; //set to True if added

    procedure LogIntoCpanelAndCheckIPaddress;
    function GetElementById(const Doc: IDispatch; const Id: string): IDispatch;
    function GetTextOfPage(WB:twebbrowser) : string;
    function IPaddressAlreadyPresent(TheIPAddress:string; HostList2:TstringList): boolean ;
    procedure Logout;
    procedure AddNewIPaddress(TheIPaddress: string);
    function GetExternalIPAddress: string;   //works without needing to create a file
  public
    { Public declarations }
     function CheckIPAddressAndAddIfNecessary(IPaddress:string):boolean;     //returns true if address added,false otherwise
  end;

var
  FrmCheckIPaddressIsInAllowedHosts: TFrmCheckIPaddressIsInAllowedHosts;
  CheckForIPaddress : Boolean;
  CanExit : Boolean;   //flag to say we have checked the address and maybe added it

implementation

{$R *.dfm}

{ TForm5 }

{ TWebBrowser extensions}

function TWebBrowser.Exec(CmdGroup: PGUID; nCmdID, nCmdexecopt: DWORD;
  const vaIn: OleVariant; var vaOut: OleVariant): HRESULT; stdcall;
begin
  // presume that all commands can be executed; for list of available commands
  // see SHDocVw.pas unit, using this event you can suppress or create custom
  // events for more than just script error dialogs, there are commands like
  // undo, redo, refresh, open, save, print etc. etc.
  // be careful, because not all command results are meaningful, like the one
  // with script error message boxes, I would expect that if you return S_OK,
  // the error dialog will be displayed, but it's vice-versa
  Result := S_OK;

  // there's a script error in the currently executed script, so
  if nCmdID = OLECMDID_SHOWSCRIPTERROR then
  begin
    // if you return S_FALSE, the script error dialog is shown
    Result := S_FALSE;
    // if you return S_OK, the script error dialog is suppressed
    Result := S_OK;
  end;
end;   { end of TWebBrowser extensions}

function TWebBrowser.QueryStatus(CmdGroup: PGUID; cCmds: Cardinal;
  prgCmds: POleCmd; CmdText: POleCmdText): HRESULT;  stdcall;
begin
    Result := S_OK;
end;

procedure TFrmCheckIPaddressIsInAllowedHosts.AddNewIPaddress(TheIPaddress: string);
var
  Elem: IHTMLElement;

begin
//get hold of the new hosts box and enter the new IP address
  Elem := GetElementById(WebBrowser1.Document, 'host') as IHTMLElement;
  if Assigned(Elem) then
   if Elem.tagName = 'INPUT' then (Elem as IHTMLInputElement).value := TheIPaddress;

   //now click the add hosts button
     Elem := GetElementById(WebBrowser1.Document, 'submit-button') as IHTMLElement;
  if Assigned(Elem) then
    Elem.click;
end;

function TFrmCheckIPaddressIsInAllowedHosts.CheckIPAddressAndAddIfNecessary(IPaddress:string):boolean;
begin
TheIPAddress :=     IPaddress;
AddressAdded := False;
LogIntoCpanelAndCheckIPaddress  ;
Result := AddressAdded;
end;

procedure TFrmCheckIPaddressIsInAllowedHosts.FormCreate(Sender: TObject);
begin
  addresses := TStringList.create;
end;

procedure TFrmCheckIPaddressIsInAllowedHosts.FormDestroy(Sender: TObject);
begin
 addresses.Free;
end;

function TFrmCheckIPaddressIsInAllowedHosts.GetElementById(const Doc: IDispatch;  const Id: string): IDispatch;
 var
  Document: IHTMLDocument2;     // IHTMLDocument2 interface of Doc
  Body: IHTMLElement2;          // document body element
  Tags: IHTMLElementCollection; // all tags in document body
  Tag: IHTMLElement;            // a tag in document body
  I: Integer;                   // loops thru tags in document body
begin
  Result := nil;
  // Check for valid document: require IHTMLDocument2 interface to it
  if not Supports(Doc, IHTMLDocument2, Document) then
    raise Exception.Create('Invalid HTML document');
  // Check for valid body element: require IHTMLElement2 interface to it
  if not Supports(Document.body, IHTMLElement2, Body) then
    raise Exception.Create('Can''t find <body> element');
  // Get all tags in body element ('*' => any tag name)
  Tags := Body.getElementsByTagName('*');
  // Scan through all tags in body
  for I := 0 to Pred(Tags.length) do
      begin
        // Get reference to a tag
        Tag := Tags.item(I, EmptyParam) as IHTMLElement;
        // Check tag's id and return it if id matches
        if AnsiSameText(Tag.id, Id) then
        begin
          Result := Tag;
          Break;
        end;
      end;
end;

function TFrmCheckIPaddressIsInAllowedHosts.GetExternalIPAddress: string;
 //this is a copy of the function that is already in U_GeneralRoutines in mambase
var
i: integer;
PageText : string;
MStream : TMemoryStream;
HttpClient: TIdHTTP;  //need 'uses IdHTTP '

begin
//use http://checkip.dyndns.org to return ip address in a page containing the single line below
// <html><head><title>Current IP Check</title></head><body>Current IP Address: 82.71.38.7</body></html>
 Result := '';
 MStream := TMemoryStream.Create;
 HttpClient := TIdHTTP.Create;
 try
    try
    HttpClient.Get( 'http://checkip.dyndns.org/', MStream );  //download web page to a memory stream (instead of a file)
    HttpClient.Disconnect;  //not strickly necessary but prevents error 10054 Connection reset by peer
    SetString(PageText, PAnsiChar(MStream.Memory), MStream.Size) ; //assign stream contents to a string called PageText
    for i := 1 to Length(PageText) do      //extract just the numeric ip address from the line returned from the web page
        if (PageText[i] in ['0'..'9','.']) then
           Result := Result + PageText[i]  ;
    except
    on E : Exception do
      begin
      showmessage ('Could not download from checkip'  +slinebreak
                  +'Exception class name = '+E.ClassName+ slinebreak
                  +'Exception message = '+E.Message);
      end  //on E
    end;//try except

 finally
    MStream.Free;
    FreeAndNil(HttpClient);   //freenamdnil needs sysutils
 end;
end;

function TFrmCheckIPaddressIsInAllowedHosts.GetTextOfPage(WB: twebbrowser): string;
var
  Document: IHtmlDocument2;
begin
  document := WB.document as IHtmlDocument2;
  result := trim(document.body.innertext);  // to get text
 end;

function TFrmCheckIPaddressIsInAllowedHosts.IPaddressAlreadyPresent(TheIPAddress: string;
  HostList2: TstringList): boolean;
const
      digits = ['0'..'9'];
  var
    i,j,k : integer;
    line : string;
    match : boolean;
begin
result := false;  //assume the IP address is not there

////////////////////////
 for i := 0 to HostList2.Count - 1 do
     begin
     Line := HostList2[i];  // or Memo1.Lines.Strings[i]; //  get one line

     if (line <> '') and (line[1] in digits) then  //first character is a digit so we are on an IP address row  - note if line = '' then line[i] is not (and cannot be), evaluated

   //  if length(line) >= length(TheIPAddress) then  //could possibly match
        begin
        match := true;    //assume they match
        for j := 1 to length(TheIPAddress) do
          begin
          if not ((TheIPAddress[j] = line[j]) or (line[j] = '%')) then   //they don't match
              match := false;
          end;
         //set flag for result of this comparison
        if match then  //every position must have matched
          begin
          result := match;
          Exit;   //quit looping through lin4es as we have found it
          end;
        end; // if length(line) >= length(TheIPAddress)
     end;// for i := 0 to HostList.Lines.Count - 1
end;

procedure TFrmCheckIPaddressIsInAllowedHosts.LogIntoCpanelAndCheckIPaddress;
var
  Elem: IHTMLElement;
  Document: IHtmlDocument2;
 // d: OleVariant;
begin

//set teh global variable to say whether we check the text of the page or not
CheckForIPaddress := True; //as we haven't checked yet. this gets set to false after the first check
CanExit := False;  //don't exit this section until we have checked the address

//navigate to the cpanel IP hosts page - as part of this process we wil have to log on

  WebBrowser1.Navigate('https://thewebsite address.html');  //this goes through the login page
   repeat
     Application.ProcessMessages
   until FDocLoaded;

//while the page is loading, every time WebBrowser1DocumentComplete fires
//we check to see if we are on the hosts page and if so process the ip address

//now the log on page will be showing as part of navigating to the hosts page so
//fill in the user name and passwrord
   Elem := GetElementById(WebBrowser1.Document, 'user') as IHTMLElement;
  if Assigned(Elem) then
   if Elem.tagName = 'INPUT' then (Elem as IHTMLInputElement).value := 'the user';

//now the password
  Elem := GetElementById(WebBrowser1.Document, 'pass') as IHTMLElement;
  if Assigned(Elem) then
   if Elem.tagName = 'INPUT' then (Elem as IHTMLInputElement).value := 'thepassword';

   // now click the logon button
 Elem := GetElementById(WebBrowser1.Document, 'login_submit') as IHTMLElement;
  if Assigned(Elem) then
    Elem.click;

   repeat
     Application.ProcessMessages
   until FDocLoaded;

    //now we are logged on so see what the url is so we know the security token
   //    memo1.Lines.Add(WebBrowser1.LocationURL); //debug, show the url so we can get the security code

   //now wait until we have finished any residual processing of the IP address and then exit
   repeat
     Application.ProcessMessages
   until CanExit;
   Logout;
 end;

procedure TFrmCheckIPaddressIsInAllowedHosts.Logout;
begin
WebBrowser1.Navigate( 'https://thelogouturl' );
   repeat
     Application.ProcessMessages
   until FDocLoaded;
   showmessage('logged out');
end;

procedure TFrmCheckIPaddressIsInAllowedHosts.WebBrowser1BeforeNavigate2(ASender: TObject;
  const pDisp: IDispatch; var URL, Flags, TargetFrameName, PostData,
  Headers: OleVariant; var Cancel: WordBool);
begin
   CurDispatch := nil;
      FDocLoaded := False;
end;

procedure TFrmCheckIPaddressIsInAllowedHosts.WebBrowser1DocumentComplete(ASender: TObject;
  const pDisp: IDispatch; var URL: OleVariant);
  var s : string;
begin
     if (pDisp = CurDispatch) then
      begin
        FDocLoaded := True;
        CurDispatch := nil;
      end;

    //WebBrowser1DocumentComplete is called many times and so FDocLoaded could be true many times
    //to avoid checking the ip address multiple times we use a global variable CheckForIPaddress as a flag
    //to ensure we only check once

    if CheckForIPaddress and FDocLoaded then     //if CheckForIPaddress is false then we have already checked so don't do it again
        begin
        //now check which page we are on. if its the hosts page then we have the text we need
         s := GetTextOfPage(Webbrowser1);
         if ContainsText(s,'Remote Database Access Hosts') then //we are on the hosts page
          begin     //process the ip address with respect to those already recorded
          CheckForIPaddress := false; //reset the flag so that we don't bother checking each time FDocLoaded is true
          addresses.text :=s;       //put the addresses into a list so we can check them
          if IPaddressAlreadyPresent(TheIPAddress, addresses) then
              begin
              AddressAdded := false;
             // showmessage('already there');
             // Logout;
              end
          else
             begin
            // showmessage('not there');
             AddNewIPaddress(TheIPAddress);
             AddressAdded := True;
            // Logout;
             end;
          //either way we can now exit
          CanExit := True; //the procedure  LogIntoCpanelAndGotToHostsPage can exit back to the main program when it finishes
          end;
        end; //if FDocLoaded

end;

procedure TFrmCheckIPaddressIsInAllowedHosts.WebBrowser1NavigateComplete2(ASender: TObject;
  const pDisp: IDispatch; var URL: OleVariant);
begin
       if CurDispatch = nil then
        CurDispatch := pDisp;
end;

end.
</code>```

答: Call WebBrowser1.HandleNeeded; before calling Navigate.

Body:
I have a form, call it FrmCheck, with a Twebbrowser on it.
The webbrowser does not need to be shown but I an using it (instead of Indy or dynamically creating the Twebbrowser) for convenience.
The only public function on FrmCheck is function CheckIP(TheIP:string):boolean; that navigates to a few web pages, does some processing to do with IP addresses, sets a boolean retun value and exits.

The function works correctly.

However, I've noticed that when function CheckIP is called from another form, it only returns if FrmCheck (the form containing the TWebBrowser) is showing at the time.

ie this works

procedure TForm1.TestMyIPaddress(Sender: TObject);
var
    myIP : string;
begin
myIP := GetExternalIPAddress;
FrmCheck.Show;

if FrmCheck.CheckIP(myIP) then
   ShowMessage('New IP address ' + myIP +' added to those allowed access')
else
    ShowMessage('IP address already there') ;
end;

But with the FrmCheck.Show; commented out the function doesn't return.

ie this does not work

procedure TForm1.TestMyIPaddress(Sender: TObject);
var
    myIP : string;
begin
myIP := GetExternalIPAddress;
 //FrmCheck.Show;

if FrmCheck.CheckIP(myIP) then
   ShowMessage('New IP address ' + myIP +' added to those allowed access')
else
    ShowMessage('IP address already there') ;
end;

As a work around I found I could show the form but immediately make it invisible

ie this does work and does not show the form on the screen, the desired behaviour

procedure TForm1.TestMyIPaddress(Sender: TObject);
var
    myIP : string;
begin
myIP := GetExternalIPAddress;
FrmCheck.Show;
FrmCheck.Visible := False;

if FrmCheck.CheckIP(myIP) then
   ShowMessage('New IP address ' + myIP +' added to those allowed access')
else
    ShowMessage('IP address already there') ;
end;

Is this expected behaviour?

Does a TWebBrowser only operate correctly when it is on a form that is being shown (even if the form is invisible), or should I be looking elsewhere for an explanation?

In deference to MartynA, here is the code of the form, using the real function names instead of the simplified ones I used to make the point of my question clear.

I am still only asking the question 'Does a TWebBrowser only operate correctly when it is on a form that is being shown'? and not what is wrong with my code.

unit U_FrmCheckIPaddressIsInAllowedHosts;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, OleCtrls,
  MSHTML,    //to access the ole bits of twebrowser
  StrUtils,  //for 'containstext' function
  IdHTTP,   //for GetExtenalIPAddress function
  SHDocVw,   //to get to the Twebbroswer Class so we can extend it
  ActiveX // For IOleCommandTarget   when adding extensions to Twebbrowser
  ;

type

//override Twebbrowser to add functionality to suppres js errors yet keep running code
//from https://stackoverflow.com/questions/8566659/how-do-i-make-twebbrowser-keep-running-javascript-after-an-error
  TWebBrowser = class(SHDocVw.TWebBrowser, IOleCommandTarget)
  private
    function QueryStatus(CmdGroup: PGUID; cCmds: Cardinal; prgCmds: POleCmd;
      CmdText: POleCmdText): HRESULT; stdcall;

    function Exec(CmdGroup: PGUID; nCmdID, nCmdexecopt: DWORD;
      const vaIn: OleVariant; var vaOut: OleVariant): HRESULT; stdcall;
  end;
  ////////////////////////////////////////////////////

  TFrmCheckIPaddressIsInAllowedHosts = class(TForm)
    WebBrowser1: TWebBrowser;
    procedure WebBrowser1BeforeNavigate2(ASender: TObject;
      const pDisp: IDispatch; var URL, Flags, TargetFrameName, PostData,
      Headers: OleVariant; var Cancel: WordBool);
    procedure WebBrowser1DocumentComplete(ASender: TObject;
      const pDisp: IDispatch; var URL: OleVariant);
    procedure WebBrowser1NavigateComplete2(ASender: TObject;
      const pDisp: IDispatch; var URL: OleVariant);
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);

  private      { Private declarations }
    CurDispatch: IDispatch;  //used to wait until document is loaded
    FDocLoaded: Boolean;     //flag to indicate when document is loaded
    addresses : TStringList;  //to hold the list of IP addresses already in hosts list
    TheIPAddress:string;
    AddressAdded : Boolean; //set to True if added

    procedure LogIntoCpanelAndCheckIPaddress;
    function GetElementById(const Doc: IDispatch; const Id: string): IDispatch;
    function GetTextOfPage(WB:twebbrowser) : string;
    function IPaddressAlreadyPresent(TheIPAddress:string; HostList2:TstringList): boolean ;
    procedure Logout;
    procedure AddNewIPaddress(TheIPaddress: string);
    function GetExternalIPAddress: string;   //works without needing to create a file
  public
    { Public declarations }
     function CheckIPAddressAndAddIfNecessary(IPaddress:string):boolean;     //returns true if address added,false otherwise
  end;

var
  FrmCheckIPaddressIsInAllowedHosts: TFrmCheckIPaddressIsInAllowedHosts;
  CheckForIPaddress : Boolean;
  CanExit : Boolean;   //flag to say we have checked the address and maybe added it

implementation

{$R *.dfm}

{ TForm5 }

{ TWebBrowser extensions}

function TWebBrowser.Exec(CmdGroup: PGUID; nCmdID, nCmdexecopt: DWORD;
  const vaIn: OleVariant; var vaOut: OleVariant): HRESULT; stdcall;
begin
  // presume that all commands can be executed; for list of available commands
  // see SHDocVw.pas unit, using this event you can suppress or create custom
  // events for more than just script error dialogs, there are commands like
  // undo, redo, refresh, open, save, print etc. etc.
  // be careful, because not all command results are meaningful, like the one
  // with script error message boxes, I would expect that if you return S_OK,
  // the error dialog will be displayed, but it's vice-versa
  Result := S_OK;

  // there's a script error in the currently executed script, so
  if nCmdID = OLECMDID_SHOWSCRIPTERROR then
  begin
    // if you return S_FALSE, the script error dialog is shown
    Result := S_FALSE;
    // if you return S_OK, the script error dialog is suppressed
    Result := S_OK;
  end;
end;   { end of TWebBrowser extensions}

function TWebBrowser.QueryStatus(CmdGroup: PGUID; cCmds: Cardinal;
  prgCmds: POleCmd; CmdText: POleCmdText): HRESULT;  stdcall;
begin
    Result := S_OK;
end;

procedure TFrmCheckIPaddressIsInAllowedHosts.AddNewIPaddress(TheIPaddress: string);
var
  Elem: IHTMLElement;

begin
//get hold of the new hosts box and enter the new IP address
  Elem := GetElementById(WebBrowser1.Document, 'host') as IHTMLElement;
  if Assigned(Elem) then
   if Elem.tagName = 'INPUT' then (Elem as IHTMLInputElement).value := TheIPaddress;

   //now click the add hosts button
     Elem := GetElementById(WebBrowser1.Document, 'submit-button') as IHTMLElement;
  if Assigned(Elem) then
    Elem.click;
end;

function TFrmCheckIPaddressIsInAllowedHosts.CheckIPAddressAndAddIfNecessary(IPaddress:string):boolean;
begin
TheIPAddress :=     IPaddress;
AddressAdded := False;
LogIntoCpanelAndCheckIPaddress  ;
Result := AddressAdded;
end;

procedure TFrmCheckIPaddressIsInAllowedHosts.FormCreate(Sender: TObject);
begin
  addresses := TStringList.create;
end;

procedure TFrmCheckIPaddressIsInAllowedHosts.FormDestroy(Sender: TObject);
begin
 addresses.Free;
end;

function TFrmCheckIPaddressIsInAllowedHosts.GetElementById(const Doc: IDispatch;  const Id: string): IDispatch;
 var
  Document: IHTMLDocument2;     // IHTMLDocument2 interface of Doc
  Body: IHTMLElement2;          // document body element
  Tags: IHTMLElementCollection; // all tags in document body
  Tag: IHTMLElement;            // a tag in document body
  I: Integer;                   // loops thru tags in document body
begin
  Result := nil;
  // Check for valid document: require IHTMLDocument2 interface to it
  if not Supports(Doc, IHTMLDocument2, Document) then
    raise Exception.Create('Invalid HTML document');
  // Check for valid body element: require IHTMLElement2 interface to it
  if not Supports(Document.body, IHTMLElement2, Body) then
    raise Exception.Create('Can''t find  element');
  // Get all tags in body element ('*' => any tag name)
  Tags := Body.getElementsByTagName('*');
  // Scan through all tags in body
  for I := 0 to Pred(Tags.length) do
      begin
        // Get reference to a tag
        Tag := Tags.item(I, EmptyParam) as IHTMLElement;
        // Check tag's id and return it if id matches
        if AnsiSameText(Tag.id, Id) then
        begin
          Result := Tag;
          Break;
        end;
      end;
end;

function TFrmCheckIPaddressIsInAllowedHosts.GetExternalIPAddress: string;
 //this is a copy of the function that is already in U_GeneralRoutines in mambase
var
i: integer;
PageText : string;
MStream : TMemoryStream;
HttpClient: TIdHTTP;  //need 'uses IdHTTP '

begin
//use http://checkip.dyndns.org to return ip address in a page containing the single line below
// <title>Current IP Check</title>Current IP Address: 82.71.38.7
 Result := '';
 MStream := TMemoryStream.Create;
 HttpClient := TIdHTTP.Create;
 try
    try
    HttpClient.Get( 'http://checkip.dyndns.org/', MStream );  //download web page to a memory stream (instead of a file)
    HttpClient.Disconnect;  //not strickly necessary but prevents error 10054 Connection reset by peer
    SetString(PageText, PAnsiChar(MStream.Memory), MStream.Size) ; //assign stream contents to a string called PageText
    for i := 1 to Length(PageText) do      //extract just the numeric ip address from the line returned from the web page
        if (PageText[i] in ['0'..'9','.']) then
           Result := Result + PageText[i]  ;
    except
    on E : Exception do
      begin
      showmessage ('Could not download from checkip'  +slinebreak
                  +'Exception class name = '+E.ClassName+ slinebreak
                  +'Exception message = '+E.Message);
      end  //on E
    end;//try except

 finally
    MStream.Free;
    FreeAndNil(HttpClient);   //freenamdnil needs sysutils
 end;
end;

function TFrmCheckIPaddressIsInAllowedHosts.GetTextOfPage(WB: twebbrowser): string;
var
  Document: IHtmlDocument2;
begin
  document := WB.document as IHtmlDocument2;
  result := trim(document.body.innertext);  // to get text
 end;

function TFrmCheckIPaddressIsInAllowedHosts.IPaddressAlreadyPresent(TheIPAddress: string;
  HostList2: TstringList): boolean;
const
      digits = ['0'..'9'];
  var
    i,j,k : integer;
    line : string;
    match : boolean;
begin
result := false;  //assume the IP address is not there

////////////////////////
 for i := 0 to HostList2.Count - 1 do
     begin
     Line := HostList2[i];  // or Memo1.Lines.Strings[i]; //  get one line

     if (line <> '') and (line[1] in digits) then  //first character is a digit so we are on an IP address row  - note if line = '' then line[i] is not (and cannot be), evaluated

   //  if length(line) >= length(TheIPAddress) then  //could possibly match
        begin
        match := true;    //assume they match
        for j := 1 to length(TheIPAddress) do
          begin
          if not ((TheIPAddress[j] = line[j]) or (line[j] = '%')) then   //they don't match
              match := false;
          end;
         //set flag for result of this comparison
        if match then  //every position must have matched
          begin
          result := match;
          Exit;   //quit looping through lin4es as we have found it
          end;
        end; // if length(line) >= length(TheIPAddress)
     end;// for i := 0 to HostList.Lines.Count - 1
end;

procedure TFrmCheckIPaddressIsInAllowedHosts.LogIntoCpanelAndCheckIPaddress;
var
  Elem: IHTMLElement;
  Document: IHtmlDocument2;
 // d: OleVariant;
begin

//set teh global variable to say whether we check the text of the page or not
CheckForIPaddress := True; //as we haven't checked yet. this gets set to false after the first check
CanExit := False;  //don't exit this section until we have checked the address

//navigate to the cpanel IP hosts page - as part of this process we wil have to log on

  WebBrowser1.Navigate('https://thewebsite address.html');  //this goes through the login page
   repeat
     Application.ProcessMessages
   until FDocLoaded;

//while the page is loading, every time WebBrowser1DocumentComplete fires
//we check to see if we are on the hosts page and if so process the ip address

//now the log on page will be showing as part of navigating to the hosts page so
//fill in the user name and passwrord
   Elem := GetElementById(WebBrowser1.Document, 'user') as IHTMLElement;
  if Assigned(Elem) then
   if Elem.tagName = 'INPUT' then (Elem as IHTMLInputElement).value := 'the user';

//now the password
  Elem := GetElementById(WebBrowser1.Document, 'pass') as IHTMLElement;
  if Assigned(Elem) then
   if Elem.tagName = 'INPUT' then (Elem as IHTMLInputElement).value := 'thepassword';

   // now click the logon button
 Elem := GetElementById(WebBrowser1.Document, 'login_submit') as IHTMLElement;
  if Assigned(Elem) then
    Elem.click;

   repeat
     Application.ProcessMessages
   until FDocLoaded;

    //now we are logged on so see what the url is so we know the security token
   //    memo1.Lines.Add(WebBrowser1.LocationURL); //debug, show the url so we can get the security code

   //now wait until we have finished any residual processing of the IP address and then exit
   repeat
     Application.ProcessMessages
   until CanExit;
   Logout;
 end;

procedure TFrmCheckIPaddressIsInAllowedHosts.Logout;
begin
WebBrowser1.Navigate( 'https://thelogouturl' );
   repeat
     Application.ProcessMessages
   until FDocLoaded;
   showmessage('logged out');
end;

procedure TFrmCheckIPaddressIsInAllowedHosts.WebBrowser1BeforeNavigate2(ASender: TObject;
  const pDisp: IDispatch; var URL, Flags, TargetFrameName, PostData,
  Headers: OleVariant; var Cancel: WordBool);
begin
   CurDispatch := nil;
      FDocLoaded := False;
end;

procedure TFrmCheckIPaddressIsInAllowedHosts.WebBrowser1DocumentComplete(ASender: TObject;
  const pDisp: IDispatch; var URL: OleVariant);
  var s : string;
begin
     if (pDisp = CurDispatch) then
      begin
        FDocLoaded := True;
        CurDispatch := nil;
      end;

    //WebBrowser1DocumentComplete is called many times and so FDocLoaded could be true many times
    //to avoid checking the ip address multiple times we use a global variable CheckForIPaddress as a flag
    //to ensure we only check once

    if CheckForIPaddress and FDocLoaded then     //if CheckForIPaddress is false then we have already checked so don't do it again
        begin
        //now check which page we are on. if its the hosts page then we have the text we need
         s := GetTextOfPage(Webbrowser1);
         if ContainsText(s,'Remote Database Access Hosts') then //we are on the hosts page
          begin     //process the ip address with respect to those already recorded
          CheckForIPaddress := false; //reset the flag so that we don't bother checking each time FDocLoaded is true
          addresses.text :=s;       //put the addresses into a list so we can check them
          if IPaddressAlreadyPresent(TheIPAddress, addresses) then
              begin
              AddressAdded := false;
             // showmessage('already there');
             // Logout;
              end
          else
             begin
            // showmessage('not there');
             AddNewIPaddress(TheIPAddress);
             AddressAdded := True;
            // Logout;
             end;
          //either way we can now exit
          CanExit := True; //the procedure  LogIntoCpanelAndGotToHostsPage can exit back to the main program when it finishes
          end;
        end; //if FDocLoaded

end;

procedure TFrmCheckIPaddressIsInAllowedHosts.WebBrowser1NavigateComplete2(ASender: TObject;
  const pDisp: IDispatch; var URL: OleVariant);
begin
       if CurDispatch = nil then
        CurDispatch := pDisp;
end;

end.


问:
CSS grid in ie11 with less mixins
Did anybody see css grids mixins on less for IE11.
I try to use grids but it's too difficult write all prefix on IE11. I talk about this:

```<code>-ms-grid-row: 1;
-ms-grid-column: 3;
-ms-grid-column-span: 2;

grid-column: 3 ~'/' 5;
grid-row: 1;
</code>```

Any lifehacks?

Codepen -> https://codepen.io/Muskos/pen/vpLeJg

答:
If I understand you right all you need is:

```<code>.grid-mixin(@row, @column-start, @column-span, @row-span, @column-end: @column-start + @column-span, @row-end: @row + @row-span){
  -ms-grid-row: @row;
  -ms-grid-row-span: @row-span;
  -ms-grid-column: @column-start;
  -ms-grid-column-span: @column-span;

  grid-column: @column-start ~'/' @column-end;
  grid-row:  @row ~'/' @row-end;
}
</code>```

and when needed you just need to call it like:

```<code>.grid-mixin(1,3,2,1);
</code>```

You can try this solution here: https://codepen.io/Muskos/pen/vpLeJg?editors=1100

Also if you are using gulp, webpack and etc, use Autoprefixer. It's already about 3 years we don't have to put any vendor prefixes into CSS. Just write standard CSS and the tools will do the rest.

Title: CSS grid in ie11 with less mixins

Body:
Did anybody see css grids mixins on less for IE11.
I try to use grids but it's too difficult write all prefix on IE11. I talk about this:

-ms-grid-row: 1;
-ms-grid-column: 3;
-ms-grid-column-span: 2;

grid-column: 3 ~'/' 5;
grid-row: 1;

Any lifehacks?

Codepen -> https://codepen.io/Muskos/pen/vpLeJg

Body:
If I understand you right all you need is:

.grid-mixin(@row, @column-start, @column-span, @row-span, @column-end: @column-start + @column-span, @row-end: @row + @row-span){
  -ms-grid-row: @row;
  -ms-grid-row-span: @row-span;
  -ms-grid-column: @column-start;
  -ms-grid-column-span: @column-span;

  grid-column: @column-start ~'/' @column-end;
  grid-row:  @row ~'/' @row-end;
}

and when needed you just need to call it like:

.grid-mixin(1,3,2,1);

You can try this solution here: https://codepen.io/Muskos/pen/vpLeJg?editors=1100

Also if you are using gulp, webpack and etc, use Autoprefixer. It's already about 3 years we don't have to put any vendor prefixes into CSS. Just write standard CSS and the tools will do the rest.


问:
How can I specify exact output path for new .csproj file format?
I'm playing around with using the new .csproj file format.

I want my project to build to:

C:\Development\Source\DotNet\bin\x64\Debug\

But it seems to be implicitly adding to the path and building it at:

C:\Development\Source\DotNet\bin\x64\Debug\net46

Is there a way to prevent it from doing that?

My project is:

```<code><Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>net46</TargetFramework>
    <Platforms>x64</Platforms>
    <ApplicationIcon />
    <OutputType>Exe</OutputType>
    <StartupObject />
  </PropertyGroup>

  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
    <OutputPath>C:\Development\Source\DotNet\bin\x64\Debug\</OutputPath>
  </PropertyGroup>

  <ItemGroup>
    <Reference Include="AssetManagement_Gen">
      <HintPath>..\..\Development\Source\DotNet\bin\x64\Debug\AssetManagement_Gen.dll</HintPath>
    </Reference>
    <Reference Include="EXPLink">
      <HintPath>..\..\Development\Source\DotNet\bin\x64\Debug\EXPLink.dll</HintPath>
    </Reference>
    <Reference Include="IvaraCommon">
      <HintPath>..\..\Development\Source\DotNet\bin\x64\Debug\IvaraCommon.dll</HintPath>
    </Reference>
    <Reference Include="NLog">
      <HintPath>..\..\Development\Source\DotNet\bin\x64\Debug\NLog.dll</HintPath>
    </Reference>
    <Reference Include="System.Windows.Forms" />
  </ItemGroup>

</Project>
</code>```

If I open it in visual studio it also shows up with the "net46" appended to the output path.

For my posterity, the combination of <OutputPath> and <AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath> lets you get a completely custom path.

```<code><Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>net46</TargetFramework>
    <AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
    <Platforms>x64</Platforms>
    <ApplicationIcon />
    <OutputType>Exe</OutputType>
    <StartupObject />
  </PropertyGroup>

  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
    <OutputPath>..\..\..\bin\$(Platform)\$(Configuration)</OutputPath>
  </PropertyGroup>

  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
    <OutputPath>..\..\..\bin\$(Platform)\$(Configuration)</OutputPath>
  </PropertyGroup>

  <ItemGroup>
    <Reference Include="AssetManagement_Gen">
      <HintPath>$(OutDir)\AssetManagement_Gen.dll</HintPath>
    </Reference>
    <Reference Include="EXPLink">
      <HintPath>$(OutDir)\EXPLink.dll</HintPath>
    </Reference>
    <Reference Include="IvaraCommon">
      <HintPath>$(OutDir)\IvaraCommon.dll</HintPath>
    </Reference>
    <Reference Include="NLog">
      <HintPath>$(OutDir)\NLog.dll</HintPath>
    </Reference>
    <Reference Include="System.Windows.Forms" />
  </ItemGroup>

</Project>
</code>```

答:
I found the following post:

https://compiledexperience.com/blog/posts/multi-targeting-output-path

If you want to disable this automatic appending, for instance you’re only going to be using one target framework or you’re defining a different output path per framework then you can use AppendTargetFrameworkToOutputPath.

```<code><Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>netstandard1.4</TargetFramework>
    <AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
  </PropertyGroup>
</Project>
</code>```

ContentLicense: CC BY-SA 4.0

Body:
I'm playing around with using the new .csproj file format.

I want my project to build to:

C:\Development\Source\DotNet\bin\x64\Debug\

But it seems to be implicitly adding to the path and building it at:

C:\Development\Source\DotNet\bin\x64\Debug\net46

Is there a way to prevent it from doing that?

My project is:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>net46</TargetFramework>
    <Platforms>x64</Platforms>
    <ApplicationIcon />
    <OutputType>Exe</OutputType>
    <StartupObject />
  </PropertyGroup>

  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
    <OutputPath>C:\Development\Source\DotNet\bin\x64\Debug\</OutputPath>
  </PropertyGroup>

  <ItemGroup>
    <Reference Include="AssetManagement_Gen">
      <HintPath>..\..\Development\Source\DotNet\bin\x64\Debug\AssetManagement_Gen.dll</HintPath>
    </Reference>
    <Reference Include="EXPLink">
      <HintPath>..\..\Development\Source\DotNet\bin\x64\Debug\EXPLink.dll</HintPath>
    </Reference>
    <Reference Include="IvaraCommon">
      <HintPath>..\..\Development\Source\DotNet\bin\x64\Debug\IvaraCommon.dll</HintPath>
    </Reference>
    <Reference Include="NLog">
      <HintPath>..\..\Development\Source\DotNet\bin\x64\Debug\NLog.dll</HintPath>
    </Reference>
    <Reference Include="System.Windows.Forms" />
  </ItemGroup>

</Project>

If I open it in visual studio it also shows up with the "net46" appended to the output path.

For my posterity, the combination of <OutputPath> and <AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath> lets you get a completely custom path.

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>net46</TargetFramework>
    <AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
    <Platforms>x64</Platforms>
    <ApplicationIcon />
    <OutputType>Exe</OutputType>
    <StartupObject />
  </PropertyGroup>

  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
    <OutputPath>..\..\..\bin\$(Platform)\$(Configuration)</OutputPath>
  </PropertyGroup>

  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
    <OutputPath>..\..\..\bin\$(Platform)\$(Configuration)</OutputPath>
  </PropertyGroup>

  <ItemGroup>
    <Reference Include="AssetManagement_Gen">
      <HintPath>$(OutDir)\AssetManagement_Gen.dll</HintPath>
    </Reference>
    <Reference Include="EXPLink">
      <HintPath>$(OutDir)\EXPLink.dll</HintPath>
    </Reference>
    <Reference Include="IvaraCommon">
      <HintPath>$(OutDir)\IvaraCommon.dll</HintPath>
    </Reference>
    <Reference Include="NLog">
      <HintPath>$(OutDir)\NLog.dll</HintPath>
    </Reference>
    <Reference Include="System.Windows.Forms" />
  </ItemGroup>

</Project>

Body:
I found the following post:

https://compiledexperience.com/blog/posts/multi-targeting-output-path

If you want to disable this automatic appending, for instance you’re only going to be using one target framework or you’re defining a different output path per framework then you can use AppendTargetFrameworkToOutputPath.

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>netstandard1.4</TargetFramework>
    <AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
  </PropertyGroup>
</Project>


问:
Git Submodules become detach on clone
I am setting up a git-repository that will be used by 5-10 developers
I have setup a few submodules within my main repository, but it seems they do not automatically track a branch upon recursive clone.
The main problem is to avoid developers committing outside a branch (i.e. headless)

I believe i have added the submodules the way other StackOverflow post suggest you should setup branch tracking. e.g. git submodule tracking latest

i use git 2.7.4 and add with the commands

```<code>git submodule add -b ${submodule_branch} ../../${submodule_repo_path}.git ${submodule_path}
git submodule update --remote
</code>```

When i call 'git branch' within one of the submodules it clearly show that i am on a branch.

```<code>git branch
* master
</code>```

I commit this change and push to the remote 'git push origin --mirror --force'

The server is BitBucket v5.3.0

When i clone with 'git clone --recursive' i get all the repo and the .gitmodules looks right, it mentions the branch

```<code>[submodule "some_app"]
path = some_app
url = ../../some_app.git
branch = master
</code>```

However within the submodule it looks like it is detached:

```<code>somepath/some_app ((487b858...))
$ git branch
git branch
* (HEAD detached at 487b858)
  master
</code>```

I can make a workaround by checking out the correct branch in each submodule, but i do not think it should be needed.

i have also tried to call

```<code>git submodule update --remote
</code>```

after cloning, but it did not help

Is it normal practice that you must first checkout a branch when working with submodules?

答:
From which folder did you try the submodules update command? I guess without testing that this is one of the cases you should at least be in the main repository containing the subrepositories and not within one of them.

The detach behavior is the wished behavior. When you look at the file that represents the submodule folder you'll see the commit hash from the time the submodule was added.
When you do a git submodule update --remote you'll also see that you have to commit the updates, which means that git will write the now newest commit hash to the file. This allows you to go to a specific commit of the submodule.

I needed some time to get used to it. You should definitly read the submodules chapter of the git scm book. It gives you some tips and tricks (and commands/settings) that help you using submodules.

Title: Git Submodules become detach on clone

Body:
I am setting up a git-repository that will be used by 5-10 developers
I have setup a few submodules within my main repository, but it seems they do not automatically track a branch upon recursive clone.
The main problem is to avoid developers committing outside a branch (i.e. headless)

I believe i have added the submodules the way other StackOverflow post suggest you should setup branch tracking. e.g. git submodule tracking latest

i use git 2.7.4 and add with the commands

git submodule add -b ${submodule_branch} ../../${submodule_repo_path}.git ${submodule_path}
git submodule update --remote

When i call 'git branch' within one of the submodules it clearly show that i am on a branch.

git branch
* master

I commit this change and push to the remote 'git push origin --mirror --force'

The server is BitBucket v5.3.0

When i clone with 'git clone --recursive' i get all the repo and the .gitmodules looks right, it mentions the branch

[submodule "some_app"]
path = some_app
url = ../../some_app.git
branch = master

However within the submodule it looks like it is detached:

somepath/some_app ((487b858...))
$ git branch
git branch
* (HEAD detached at 487b858)
  master

I can make a workaround by checking out the correct branch in each submodule, but i do not think it should be needed.

i have also tried to call

git submodule update --remote

after cloning, but it did not help

Is it normal practice that you must first checkout a branch when working with submodules?


问:
How to assign values after the program finished drawing Google Charts?
I know that sounds a bit weird but I got a piece of code in here:

```<code>let globalResult = [];
let defaultData = ["None", 1200, 1200, 1200, 1200, 1200, 1200, 1200,
1200, 1200, 1200, 1200];
$(document).ready(() => {
    // set a listener on the textbox
    $('#input').on("change", (evt) => {
        let text = $('#input').val();
        // the {text: text} sends a parameter named text with the
        // value of what was typed in the textbox
        $.get("/display", {text: text})
            .done((data) => {
                globalResult = data['result'];
                $('#input').val('');   // reset the textbox
                //Draw Graph
                google.charts.load('current', {'packages':['corechart']});
                google.charts.setOnLoadCallback(drawChart);

                function drawChart() {
                    //Chart stuff.... Doesn't matter
                    //It's programmed to Draw Line with defaultData and globalResult
                    };

                    var chart = new google.visualization.LineChart(document.getElementById('curve_chart'));

                    chart.draw(data, options);
                    //Swap Value here:
                    defaultData = globalResult;
                }

            })
</code>```

I tried to swap defaultData and globalResult after the Chart is drawn, But some how it always drawing a new chart when swapping data, thus it causes interruption on the graph (like another line just died in the middle of the drawing, left half of the line hanging out there). If I trying to put these outside of the function drawChart, it will draw 2 same line with another dies in the middle. And I also cannot place this outside of $.get() scope cause that the chart won't be drawn. How do I fix that?

答:
the load statement (google.charts.load) will wait until the document is ready,

before executing the callback, or promise it returns...

as such, no need for --> $(document).ready

load google first using the promise,

then create the chart and save the reference for later use,

which will allow you to draw the same chart with any data

recommend setup similar to following...

```<code>let globalResult = [];
let defaultData = ["None", 1200, 1200, 1200, 1200, 1200, 1200, 1200, 1200, 1200, 1200, 1200];

google.charts.load('current', {
  packages: ['corechart']
}).then(() => {
    // save reference to chart here
    var chart = new google.visualization.LineChart(document.getElementById('curve_chart'));

    $('#input').on("change", (evt) => {
        let text = $('#input').val();
        // the {text: text} sends a parameter named text with the
        // value of what was typed in the textbox
        $.get("/display", {text: text})
            .done((data) => {
                globalResult = data['result'];
                $('#input').val('');   // reset the textbox

                //Chart stuff....
                chart.draw(data, options);

                //Swap Value here:
                defaultData = globalResult;
            });

    });
});
</code>```

Body:
I know that sounds a bit weird but I got a piece of code in here:

let globalResult = [];
let defaultData = ["None", 1200, 1200, 1200, 1200, 1200, 1200, 1200,
1200, 1200, 1200, 1200];
$(document).ready(() => {
    // set a listener on the textbox
    $('#input').on("change", (evt) => {
        let text = $('#input').val();
        // the {text: text} sends a parameter named text with the
        // value of what was typed in the textbox
        $.get("/display", {text: text})
            .done((data) => {
                globalResult = data['result'];
                $('#input').val('');   // reset the textbox
                //Draw Graph
                google.charts.load('current', {'packages':['corechart']});
                google.charts.setOnLoadCallback(drawChart);

                function drawChart() {
                    //Chart stuff.... Doesn't matter
                    //It's programmed to Draw Line with defaultData and globalResult
                    };

                    var chart = new google.visualization.LineChart(document.getElementById('curve_chart'));

                    chart.draw(data, options);
                    //Swap Value here:
                    defaultData = globalResult;
                }

            })

I tried to swap defaultData and globalResult after the Chart is drawn, But some how it always drawing a new chart when swapping data, thus it causes interruption on the graph (like another line just died in the middle of the drawing, left half of the line hanging out there). If I trying to put these outside of the function drawChart, it will draw 2 same line with another dies in the middle. And I also cannot place this outside of $.get() scope cause that the chart won't be drawn. How do I fix that?

Body:
the load statement (google.charts.load) will wait until the document is ready,

before executing the callback, or promise it returns...

as such, no need for --> $(document).ready

load google first using the promise,

then create the chart and save the reference for later use,

which will allow you to draw the same chart with any data

recommend setup similar to following...

let globalResult = [];
let defaultData = ["None", 1200, 1200, 1200, 1200, 1200, 1200, 1200, 1200, 1200, 1200, 1200];

google.charts.load('current', {
  packages: ['corechart']
}).then(() => {
    // save reference to chart here
    var chart = new google.visualization.LineChart(document.getElementById('curve_chart'));

    $('#input').on("change", (evt) => {
        let text = $('#input').val();
        // the {text: text} sends a parameter named text with the
        // value of what was typed in the textbox
        $.get("/display", {text: text})
            .done((data) => {
                globalResult = data['result'];
                $('#input').val('');   // reset the textbox

                //Chart stuff....
                chart.draw(data, options);

                //Swap Value here:
                defaultData = globalResult;
            });

    });
});


问:
Check if the text file was empty
I'd like to know how to check if a text file is empty or not. It means that there is no text even some space, i.e. it was blank</p>

```<code>function keyRemain($path)
{
    $ambil = file_get_contents("data/$path/keywords.txt");
    $kw = explode(",", $ambil);
    if (count($kw) > 1) {
        return false;
    } else {
        return true;
    }
}
</code>```

答: Maybe this was not the answer, just the another way to check the file. Before this was happend, the code appear instead the class. After i cut it and move it outside of the class it work perfectly without any errors.</p>

Title: Check if the text file was empty

Body:
I'd like to know how to check if a text file is empty or not. It means that there is no text even some space, i.e. it was blank

function keyRemain($path)
{
    $ambil = file_get_contents("data/$path/keywords.txt");
    $kw = explode(",", $ambil);
    if (count($kw) > 1) {
        return false;
    } else {
        return true;
    }
}


问:
Safe way to store mysql server credentials in flask?
I was wondering about the safety of some thing in my app.py flask app. First the database, I'm using mysql and currently I am connecting to it in the following way:

```<code># Config MySQL
app.config['MYSQL_HOST'] = 'localhost'
app.config['MYSQL_USER'] = 'root'
app.config['MYSQL_PASSWORD'] = 'password'
app.config['MYSQL_DB'] = 'databasename'
app.config['MYSQL_CURSORCLASS'] = 'DictCursor'
</code>```

And to me this feels very weird, just putting in your password in plain text etc. I've been searching online but have not found any other way of doing this other than putting it in a seperate python file and just importing it. Which kinda feels like doing nothing at all.. Is there a better way to do this security wise?

Then the secret key I use for password encoding. Which is also just stored in plain text in my code, is there also a way to make this more secure or make it less obvious?

Thanks in advance!

答:
The computer which runs your code needs to know the password, so you can't secure against the owner of the computer (if that's not you). But if you are having the password in the sourcecode it can easily happen that you put it into version control and if you use a public github it can easily happen that you publish your key.

As alternative you can put the password in a config file (take care to not put it into version control e.g. via .gitignore) or you can use environmental variables.

Body:
I was wondering about the safety of some thing in my app.py flask app. First the database, I'm using mysql and currently I am connecting to it in the following way:

# Config MySQL
app.config['MYSQL_HOST'] = 'localhost'
app.config['MYSQL_USER'] = 'root'
app.config['MYSQL_PASSWORD'] = 'password'
app.config['MYSQL_DB'] = 'databasename'
app.config['MYSQL_CURSORCLASS'] = 'DictCursor'

And to me this feels very weird, just putting in your password in plain text etc. I've been searching online but have not found any other way of doing this other than putting it in a seperate python file and just importing it. Which kinda feels like doing nothing at all.. Is there a better way to do this security wise?

Then the secret key I use for password encoding. Which is also just stored in plain text in my code, is there also a way to make this more secure or make it less obvious?

Thanks in advance!


问:
Is there a way to intercept Android Activity after it is instantiated?
Is there a way to intercept whenever the Application creates a new Activity instance?  I'm only interested in Activities belonging to the Application process not all Activities on the phone.  Is there some way to do this?  Is the Application class involved in doing this in some way?  What methods can I override to get at the Activity instance after it's been created?</p>

答:
Ok, just an idea - in your app you can create a base activity class so all the rest of activities are subclassed from that base activity. Then in the onCreate() callback you may notify some listener instance about the fact of a new app activity instance creation:

```<code>public class BaseActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // put the code to notify a listener here
    }

}

public class YourWorkingActivity extends BaseActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ...
    }
}
</code>```

If you use a ListActivity (that is common for an average Android app), then you should also create a similar BaseListActivity for it.

Most likely the best candidate for a listener would be an Application subclass since it is guaranteed by the OS that is will be created before any Activity will be instantiated.

Warning: you should avoid keeping a strong reference to an Activity in the listener since it will create a memory leak when the OS will try to kill that Activity (as a part of the Activity or Process life-cycle). Probably use WeakReference for this.

ContentLicense: CC BY-SA 2.5

Body:
Ok, just an idea - in your app you can create a base activity class so all the rest of activities are subclassed from that base activity. Then in the onCreate() callback you may notify some listener instance about the fact of a new app activity instance creation:

public class BaseActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // put the code to notify a listener here
    }

}

public class YourWorkingActivity extends BaseActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ...
    }
}

If you use a ListActivity (that is common for an average Android app), then you should also create a similar BaseListActivity for it.

Most likely the best candidate for a listener would be an Application subclass since it is guaranteed by the OS that is will be created before any Activity will be instantiated.

Warning: you should avoid keeping a strong reference to an Activity in the listener since it will create a memory leak when the OS will try to kill that Activity (as a part of the Activity or Process life-cycle). Probably use WeakReference for this.


问:
WPF Treeview single objects as child nodes
I'm not quite sure if a TreeView is the thing I should use in my situation but it seems to be a logical choice. I'm trying to create a TreeView which gets populated by a list of ObjectA.

ObjectA looks like this:

```<code>public class ObjectA{
    public string DisplayName { get; set; }
    public ObjectB CurrentChild { get; set; }
    public ObjectB PreviousChild { get; set; }
}
</code>```

As you can see ObjectA contains two childs of ObjectB. One is the current child and the second one is the previous child.

ObjectB looks like this:

```<code>public class ObjectB{
    public string DisplayName { get; set; }
}
</code>```

How can I create a TreeView which Displays the "DisplayName" of ObjectA and if you expand ObjectA you can see two child nodes, one is the CurrentChild and the other one is the PreviousChild? I know I could create a List of ObjectB as property of ObjectA and store CurrentChild & PreviousChild inside of this list rather than using two properties and with such a list I could do easy stuff with an "HierarchicalDataTemplate" but I would like to know if it's possible to create a TreeView or another WPF control which can display these objects without altering the actual "Backend"-code. I would appreciate your help :)

答:
If you really don't want to change your object model, you could go for the HierarchicalDataTemplate too, and use a converter to the binding object:

```<code><TreeView ItemsSource="{Binding CollectionAObjects}">
  <TreeView.Resources>
    <HierarchicalDataTemplate ItemsSource="{Binding, Converter={StaticResource MyCollectionConverter}}" ...>
</code>```

The converter class should be something simple like...

```<code>public class MyCollectionConverter: IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        var result = new ObservableCollection<ObjectB>();
        result.Add(((ObjectA)value).CurrentChild);
        result.Add(((ObjectA)value).PreviousChild );
        return result;
   }

   public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
   {
       throw new NotImplementedException();
   }
}
</code>```

Don't forget to declare the namespace of your converter (if it is not in the same as your WPF View class) and add it on your local resources:

```<code><Window.Resources>
   <local:MyCollectionConverter x:Key="MyCollectionConverter" />
</Window.Resources>
</code>```

Body:
I'm not quite sure if a TreeView is the thing I should use in my situation but it seems to be a logical choice. I'm trying to create a TreeView which gets populated by a list of ObjectA.

ObjectA looks like this:

public class ObjectA{
    public string DisplayName { get; set; }
    public ObjectB CurrentChild { get; set; }
    public ObjectB PreviousChild { get; set; }
}

As you can see ObjectA contains two childs of ObjectB. One is the current child and the second one is the previous child.

ObjectB looks like this:

public class ObjectB{
    public string DisplayName { get; set; }
}

How can I create a TreeView which Displays the "DisplayName" of ObjectA and if you expand ObjectA you can see two child nodes, one is the CurrentChild and the other one is the PreviousChild? I know I could create a List of ObjectB as property of ObjectA and store CurrentChild & PreviousChild inside of this list rather than using two properties and with such a list I could do easy stuff with an "HierarchicalDataTemplate" but I would like to know if it's possible to create a TreeView or another WPF control which can display these objects without altering the actual "Backend"-code. I would appreciate your help :)

Body:
If you really don't want to change your object model, you could go for the HierarchicalDataTemplate too, and use a converter to the binding object:

<TreeView ItemsSource="{Binding CollectionAObjects}">
  <TreeView.Resources>
    <HierarchicalDataTemplate ItemsSource="{Binding, Converter={StaticResource MyCollectionConverter}}" ...>

The converter class should be something simple like...

public class MyCollectionConverter: IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        var result = new ObservableCollection<ObjectB>();
        result.Add(((ObjectA)value).CurrentChild);
        result.Add(((ObjectA)value).PreviousChild );
        return result;
   }

   public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
   {
       throw new NotImplementedException();
   }
}

Don't forget to declare the namespace of your converter (if it is not in the same as your WPF View class) and add it on your local resources:

<Window.Resources>
   <local:MyCollectionConverter x:Key="MyCollectionConverter" />
</Window.Resources>


问:
How to translate the Nation name into the current culture?
I've a List of Nations that's scraped from the web, this is returned in english. I saved each Nation inside a list like this:

```<code>List<Nation> Nations { get; set; } = new List<Nation>();
</code>```

where Nation have this implementation:

```<code>public Nation
{
    public string Name { get; set; }
    public string Link { get; set; }
}
</code>```

the property Name contains the name of the Nation in English, so essentially I'll get something similar to:

```<code>England
Italy
France
...
</code>```

I'm looking for a way to translate the name of each item of the list Nations in the current culture, so suppose that the current software language is italian:

```<code>Thread.CurrentThread.CurrentCulture = Thread.CurrentThread.CurrentUICulture = CultureInfo.CreateSpecificCulture("it");
</code>```

how can I translate all the nations in italian language?

I doesn't found any method in .NET framework that allow this in a simple way like:

```<code>//Get the current language of the app
var language = Thread.CurrentThread.CurrentCulture;

//Iterate through all items of the list and change the language
foreach(var nation in nations)
{
    nation.Name = GetTranslatedName(nation.Name);
}
</code>```

any suggestions? Ideas?

Thanks.

答:
You can try Google Translate:

Pass language pair as en|it

```<code>public string GoogleTranslateText(string textToTranslate, string languagePair)
{
    string url = String.Format("http://www.google.com/translate_t?hl=en&ie=UTF8&text={0}&langpair={1}", textToTranslate, languagePair);
    WebClient webClient = new WebClient();
    webClient.Encoding = System.Text.Encoding.UTF8;
    string translatedText = webClient.DownloadString(url);
    translatedText = translatedText.Substring(translatedText.IndexOf("<span title=\"") + "<span title=\"".Length);
    translatedText = translatedText.Substring(translatedText.IndexOf(">") + 1);
    translatedText = translatedText.Substring(0, translatedText.IndexOf("</span>"));
    return translatedText.Trim();
}
</code>```

Body:
I've a List of Nations that's scraped from the web, this is returned in english. I saved each Nation inside a list like this:

List<Nation> Nations { get; set; } = new List<Nation>();

where Nation have this implementation:

public Nation
{
    public string Name { get; set; }
    public string Link { get; set; }
}

the property Name contains the name of the Nation in English, so essentially I'll get something similar to:

England
Italy
France
...

I'm looking for a way to translate the name of each item of the list Nations in the current culture, so suppose that the current software language is italian:

Thread.CurrentThread.CurrentCulture = Thread.CurrentThread.CurrentUICulture = CultureInfo.CreateSpecificCulture("it");

how can I translate all the nations in italian language?

I doesn't found any method in .NET framework that allow this in a simple way like:

//Get the current language of the app
var language = Thread.CurrentThread.CurrentCulture;

//Iterate through all items of the list and change the language
foreach(var nation in nations)
{
    nation.Name = GetTranslatedName(nation.Name);
}

any suggestions? Ideas?

Thanks.

Body:
You can try Google Translate:

Pass language pair as en|it

public string GoogleTranslateText(string textToTranslate, string languagePair)
{
    string url = String.Format("http://www.google.com/translate_t?hl=en&ie=UTF8&text={0}&langpair={1}", textToTranslate, languagePair);
    WebClient webClient = new WebClient();
    webClient.Encoding = System.Text.Encoding.UTF8;
    string translatedText = webClient.DownloadString(url);
    translatedText = translatedText.Substring(translatedText.IndexOf("<span title=\"") + "<span title=\"".Length);
    translatedText = translatedText.Substring(translatedText.IndexOf(">") + 1);
    translatedText = translatedText.Substring(0, translatedText.IndexOf("</span>"));
    return translatedText.Trim();
}


问:
Bracket notation property accessor for arrays
In Typescript (and Javascript for that matter), you can access an object's properties using the dot notation or the bracket notation:

```<code>object.property
object['property']
</code>```

Using a concrete example for the latter:

```<code>const user = {
    firstName: 'John',
    lastName: 'Doe'
}
const prop = 'firstName';
console.log(user[prop]);  //"John"
</code>```

My question is if/how bracket notation can be used for array properties where the value in the bracket is a path to an array.  Here is an example:

```<code>const user = {
    firstName: 'John',
    lastName: 'Doe',
    nicknames: [
        { id: 1, value: 'Johnny'},
        { id: 2, value: 'JD'},
        { id: 3, value: 'Dude'}
    ]
}
const prop = 'nicknames[2].value';
console.log(user[prop]);
</code>```

My goal with the console.log() would be to print JD, but this example would fail because there is, of course, no property of user called nicknames[2].value;

How can I use bracket notation in this manner with array properties?

答:
If you do not fancy including lodash for a single function then you might consider adding a function onto your object which provides this functionality.

I have provided a snippet with an example which is able to use the type of prop string that you specified in your question

const user = {
    firstName: 'John',
    lastName: 'Doe',
    nicknames: [
        { id: 1, value: 'Johnny'},
        { id: 2, value: 'JD'},
        { id: 3, value: 'Dude'}
    ],
    byProp (path) {
      return path.split(/\].|\]\[|\[|\./) // split on [] or .
                 .map( el => el.replace(/\]$/,'')) // remove any trailing ']'
                 // loop over split-string to get element
                 // return undefined if the property does not exist
                 .reduce( (obj, el) => obj? obj[el]:undefined, this);
    }
}

console.log(user.byProp('nicknames[2].value'));
console.log(user.byProp('nicknames[1][value]'));
console.log(user.byProp('firstName'));
console.log(user.byProp('firstName.undefined'));```

Body:
In Typescript (and Javascript for that matter), you can access an object's properties using the dot notation or the bracket notation:

object.property
object['property']

Using a concrete example for the latter:

const user = {
    firstName: 'John',
    lastName: 'Doe'
}
const prop = 'firstName';
console.log(user[prop]);  //"John"

My question is if/how bracket notation can be used for array properties where the value in the bracket is a path to an array.  Here is an example:

const user = {
    firstName: 'John',
    lastName: 'Doe',
    nicknames: [
        { id: 1, value: 'Johnny'},
        { id: 2, value: 'JD'},
        { id: 3, value: 'Dude'}
    ]
}
const prop = 'nicknames[2].value';
console.log(user[prop]);

My goal with the console.log() would be to print JD, but this example would fail because there is, of course, no property of user called nicknames[2].value;

How can I use bracket notation in this manner with array properties?


问:
Go race condition when closing a Go channel
The following Go code example has a Race condition between the line c <- byte(0) and close(c). It is signaled when the code is run with go test -race.

```<code>func TestRace(t *testing.T) {
    var c = make(chan byte, 20)
    go func() {
        defer func() {
            if r := recover(); r == nil {
                t.Error("expected panic error")
            }
        }()
        for i := 0; i < 25; i++ {
            c <- byte(0)
        }
        t.Error("expected a panic")
    }()
    close(c)
}
</code>```

How can I avoid this race condition ?

Edit: based on Icza suggestion in his comments, here is the solution:

```<code>func TestRace(t *testing.T) {
    var c = make(chan byte, 20)
    var done = make(chan struct{})
    go func() {
        for i := 0; i < 25; i++ {
            select{
            case c <- byte(0):
            case <-done:
                close(c)
                return
        }
    }()
    close(done)
}
</code>```

This won't have a race condition and will be clean. It's a stupid simple example. I was told the select adds an overhead, but I didn't look into it because it isn't relevant in my use case.

答:
Normally the goroutine that sends values on a channel is responsible to close it. Closing a channel is basically a signal that no more values will (can) be sent on it.

You are not doing this: your new goroutine is the one sending values on it, and your other goroutine is the one closing it.

To get rid of the race condition, simply use the channels as they were intended to: move the close(c) call to the goroutine that sends values on it, e.g.:

```<code>go func() {
    defer func() {
        if r := recover(); r == nil {
            fmt.Println("expected panic error")
        }
    }()
    for i := 0; i < 25; i++ {
        c <- byte(0)
    }
    close(c)
    fmt.Println("expected a panic")
}()
for x := range c {
    fmt.Println("Received:", x)
}
</code>```

Try it on the Go Playground.

Body:
The following Go code example has a Race condition between the line c <- byte(0) and close(c). It is signaled when the code is run with go test -race.

func TestRace(t *testing.T) {
    var c = make(chan byte, 20)
    go func() {
        defer func() {
            if r := recover(); r == nil {
                t.Error("expected panic error")
            }
        }()
        for i := 0; i < 25; i++ {
            c <- byte(0)
        }
        t.Error("expected a panic")
    }()
    close(c)
}

How can I avoid this race condition ?

Edit: based on Icza suggestion in his comments, here is the solution:

func TestRace(t *testing.T) {
    var c = make(chan byte, 20)
    var done = make(chan struct{})
    go func() {
        for i := 0; i < 25; i++ {
            select{
            case c <- byte(0):
            case <-done:
                close(c)
                return
        }
    }()
    close(done)
}

This won't have a race condition and will be clean. It's a stupid simple example. I was told the select adds an overhead, but I didn't look into it because it isn't relevant in my use case.

Body:
Normally the goroutine that sends values on a channel is responsible to close it. Closing a channel is basically a signal that no more values will (can) be sent on it.

You are not doing this: your new goroutine is the one sending values on it, and your other goroutine is the one closing it.

To get rid of the race condition, simply use the channels as they were intended to: move the close(c) call to the goroutine that sends values on it, e.g.:

go func() {
    defer func() {
        if r := recover(); r == nil {
            fmt.Println("expected panic error")
        }
    }()
    for i := 0; i < 25; i++ {
        c <- byte(0)
    }
    close(c)
    fmt.Println("expected a panic")
}()
for x := range c {
    fmt.Println("Received:", x)
}

Try it on the Go Playground.


问:
Merge two array of objects with same keys, some object won't have the same value?

I want to merge two arrays of objects. The keys are the same but the values might not always be the same.

Any solution is appreciated preferably in javascript, but a python solution is fine as well.

Here is the sample data:

```<code>var g= [
    { id: 36, name: 'AAA', goal: 'yes' , 'random':27},
    { id: 40, name: 'BBB', goal: 'yes' },
    { id: 39, name: 'JJJ', goal: 'yes' },
    { id: 27, name: 'CCC', goal: 'yes' , lag: "23.3343"}];

var c= [
    { id: 36, name: 'AAA', goal: 'yes', color:"purple" },
    { id: 40, name: 'BBB', circle: 'yes', color:"purple" },
    { id: 100, name: 'JJJ', circle: 'yes'} ];
</code>```

      My expected output should be :

```<code> var finalData = [{
 { id: 36, name: 'AAA', goal: 'yes' ,'random':27, color:"purple"},
 { id: 40, name: 'BBB', circle: 'yes', color:"purple"},
 { id: 39, name: 'JJJ', goal: 'yes' },
 { id: 27, name: 'CCC', goal: 'yes' ,lag: "23.3343"},
 { id: 100, name: 'JJJ', circle: 'yes' }

  }]
</code>```

Here is my current code, it works to some degree but it doesn't add keys it might have missed.

```<code>var finalData = [];
for(var i in g){
   var shared = false;
   for (var j in c)
       if (c[j].name == g[i].name) {
           shared = true;
           break;
       }
   if(!shared) finalData.push(g[i])
}
finalData = finalData.concat(c);

finalData
</code>```

答:
This can be easily achieved by underscore functions _.uniq and _.union.

Just use this:

```<code>var finalData = _.uniq(_.union(c, g),  function (ele)  {
                    return ele.id
                })
</code>```

This will return you what you are looking for.

Body:
I want to merge two arrays of objects. The keys are the same but the values might not always be the same.

Any solution is appreciated preferably in javascript, but a python solution is fine as well.

Here is the sample data:

var g= [
    { id: 36, name: 'AAA', goal: 'yes' , 'random':27},
    { id: 40, name: 'BBB', goal: 'yes' },
    { id: 39, name: 'JJJ', goal: 'yes' },
    { id: 27, name: 'CCC', goal: 'yes' , lag: "23.3343"}];

var c= [
    { id: 36, name: 'AAA', goal: 'yes', color:"purple" },
    { id: 40, name: 'BBB', circle: 'yes', color:"purple" },
    { id: 100, name: 'JJJ', circle: 'yes'} ];

      My expected output should be :

 var finalData = [{
 { id: 36, name: 'AAA', goal: 'yes' ,'random':27, color:"purple"},
 { id: 40, name: 'BBB', circle: 'yes', color:"purple"},
 { id: 39, name: 'JJJ', goal: 'yes' },
 { id: 27, name: 'CCC', goal: 'yes' ,lag: "23.3343"},
 { id: 100, name: 'JJJ', circle: 'yes' }

  }]

Here is my current code, it works to some degree but it doesn't add keys it might have missed.

var finalData = [];
for(var i in g){
   var shared = false;
   for (var j in c)
       if (c[j].name == g[i].name) {
           shared = true;
           break;
       }
   if(!shared) finalData.push(g[i])
}
finalData = finalData.concat(c);

finalData

Body:
This can be easily achieved by underscore functions _.uniq and _.union.

Just use this:

var finalData = _.uniq(_.union(c, g),  function (ele)  {
                    return ele.id
                })

This will return you what you are looking for.


问:
Schema qualified tables with SQLAlchemy, SQLite and Postgresql?
I have a Pylons project and a SQLAlchemy model that implements schema qualified tables:

```<code>class Hockey(Base):
    __tablename__ = "hockey"
    __table_args__ = {'schema':'winter'}
    hockey_id = sa.Column(sa.types.Integer, sa.Sequence('score_id_seq', optional=True), primary_key=True)
    baseball_id = sa.Column(sa.types.Integer, sa.ForeignKey('summer.baseball.baseball_id'))
</code>```

This code works great with Postgresql but fails when using SQLite on table and foreign key names (due to SQLite's lack of schema support)

sqlalchemy.exc.OperationalError: (OperationalError) unknown database "winter" 'PRAGMA "winter".table_info("hockey")' ()

I'd like to continue using SQLite for dev and testing.

Is there a way of have this fail gracefully on SQLite?

答:
I'd like to continue using SQLite for
  dev and testing.

Is there a way of have this fail
  gracefully on SQLite?

It's hard to know where to start with that kind of question. So . . .

Stop it. Just stop it.

There are some developers who don't have the luxury of developing on their target platform. Their life is a hard one--moving code (and sometimes compilers) from one environment to the other, debugging twice (sometimes having to debug remotely on the target platform), gradually coming to an awareness that the gnawing in their gut is actually the start of an ulcer.

Install PostgreSQL.

When you can use the same database environment for development, testing, and deployment, you should.

Not to mention the QA team. Why on earth are they testing stuff they're not going to ship? If you're deploying on PostgreSQL, assure the quality of your work on PostgreSQL.

Seriously.

Body:
I have a Pylons project and a SQLAlchemy model that implements schema qualified tables:

class Hockey(Base):
    __tablename__ = "hockey"
    __table_args__ = {'schema':'winter'}
    hockey_id = sa.Column(sa.types.Integer, sa.Sequence('score_id_seq', optional=True), primary_key=True)
    baseball_id = sa.Column(sa.types.Integer, sa.ForeignKey('summer.baseball.baseball_id'))

This code works great with Postgresql but fails when using SQLite on table and foreign key names (due to SQLite's lack of schema support)

sqlalchemy.exc.OperationalError: (OperationalError) unknown database "winter" 'PRAGMA "winter".table_info("hockey")' ()

I'd like to continue using SQLite for dev and testing.

Is there a way of have this fail gracefully on SQLite?


问:
ES6 Iterate over class methods
Given this class; how would i iterate over the methods that it includes?

```<code>class Animal {
    constructor(type){
        this.animalType = type;
    }
    getAnimalType(){
        console.log('this.animalType: ', this.animalType );
    }
}

let cat = window.cat = new Animal('cat')
</code>```

What I have tried is the following with no success:

```<code>for (var each in Object.getPrototypeOf(cat) ){
    console.log(each);
}
</code>```

答:
i know, i know, but hey...

const isGetter = ( x, name ) => ( Object.getOwnPropertyDescriptor( x, name ) || {} ).get
const isFunction = ( x, name ) => typeof x[ name ] === "function";
const deepFunctions = x =>
  x && x !== Object.prototype &&
  Object.getOwnPropertyNames( x )
    .filter( name => isGetter( x, name ) || isFunction( x, name ) )
    .concat( deepFunctions( Object.getPrototypeOf( x ) ) || [] );
const distinctDeepFunctions = x => Array.from( new Set( deepFunctions( x ) ) );
const userFunctions = x => distinctDeepFunctions( x ).filter( name => name !== "constructor" && !~name.indexOf( "__" ) );

// example usage

class YourObject {
   hello() { return "uk"; }
   goodbye() { return "eu"; }
}

class MyObject extends YourObject {
   hello() { return "ie"; }
   get when() { return "soon"; }
}

const obj = new MyObject();
console.log( userFunctions( obj ) ); // [ "hello", "when", "goodbye" ]```

Title: ES6 Iterate over class methods

Body:
Given this class; how would i iterate over the methods that it includes?

class Animal {
    constructor(type){
        this.animalType = type;
    }
    getAnimalType(){
        console.log('this.animalType: ', this.animalType );
    }
}

let cat = window.cat = new Animal('cat')

What I have tried is the following with no success:

for (var each in Object.getPrototypeOf(cat) ){
    console.log(each);
}


问:
Handheld Android 2D Barcode Scanner - How to access the scanner and read data
I'm busy working with an android device that has a physical barcode scanner built in. I need to access this scanner and scan a PDF417 barcode (like a drivers license).

I found that this to some extent registered as a keyboard, meaning I can get some form of input through the override onKeyDown events. Though, when I try and read this data, is comes back as an encoded string or as a replacement character (special character or the diamond with the question mark).

The code looks something like this:

What I need, is for the result to show me what the value is of the barcode I'm scanning.

This is what I'm currently getting:

答:
Watch carefully setting up your scanner.
The problem is not in the application.
In the scanner, you can still add a special of carriage so that the machine will trigger an event onKeyDown</p>


问:
Python Iterating over lists in lists with map()
So my intention is to iterate over lists in lists with map, filter and lambda
e.g.:

[ [33,3,3,0] , [34,1,0,4] ]  should result in [ [33,3,3] , [34,1,4] ]

```<code>   def no_zeros(lst):
      a=map(filter(lambda x:(y==0 for y in x) ,lst),lst)
      print (list(a))
      #(says that filter is not callable)
</code>```

I know that this code won't work but i do not know what exactly i do wrong since i'm still kind of new to lambda,etc.I already tried different stuff , like moving the filter after the lambda,but that did not seem to work either . Im gratefull for any kind of tipps or help.

答:
Here is one possibility:</p>

```<code>import itertools
a = [ [33,3,3,0] , [34,1,0,4] ]
list(map(list, map(filter, itertools.repeat(bool), a)))
# [[33, 3, 3], [34, 1, 4]]
</code>```

Body:
So my intention is to iterate over lists in lists with map, filter and lambda
e.g.:

[ [33,3,3,0] , [34,1,0,4] ]  should result in [ [33,3,3] , [34,1,4] ]

   def no_zeros(lst):
      a=map(filter(lambda x:(y==0 for y in x) ,lst),lst)
      print (list(a))
      #(says that filter is not callable)

I know that this code won't work but i do not know what exactly i do wrong since i'm still kind of new to lambda,etc.I already tried different stuff , like moving the filter after the lambda,but that did not seem to work either . Im gratefull for any kind of tipps or help.

Body:
Here is one possibility:

import itertools
a = [ [33,3,3,0] , [34,1,0,4] ]
list(map(list, map(filter, itertools.repeat(bool), a)))
# [[33, 3, 3], [34, 1, 4]]


问:
VBA - Pasting only specific columns from array
following a question I have asked recently I have created an array to copy data from one worksheet to another. My problem is that the array includes many columns I do not need in the new worksheet.

```<code>x = Sheets("Sheet1").Range("A1048576").End(xlUp).Row
Set my_range = Sheets("Sheet1").Range("A2:AM" & x)
DirArray = my_range

Sheets("Sheet2").Select

Set Destination = Range("A3")
Destination.Resize(UBound(DirArray, 1), UBound(DirArray, 2)).Value = DirArray
</code>```

This code copies all the data from the array but I only want specific columns from the array. How would I have to go about this to get only columns A:E, AA, L, M:K?

Any help is appreciated. Thanks in advance.

答:
Well if you are going to use arrays, then maybe something along these lines might help:

```<code>Sub foo()
    Dim ColumnAarray() As Variant
    Dim my_Arange As Range
    LastRow = Sheet1.Cells(Sheet1.Rows.Count, "A").End(xlUp).Row

    'Get one column's data
    Set my_Arange = Sheets("Sheet1").Range("A2:A" & LastRow) ' get specific column
    ReDim ColumnAarray(LastRow) 'Re size your array to fit data
    ColumnAarray = my_Arange 'add data to array
    ''
    ''Repeat the process to copy more columns

    ''
    Set Destination = Sheet2.Range("A3")
    Destination.Resize(UBound(ColumnAarray, 1), UBound(ColumnAarray, 2)).Value = ColumnAarray 'add column A to Range A3 on Sheet2
End Sub
</code>```

Or where you go about pasting the array values, you could change this to only paste specific columns from your original range... such as:

```<code>Sub foo()
    Dim ColumnAarray() As Variant
    Dim my_Arange As Range
    LastRow = Sheet1.Cells(Sheet1.Rows.Count, "A").End(xlUp).Row
    Set my_Arange = Sheets("Sheet1").Range("A2:AM" & LastRow) ' get specific range
    ReDim ColumnAarray(LastRow) 'Re size your array to fit data
    ColumnAarray = my_Arange 'add data to array

    For i = LBound(ColumnAarray) To UBound(ColumnAarray)
        Sheet2.Range("A" & i) = ColumnAarray(i, 1) 'paste first column from original range
        Sheet2.Range("B" & i) = ColumnAarray(i, 2) 'paste second column from original range into column B in Sheet 2
    Next i
End Sub
</code>```

Body:
following a question I have asked recently I have created an array to copy data from one worksheet to another. My problem is that the array includes many columns I do not need in the new worksheet.

x = Sheets("Sheet1").Range("A1048576").End(xlUp).Row
Set my_range = Sheets("Sheet1").Range("A2:AM" & x)
DirArray = my_range

Sheets("Sheet2").Select

Set Destination = Range("A3")
Destination.Resize(UBound(DirArray, 1), UBound(DirArray, 2)).Value = DirArray

This code copies all the data from the array but I only want specific columns from the array. How would I have to go about this to get only columns A:E, AA, L, M:K?

Any help is appreciated. Thanks in advance.

Body:
Well if you are going to use arrays, then maybe something along these lines might help:

Sub foo()
    Dim ColumnAarray() As Variant
    Dim my_Arange As Range
    LastRow = Sheet1.Cells(Sheet1.Rows.Count, "A").End(xlUp).Row

    'Get one column's data
    Set my_Arange = Sheets("Sheet1").Range("A2:A" & LastRow) ' get specific column
    ReDim ColumnAarray(LastRow) 'Re size your array to fit data
    ColumnAarray = my_Arange 'add data to array
    ''
    ''Repeat the process to copy more columns

    ''
    Set Destination = Sheet2.Range("A3")
    Destination.Resize(UBound(ColumnAarray, 1), UBound(ColumnAarray, 2)).Value = ColumnAarray 'add column A to Range A3 on Sheet2
End Sub

Or where you go about pasting the array values, you could change this to only paste specific columns from your original range... such as:

Sub foo()
    Dim ColumnAarray() As Variant
    Dim my_Arange As Range
    LastRow = Sheet1.Cells(Sheet1.Rows.Count, "A").End(xlUp).Row
    Set my_Arange = Sheets("Sheet1").Range("A2:AM" & LastRow) ' get specific range
    ReDim ColumnAarray(LastRow) 'Re size your array to fit data
    ColumnAarray = my_Arange 'add data to array

    For i = LBound(ColumnAarray) To UBound(ColumnAarray)
        Sheet2.Range("A" & i) = ColumnAarray(i, 1) 'paste first column from original range
        Sheet2.Range("B" & i) = ColumnAarray(i, 2) 'paste second column from original range into column B in Sheet 2
    Next i
End Sub


答:
The thing is that map expects a function/callable as a first argument but you're giving it the result of a filter.

You can fix this by applying filter to the sublists iterated by map:

```<code>def no_zeros(lst):
    a = map(lambda x: filter(lambda y: y != 0, x), lst)
    print(list(a))
</code>```

By the way, you can do the same thing with list comprehensions:

```<code>def no_zeros(lst):
    a = [[y for y in x if y != 0] for x in lst]
    print(a)
</code>```

Title: Python Iterating over lists in lists with map()

Body:
The thing is that map expects a function/callable as a first argument but you're giving it the result of a filter.

You can fix this by applying filter to the sublists iterated by map:

def no_zeros(lst):
    a = map(lambda x: filter(lambda y: y != 0, x), lst)
    print(list(a))

By the way, you can do the same thing with list comprehensions:

def no_zeros(lst):
    a = [[y for y in x if y != 0] for x in lst]
    print(a)


问:
How do I validate and create a new model for each line in a text area
Users have many websites, and Websites have many Keywords. (Keywords being nested resources of the Websites resource)

Right now, with the default scaffolding setup, it's very tedious to add many keywords at once. I'd like a text area instead of a text field that allows users to type many keywords, each on their own line, and submit them all at once. The only input on the form is for the keyword's "text" column.

How can I do this?

I can figure out things like params[:keyword][:text].split("\r\n").each do |text|, but I'm not sure how to interact it with the Rails form.

```<code><%= form_for [@website, @keyword] do |f| %>
  <% if @keyword.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(@keyword.errors.count, "error") %> prohibited this keyword from being saved:</h2>

      <ul>
      <% @keyword.errors.full_messages.each do |msg| %>
        <li><%= msg %></li>
      <% end %>
      </ul>
    </div>
  <% end %>

  <div class="field">
    <%= f.label :text %><br />
    <%= f.text_area :text %>
  </div>

  <div class="actions">
    <%= f.submit %>
  </div>
<% end %>
</code>```

答: If you want keywords to use tag like UI, use an input with jQuery Tag it! You can then parse it with some model callbacks to be suitable for has_many relationship or go with a full tags like solution.</p>

Body:
Users have many websites, and Websites have many Keywords. (Keywords being nested resources of the Websites resource)

Right now, with the default scaffolding setup, it's very tedious to add many keywords at once. I'd like a text area instead of a text field that allows users to type many keywords, each on their own line, and submit them all at once. The only input on the form is for the keyword's "text" column.

How can I do this?

I can figure out things like params[:keyword][:text].split("\r\n").each do |text|, but I'm not sure how to interact it with the Rails form.

<%= form_for [@website, @keyword] do |f| %>
  <% if @keyword.errors.any? %>

<%= pluralize(@keyword.errors.count, "error") %> prohibited this keyword from being saved:

      <% @keyword.errors.full_messages.each do |msg| %>

<%= msg %>

      <% end %>

  <% end %>

    <%= f.label :text %>

    <%= f.text_area :text %>

    <%= f.submit %>

<% end %>


问:
What happens if file_put_contents can't lock?
Assume multiple people write to the same file at the same time with the command

```<code>file_put_contents('file.txt', 'This is an example', LOCK_EX);
</code>```

would it be possible that one person might not be able to write to the file, because the function file_put_contents had to wait too long for the locked file? Would the function throw an exception, or would you just end up with a error like this:

"Fatal error: Maximum execution time of .. seconds exceeded"

答:
That error looks like execution timeout for the script (time taking to execute the script is beyond the configured value as process is waiting to accurire the ) , there will be default timeout you can check the default max-execution-time in php.ini file

```<code>max-execution-time=30
</code>```

you can tune the timeout and check
http://php.net/manual/en/function.set-time-limit.php or max-execution-time

Body:
Assume multiple people write to the same file at the same time with the command

file_put_contents('file.txt', 'This is an example', LOCK_EX);

would it be possible that one person might not be able to write to the file, because the function file_put_contents had to wait too long for the locked file? Would the function throw an exception, or would you just end up with a error like this:

"Fatal error: Maximum execution time of .. seconds exceeded"

Body:
That error looks like execution timeout for the script (time taking to execute the script is beyond the configured value as process is waiting to accurire the ) , there will be default timeout you can check the default max-execution-time in php.ini file

max-execution-time=30

you can tune the timeout and check
http://php.net/manual/en/function.set-time-limit.php or max-execution-time