问:
Flutter TextField TextFieldController setState - position of cursor changes
I recently wrote a test program that I needed that is essentially a CRUD program. I needed to handle this differently to other similar programs that I have written, because I normally use a stateful FAB widget, and don't have to setState() to enable and disable the FAB. In this test program I didn't want to use the custom FAB, and used the standard FAB. I found that whenever I had to enable or disable the FAB because of a change to a TextField, that this required a setState(), and after the build, the cursor for the TextField that was being edited had repositioned. I don't know why that happens, because I had not recreated the Widgets. The only solution that I could come up with to handle that issue was fairly messy and required saving the Widget position in the List of TextField and also save the Selection, and then after the build resetting the Selection to the saved Selection.

What I need to achieve is for the FAB to be only enabled when data has changed. Obviously this can vary with every key entry.

I presume I'm not handling this in the optimal way. How is this handled so that the cursor position remains as it was prior to the build?

----- Have Now Added Code below ----

```<code>import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';

void main() => runApp(MyApp());

//=====================================================================================

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Test Widgets',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: HomePage(title: 'Test Widgets'),
    );
  }
}

//=====================================================================================

class HomePage extends StatefulWidget {
  HomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _HomePageState createState() => _HomePageState();
}

//=====================================================================================

class _HomePageState extends State<HomePage> {
  bool _tfDataHasChanged = false;
  bool _tfInitialized = false;
  bool _tfSaveSelection = false;
  int _iNdxWidgetChanged = -1;
  List<String> _lsOldData = ['Row 1', 'Row 2', 'Row 3', 'Row 4'];
  List<String> _lsNewData = ['Row 1', 'Row 2', 'Row 3', 'Row 4'];
  List<TextField> _lwTextFields;
  TextSelection _wTextSelection;

//-------------------------------------------------------------------------------------

  @override
  void dispose() {
    for (int iNdxWidget = 0;
        _lwTextFields != null && iNdxWidget < _lwTextFields.length;
        iNdxWidget++) {
      _lwTextFields[iNdxWidget].focusNode.removeListener(() {
        _fnFocusChanged();
      });
      _lwTextFields[iNdxWidget]?.controller?.dispose();
      _lwTextFields[iNdxWidget]?.focusNode?.dispose();
    }
    super.dispose();
  }

//-------------------------------------------------------------------------------------

  @override
  Widget build(BuildContext context) {
    _tfInitialized = false;
    SchedulerBinding.instance.addPostFrameCallback((_) => _fnOnBuildComplete());
    if (_lwTextFields == null) {
      _fnCreateAllWidgets();
    }
    List<Widget> lwDisplay = _fnCreateDisplay();
    return Scaffold(
      appBar: AppBar(
          flexibleSpace: SafeArea(
        child: _fnCreateAppBarWidgets(),
      )),
      body: SingleChildScrollView(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: lwDisplay,
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _tfDataHasChanged ? _fnUpdateData : null,
        tooltip: 'Update',
        backgroundColor: _tfDataHasChanged ? Colors.blue : Colors.grey,
        child: Icon(Icons.done),
      ),
    );
  }

//-------------------------------------------------------------------------------------

  _fnOnBuildComplete() {
    _tfInitialized = true;
    if (_tfSaveSelection && _iNdxWidgetChanged >= 0) {
      _lwTextFields[_iNdxWidgetChanged].controller.selection = _wTextSelection;
    }
  }

//-------------------------------------------------------------------------------------

  void _fnCreateAllWidgets() {
    _lwTextFields = List(_lsNewData.length);
    for (int iNdxWidget = 0; iNdxWidget < _lwTextFields.length; iNdxWidget++) {
      _fnCreateTextField(iNdxWidget);
    }
  }

//-------------------------------------------------------------------------------------

  void _fnCreateTextField(int iNdxWidget) {
    TextEditingController wController = TextEditingController();

    FocusNode wFocusNode = FocusNode();
    wFocusNode.addListener(() => _fnFocusChanged());

    _lwTextFields[iNdxWidget] = TextField(
      autofocus: false, //(iNdxWidget == 0),
      autocorrect: false,
      enabled: true,
      keyboardType: TextInputType.text,
      maxLength: 25,
      controller: wController,
      focusNode: wFocusNode,
      textInputAction: TextInputAction.next /* TYPE OF ACTION KEY */,
      onSubmitted: ((v) => _fnSetNextFocus(iNdxWidget)),
      onChanged: (text) => _fnTextListener(iNdxWidget, text),
      decoration: _fnCreateInputDecoration(
          'Text Field Number ${iNdxWidget + 1}', 'Enter Data'),
      style: _fnCreateWidgetTextStyle(Colors.blue[700]),
    );
  }

//-------------------------------------------------------------------------------------

  _fnTextListener(int iNdxWidget, String sText) {
    if (_tfInitialized) {
      _lsNewData[iNdxWidget] = sText;
      _fnCheckIfDataHasChanged(
          iNdxWidget) /* ENABLE OR DISABLE SUBMIT BUTTON */;
    }
  }

//-------------------------------------------------------------------------------------

  _fnSetNextFocus(int iNdxWidget) {
    if (_lwTextFields[iNdxWidget].focusNode.hasFocus) {
      _lwTextFields[iNdxWidget].focusNode.unfocus();
      if (iNdxWidget + 1 < _lwTextFields.length) {
        _lwTextFields[iNdxWidget + 1]?.focusNode?.requestFocus();
      }
    }
  }

//-------------------------------------------------------------------------------------

  InputDecoration _fnCreateInputDecoration(String sHeading, String sHint) {
    return InputDecoration(
      labelText: sHeading,
      hintText: sHint,
      border: OutlineInputBorder(borderRadius: BorderRadius.circular(20.0)),
    );
  }

//-------------------------------------------------------------------------------------

  TextStyle _fnCreateWidgetTextStyle(Color color) {
    return TextStyle(
      fontSize: 14.0,
      color: color,
    );
  }

//-------------------------------------------------------------------------------------

  List<Widget> _fnCreateDisplay() {
    List<Widget> lwDisplay = List((_lwTextFields.length * 2) + 2);
    lwDisplay[0] = SizedBox(height: 10);
    int iNdxDisplay = 1;
    for (int iNdxWidget = 0; iNdxWidget < _lwTextFields.length; iNdxWidget++) {
      _lwTextFields[iNdxWidget].controller.text = _lsNewData[iNdxWidget];
      lwDisplay[iNdxDisplay++] = _lwTextFields[iNdxWidget];
      lwDisplay[iNdxDisplay++] =
          SizedBox(height: iNdxDisplay < lwDisplay.length - 2 ? 10 : 80);
    }
    lwDisplay[lwDisplay.length - 1] = Divider(color: Colors.black, height: 2);
    return lwDisplay;
  }

//-------------------------------------------------------------------------------------

  _fnUpdateData() {
    for (int iNdxWidget = 0; iNdxWidget < _lsNewData.length; iNdxWidget++) {
      if (_lsNewData[iNdxWidget] != _lsOldData[iNdxWidget]) {
        _lsOldData[iNdxWidget] = _lsNewData[iNdxWidget];
      }
    }
    _fnCheckIfDataHasChanged(-1);
  }

//-------------------------------------------------------------------------------------

  _fnCheckIfDataHasChanged(int iNdxWidgetChanged) {
    bool tfChanged = false /* INIT */;
    for (int iNdxWidgetTest = 0;
        !tfChanged && iNdxWidgetTest < _lsNewData.length;
        iNdxWidgetTest++) {
      tfChanged = _lsNewData[iNdxWidgetTest] != _lsOldData[iNdxWidgetTest];
    }
    if (iNdxWidgetChanged >= 0) {
      _iNdxWidgetChanged = iNdxWidgetChanged;
      _wTextSelection = _lwTextFields[iNdxWidgetChanged].controller.selection;
    }
    if (tfChanged != _tfDataHasChanged) {
      setState(() => _tfDataHasChanged = tfChanged) /* WE NEED TO ENABLE FAB */;
    }
  }

//-------------------------------------------------------------------------------------

  Row _fnCreateAppBarWidgets() {
    IconData wIconData =
        _tfSaveSelection ? Icons.check_box : Icons.check_box_outline_blank;
    Color wColor = _tfSaveSelection ? Colors.blue[900] : Colors.grey[600];
    IconButton wIconButton = IconButton(
        icon: Icon(wIconData),
        color: wColor,
        onPressed: _fnCheckboxChanged,
        iconSize: 40);
    return Row(children: <Widget>[
      SizedBox(width: 10),
      Text('Save\nSelection', textAlign: TextAlign.center),
      wIconButton,
      SizedBox(width: 30),
      Text('Test TextField')
    ]);
  }

//-------------------------------------------------------------------------------------

  _fnFocusChanged() {
    for (int iNdxWidget = 0; iNdxWidget < _lwTextFields.length; iNdxWidget++) {
      if (_lwTextFields[iNdxWidget].focusNode.hasFocus) {
        _iNdxWidgetChanged = iNdxWidget;
        _wTextSelection = _lwTextFields[iNdxWidget].controller.selection;
        return;
      }
    }
  }

//-------------------------------------------------------------------------------------

  void _fnCheckboxChanged() {
    _tfSaveSelection = !_tfSaveSelection;
    if (!_tfSaveSelection) {
      _iNdxWidgetChanged = -1;
    }
    setState(() {});
  }
}

</code>```

-------- Have added key to TextField, but issue persists ---------

```<code>  key: ValueKey<int>(iNdxWidget),
</code>```

答:
I hope these functions might help you </p>

```<code>  void updateText(String text) {
    if (text != null) {
      this.text = _applyMask(mask, text);
    } else {
      this.text = '';
    }

    _lastUpdatedText = this.text;
  }

  void updateMask(String mask, {bool moveCursorToEnd = true}) {
    this.mask = mask;
    updateText(text);

    if (moveCursorToEnd) {
      this.moveCursorToEnd();
    }
  }

  void moveCursorToEnd() {
    final String text = _lastUpdatedText;
    selection =
        TextSelection.fromPosition(TextPosition(offset: (text ?? '').length));
  }
</code>```

Body:
I recently wrote a test program that I needed that is essentially a CRUD program. I needed to handle this differently to other similar programs that I have written, because I normally use a stateful FAB widget, and don't have to setState() to enable and disable the FAB. In this test program I didn't want to use the custom FAB, and used the standard FAB. I found that whenever I had to enable or disable the FAB because of a change to a TextField, that this required a setState(), and after the build, the cursor for the TextField that was being edited had repositioned. I don't know why that happens, because I had not recreated the Widgets. The only solution that I could come up with to handle that issue was fairly messy and required saving the Widget position in the List of TextField and also save the Selection, and then after the build resetting the Selection to the saved Selection.

What I need to achieve is for the FAB to be only enabled when data has changed. Obviously this can vary with every key entry.

I presume I'm not handling this in the optimal way. How is this handled so that the cursor position remains as it was prior to the build?

----- Have Now Added Code below ----

import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';

void main() => runApp(MyApp());

//=====================================================================================

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Test Widgets',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: HomePage(title: 'Test Widgets'),
    );
  }
}

//=====================================================================================

class HomePage extends StatefulWidget {
  HomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _HomePageState createState() => _HomePageState();
}

//=====================================================================================

class _HomePageState extends State<HomePage> {
  bool _tfDataHasChanged = false;
  bool _tfInitialized = false;
  bool _tfSaveSelection = false;
  int _iNdxWidgetChanged = -1;
  List<String> _lsOldData = ['Row 1', 'Row 2', 'Row 3', 'Row 4'];
  List<String> _lsNewData = ['Row 1', 'Row 2', 'Row 3', 'Row 4'];
  List<TextField> _lwTextFields;
  TextSelection _wTextSelection;

//-------------------------------------------------------------------------------------

  @override
  void dispose() {
    for (int iNdxWidget = 0;
        _lwTextFields != null && iNdxWidget < _lwTextFields.length;
        iNdxWidget++) {
      _lwTextFields[iNdxWidget].focusNode.removeListener(() {
        _fnFocusChanged();
      });
      _lwTextFields[iNdxWidget]?.controller?.dispose();
      _lwTextFields[iNdxWidget]?.focusNode?.dispose();
    }
    super.dispose();
  }

//-------------------------------------------------------------------------------------

  @override
  Widget build(BuildContext context) {
    _tfInitialized = false;
    SchedulerBinding.instance.addPostFrameCallback((_) => _fnOnBuildComplete());
    if (_lwTextFields == null) {
      _fnCreateAllWidgets();
    }
    List<Widget> lwDisplay = _fnCreateDisplay();
    return Scaffold(
      appBar: AppBar(
          flexibleSpace: SafeArea(
        child: _fnCreateAppBarWidgets(),
      )),
      body: SingleChildScrollView(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: lwDisplay,
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _tfDataHasChanged ? _fnUpdateData : null,
        tooltip: 'Update',
        backgroundColor: _tfDataHasChanged ? Colors.blue : Colors.grey,
        child: Icon(Icons.done),
      ),
    );
  }

//-------------------------------------------------------------------------------------

  _fnOnBuildComplete() {
    _tfInitialized = true;
    if (_tfSaveSelection && _iNdxWidgetChanged >= 0) {
      _lwTextFields[_iNdxWidgetChanged].controller.selection = _wTextSelection;
    }
  }

//-------------------------------------------------------------------------------------

  void _fnCreateAllWidgets() {
    _lwTextFields = List(_lsNewData.length);
    for (int iNdxWidget = 0; iNdxWidget < _lwTextFields.length; iNdxWidget++) {
      _fnCreateTextField(iNdxWidget);
    }
  }

//-------------------------------------------------------------------------------------

  void _fnCreateTextField(int iNdxWidget) {
    TextEditingController wController = TextEditingController();

    FocusNode wFocusNode = FocusNode();
    wFocusNode.addListener(() => _fnFocusChanged());

    _lwTextFields[iNdxWidget] = TextField(
      autofocus: false, //(iNdxWidget == 0),
      autocorrect: false,
      enabled: true,
      keyboardType: TextInputType.text,
      maxLength: 25,
      controller: wController,
      focusNode: wFocusNode,
      textInputAction: TextInputAction.next /* TYPE OF ACTION KEY */,
      onSubmitted: ((v) => _fnSetNextFocus(iNdxWidget)),
      onChanged: (text) => _fnTextListener(iNdxWidget, text),
      decoration: _fnCreateInputDecoration(
          'Text Field Number ${iNdxWidget + 1}', 'Enter Data'),
      style: _fnCreateWidgetTextStyle(Colors.blue[700]),
    );
  }

//-------------------------------------------------------------------------------------

  _fnTextListener(int iNdxWidget, String sText) {
    if (_tfInitialized) {
      _lsNewData[iNdxWidget] = sText;
      _fnCheckIfDataHasChanged(
          iNdxWidget) /* ENABLE OR DISABLE SUBMIT BUTTON */;
    }
  }

//-------------------------------------------------------------------------------------

  _fnSetNextFocus(int iNdxWidget) {
    if (_lwTextFields[iNdxWidget].focusNode.hasFocus) {
      _lwTextFields[iNdxWidget].focusNode.unfocus();
      if (iNdxWidget + 1 < _lwTextFields.length) {
        _lwTextFields[iNdxWidget + 1]?.focusNode?.requestFocus();
      }
    }
  }

//-------------------------------------------------------------------------------------

  InputDecoration _fnCreateInputDecoration(String sHeading, String sHint) {
    return InputDecoration(
      labelText: sHeading,
      hintText: sHint,
      border: OutlineInputBorder(borderRadius: BorderRadius.circular(20.0)),
    );
  }

//-------------------------------------------------------------------------------------

  TextStyle _fnCreateWidgetTextStyle(Color color) {
    return TextStyle(
      fontSize: 14.0,
      color: color,
    );
  }

//-------------------------------------------------------------------------------------

  List<Widget> _fnCreateDisplay() {
    List<Widget> lwDisplay = List((_lwTextFields.length * 2) + 2);
    lwDisplay[0] = SizedBox(height: 10);
    int iNdxDisplay = 1;
    for (int iNdxWidget = 0; iNdxWidget < _lwTextFields.length; iNdxWidget++) {
      _lwTextFields[iNdxWidget].controller.text = _lsNewData[iNdxWidget];
      lwDisplay[iNdxDisplay++] = _lwTextFields[iNdxWidget];
      lwDisplay[iNdxDisplay++] =
          SizedBox(height: iNdxDisplay < lwDisplay.length - 2 ? 10 : 80);
    }
    lwDisplay[lwDisplay.length - 1] = Divider(color: Colors.black, height: 2);
    return lwDisplay;
  }

//-------------------------------------------------------------------------------------

  _fnUpdateData() {
    for (int iNdxWidget = 0; iNdxWidget < _lsNewData.length; iNdxWidget++) {
      if (_lsNewData[iNdxWidget] != _lsOldData[iNdxWidget]) {
        _lsOldData[iNdxWidget] = _lsNewData[iNdxWidget];
      }
    }
    _fnCheckIfDataHasChanged(-1);
  }

//-------------------------------------------------------------------------------------

  _fnCheckIfDataHasChanged(int iNdxWidgetChanged) {
    bool tfChanged = false /* INIT */;
    for (int iNdxWidgetTest = 0;
        !tfChanged && iNdxWidgetTest < _lsNewData.length;
        iNdxWidgetTest++) {
      tfChanged = _lsNewData[iNdxWidgetTest] != _lsOldData[iNdxWidgetTest];
    }
    if (iNdxWidgetChanged >= 0) {
      _iNdxWidgetChanged = iNdxWidgetChanged;
      _wTextSelection = _lwTextFields[iNdxWidgetChanged].controller.selection;
    }
    if (tfChanged != _tfDataHasChanged) {
      setState(() => _tfDataHasChanged = tfChanged) /* WE NEED TO ENABLE FAB */;
    }
  }

//-------------------------------------------------------------------------------------

  Row _fnCreateAppBarWidgets() {
    IconData wIconData =
        _tfSaveSelection ? Icons.check_box : Icons.check_box_outline_blank;
    Color wColor = _tfSaveSelection ? Colors.blue[900] : Colors.grey[600];
    IconButton wIconButton = IconButton(
        icon: Icon(wIconData),
        color: wColor,
        onPressed: _fnCheckboxChanged,
        iconSize: 40);
    return Row(children: <Widget>[
      SizedBox(width: 10),
      Text('Save\nSelection', textAlign: TextAlign.center),
      wIconButton,
      SizedBox(width: 30),
      Text('Test TextField')
    ]);
  }

//-------------------------------------------------------------------------------------

  _fnFocusChanged() {
    for (int iNdxWidget = 0; iNdxWidget < _lwTextFields.length; iNdxWidget++) {
      if (_lwTextFields[iNdxWidget].focusNode.hasFocus) {
        _iNdxWidgetChanged = iNdxWidget;
        _wTextSelection = _lwTextFields[iNdxWidget].controller.selection;
        return;
      }
    }
  }

//-------------------------------------------------------------------------------------

  void _fnCheckboxChanged() {
    _tfSaveSelection = !_tfSaveSelection;
    if (!_tfSaveSelection) {
      _iNdxWidgetChanged = -1;
    }
    setState(() {});
  }
}

-------- Have added key to TextField, but issue persists ---------

  key: ValueKey<int>(iNdxWidget),

Body:
I hope these functions might help you

  void updateText(String text) {
    if (text != null) {
      this.text = _applyMask(mask, text);
    } else {
      this.text = '';
    }

    _lastUpdatedText = this.text;
  }

  void updateMask(String mask, {bool moveCursorToEnd = true}) {
    this.mask = mask;
    updateText(text);

    if (moveCursorToEnd) {
      this.moveCursorToEnd();
    }
  }

  void moveCursorToEnd() {
    final String text = _lastUpdatedText;
    selection =
        TextSelection.fromPosition(TextPosition(offset: (text ?? '').length));
  }


来源: stackexchange

问:
How to get the full dates between two dates using javascript / react?
My requirement is to get the number of days between two dates.

For example, the start date is 02/20/2020 to 01/03/2020 I would like to display the results like

Feb 20 Thursday, Feb 21 Friday,....01 Mar Monday.

I went through this scenario in StackOverflow but I didn't get the expected solution for the same.

Could anyone please guide in achieving this scenario using javascript or react?

答:
Another method to get the difference between two dates in JavaScript:</p>

```<code>const d1 = new Date("06/30/2019");
const d2 = new Date("07/30/2019");

// To calculate the time difference of two dates
const timeDiff = d2.getTime() - d1.getTime();

// To calculate the no. of days between two dates
const days = timeDiff / (1000 * 3600 * 24);

//to list the days
while (days !== 0) {
    let date = new Date(d2)
    date.setDate(date.getDate() - days)
    console.log(date)
    days--
}
</code>```

ContentLicense: CC BY-SA 4.0

Body:
Another method to get the difference between two dates in JavaScript:

const d1 = new Date("06/30/2019");
const d2 = new Date("07/30/2019");

// To calculate the time difference of two dates
const timeDiff = d2.getTime() - d1.getTime();

// To calculate the no. of days between two dates
const days = timeDiff / (1000 * 3600 * 24);

//to list the days
while (days !== 0) {
    let date = new Date(d2)
    date.setDate(date.getDate() - days)
    console.log(date)
    days--
}


问:
How to replace only part of a word from a string in Python
I have a list of street names

```<code>streetNames = ['WELSESTRAAT', 'HENDRIKLAAN', 'LOMMERWEG']
</code>```

And another list with street abbreviations

```<code>streetAbbr = [['WEG', 'WG'], ['STRAAT', 'STR'],['LAAN', 'LN']]
</code>```

I am trying to loop through street names and replace straat with str, weg with wg and so on
but I am stuck in the replace part as there is no such method for only part of a word.

```<code>for name in streetNames:
    for abbr in streetAbbr:
        if str(abbr[0]) in str(name):
            name.replace('straat', abbr[1]) #doesn't work
</code>```

答:
The issue in your code is that your are replacing on the variable over which you are iterating, which has no effect on the original list. Instead reassign to the list by indexing it:

```<code>d = dict(streetAbbr)
# {'WEG': 'WG', 'STRAAT': 'STR', 'LAAN': 'LN'}

for k,v in d.items():
    for i, name in enumerate(streetNames):
        if k in name:
            streetNames[i] = name.replace(k, v)
</code>```

```<code>print(streetNames)
# ['WELSESTR', 'HENDRIKLN', 'LOMMERWG']
</code>```

Body:
I have a list of street names

streetNames = ['WELSESTRAAT', 'HENDRIKLAAN', 'LOMMERWEG']

And another list with street abbreviations

streetAbbr = [['WEG', 'WG'], ['STRAAT', 'STR'],['LAAN', 'LN']]

I am trying to loop through street names and replace straat with str, weg with wg and so on
but I am stuck in the replace part as there is no such method for only part of a word.

for name in streetNames:
    for abbr in streetAbbr:
        if str(abbr[0]) in str(name):
            name.replace('straat', abbr[1]) #doesn't work

Body:
The issue in your code is that your are replacing on the variable over which you are iterating, which has no effect on the original list. Instead reassign to the list by indexing it:

d = dict(streetAbbr)
# {'WEG': 'WG', 'STRAAT': 'STR', 'LAAN': 'LN'}

for k,v in d.items():
    for i, name in enumerate(streetNames):
        if k in name:
            streetNames[i] = name.replace(k, v)

print(streetNames)
# ['WELSESTR', 'HENDRIKLN', 'LOMMERWG']


问:
Get most upper descendant descendant(s) in jQuery
From page=$("#page") I want to get all the specified SVGs but not the subsequent inner ones.

```<code><div id="page">
    <div ...>
        <svg> /* THIS ONE */
            <rect ...>
            <circle ...>
            <svg> /* NOT THIS ONE */
                <foo> ... </foo>
            </svg>
        </svg>
    </div>
    <div ...>
        <div ...>
            <svg> /* THIS ONE */
                <rect ...>
                <circle ...>
                <svg> /* NOT THIS ONE */
                    <foo> ... </foo>
                </svg>
            </svg>
        </div>
   </div>
</div>
</code>```

EDIT I've updated the markup to clearly specify what I mean.

One solution is to use :not(svg svg) which i find ugly and performance heavy.

答:
After updated question

The only solutions are

```<code>$('#page svg:not(:has(svg))');
</code>```

and your own

```<code>$('#page svg:not(svg svg)');
</code>```

Performance-wise (check out the test) they are about the same with no clear winner

original answer

For the particular example

```<code>$('#page > svg:first')
</code>```

or

```<code>$('#page svg:first')
</code>```

will suffice.

But consider the following case

```<code><div id="page">
   <div>
     <p>
        <svg id="svg-1"></svg>
     </p>
     <svg id="svg-2"></svg>
   </div>
</div>
</code>```

Is this case possible (both svgs wrapped in something else) ? and if so, do you want #svg-2 ?

This case is not handled by the > version at all, and the$('#page svg:first') version will return the #svg-1

ContentLicense: CC BY-SA 3.0

Body:
From page=$("#page") I want to get all the specified SVGs but not the subsequent inner ones.

        <svg> /* THIS ONE */
            <rect ...>
            <circle ...>
            <svg> /* NOT THIS ONE */
                <foo> ... </foo>
            </svg>
        </svg>

            <svg> /* THIS ONE */
                <rect ...>
                <circle ...>
                <svg> /* NOT THIS ONE */
                    <foo> ... </foo>
                </svg>
            </svg>

EDIT I've updated the markup to clearly specify what I mean.

One solution is to use :not(svg svg) which i find ugly and performance heavy.

Body:
After updated question

The only solutions are

$('#page svg:not(:has(svg))');

and your own

$('#page svg:not(svg svg)');

Performance-wise (check out the test) they are about the same with no clear winner

original answer

For the particular example

$('#page > svg:first')

or

$('#page svg:first')

will suffice.

But consider the following case

<div id="page">
   <div>
     <p>
        <svg id="svg-1"></svg>
     </p>
     <svg id="svg-2"></svg>
   </div>
</div>

Is this case possible (both svgs wrapped in something else) ? and if so, do you want #svg-2 ?

This case is not handled by the > version at all, and the$('#page svg:first') version will return the #svg-1


问:
Format a JavaScript string using placeholders and an object of substitutions?
I have a string with say: My Name is %NAME% and my age is %AGE%.

%XXX% are placeholders. We need to substitute values there from an object.

Object looks like: {"%NAME%":"Mike","%AGE%":"26","%EVENT%":"20"}

I need to parse the object and replace the string with corresponding values. So that final output will be:

My Name is Mike and my age is 26.

The whole thing has to be done either using pure javascript or jquery.

答:
I have written a code that lets you format string easily.

Use this function.

```<code>function format() {
    if (arguments.length === 0) {
        throw "No arguments";
    }
    const string = arguments[0];
    const lst = string.split("{}");
    if (lst.length !== arguments.length) {
        throw "Placeholder format mismatched";
    }
    let string2 = "";
    let off = 1;
    for (let i = 0; i < lst.length; i++) {
        if (off < arguments.length) {
            string2 += lst[i] + arguments[off++]
        } else {
            string2 += lst[i]
        }
    }
    return string2;
}
</code>```

Example

```<code>format('My Name is {} and my age is {}', 'Mike', 26);
</code>```

Output

My Name is Mike and my age is 26

Body:
I have written a code that lets you format string easily.

Use this function.

function format() {
    if (arguments.length === 0) {
        throw "No arguments";
    }
    const string = arguments[0];
    const lst = string.split("{}");
    if (lst.length !== arguments.length) {
        throw "Placeholder format mismatched";
    }
    let string2 = "";
    let off = 1;
    for (let i = 0; i < lst.length; i++) {
        if (off < arguments.length) {
            string2 += lst[i] + arguments[off++]
        } else {
            string2 += lst[i]
        }
    }
    return string2;
}

Example

format('My Name is {} and my age is {}', 'Mike', 26);

Output

My Name is Mike and my age is 26


问:
Google Form answers validation with sheet and send email to users based on it
Data SheetRequirement :-

I am trying to write an Google App script to send email based on their answers while form submission for travel expenses.
i.e if form users choose  x as their city y as their per diem rate(allowance per day) script should check the google sheet attached for predefined values and if the user had entered the value more than allocated for a city then it should email admins to review the request else email users that is auto approved.

I know this can be done via if loop but pretty new to coding struggling to pull this condition any help would be great

```<code>function onformsubmit(e){
  var townCity = e.values[11];
  var currency = e.values[12];
.... // other lines of function
}

function sendEmails(townCity,currency){//var imported for other function for validation
  var ss = SpreadsheetApp.openById("ssid");
  var sheet = ss.getSheetByName("Rates for validation check");
  var lastRow = sheet.getLastRow();
  var city= sheet.getRange(2, 2, 141); // Fetch the range, including the minimums column 2 for city list in data sheet
  var budget= sheet.getRange(2, 3, 141); // Fetch the range, including the minimums column 3 for allocated budget for each city in dat sheet
  var location = city.getValues(); // Fetch values for each row in the Range.
  var location2 = budget.getValues();
  Logger.log(townCity); // log test
  if (townCity == location && currency == location2 ) {
    Logger.log('sendemail');}
  else if(townCity == location && currency != location2) {
    Logger.log('dontsendemail');
  }
}
</code>```

latest form sheet

Full Code

// When Form Gets submitted
function onFormSubmit(e) {
//Get information from form and set as variables
var emailAddress = e.values[1];
var clientName = e.values[4];
var StartDate = e.values[6];
var EndDate = e.values[7];
var country = e.values[9];
var townCity = e.values[8];//this value here is not been picked correctly as the contents in the column were retried by formula from all the other city columns
var amount = e.values[12];
var currency = e.values[11];
var engagementLeaderName = e.values[2];
//Logger.log('Lets see if its here'+ townCity);
}
  //funtion to validate with data sheet
function sendEmails(amount,townCity){
  var ss = SpreadsheetApp.openById("ssid");
  var sheet = ss.getSheetByName("Rates for validation check");
  var firstRow = 2;
  var firstCol = 2;
  var numRows = sheet.getLastRow() - firstRow + 1;
  var numCols = 2;
  var allocated = sheet.getRange(firstRow, firstCol, numRows, numCols).getValues();
  var index = allocated.map(function(value) {
    return value[0];
  }).indexOf(townCity);
  if (amount > allocated[index][1]) {
   // Send email:
   Logger.log('send email')
  }
}```

form screencap

答:
If I understood you correctly, you want to do the following:

When the user submits the form, grab the values from the response (retrieved with the event object): townCity and currency.

Retrieve the data from another sheet, which contains a list of cities (column B) and the allocated budget for each city (column C).

Find the city the user submitted, and check its allocated budget.

If the currency that was submitted by the user is higher than the allocated budget, send an email.

If that's correct, you can change your function sendEmails to this one:

function sendEmails(townCity, currency){
  var ss = SpreadsheetApp.openById("ssid");
  var sheet = ss.getSheetByName("Rates for validation check");
  var firstRow = 2;
  var firstCol = 2;
  var numRows = sheet.getLastRow() - firstRow + 1;
  var numCols = 2;
  var allocated = sheet.getRange(firstRow, firstCol, numRows, numCols).getValues();
  var index = allocated.map(function(value) {
    return value[0];
  }).indexOf(townCity);
  if (currency > allocated[index][1]) {
    // Send email:
    // MailApp.sendEmail(recipient, subject, body)
  }
}
```

<p>In this function, predefined cities and budgets are retrieved in a single 2D array, and indexOf is used to find the index of the submitted city in this array. Once this index is retrieved, it is used to find the corresponding budget <code>allocated[index][1]</code> and compare it to the submitted <code>currency</code>.</p>

<h3>UPDATE:</h3>

<p>In the form, you have several questions called <code>Town/City for {country}</code>, one for each country. To know city to look for, you need to first check the response from question <code>Country</code>. If that's the case, you can use the event property namedValues, an object that contains the question names and values from the form submission. </p>

<p>It could be something like this (I'm assuming you have a question called <code>Currency</code>:</p>

<pre class="lang-js prettyprint-override"><code>function onFormSubmit(e) {
  var country = e.namedValues["Country"][0]; // Retrieve country from form submission
  var currency = e.namedValues["Amount"][0]; // Retrieve currency from form submission
  country = country.charAt(0).toUpperCase() + country.slice(1).toLowerCase(); // Transform country from all capitalized to first character capitalized
  var townCity = e.namedValues["Town/City for " + country][0]; // Look for value corresponding to this country town/city
  sendEmails(townCity, currency);
}
</code>```

UPDATE 2:

The problem you were facing is that the question names are a bit different than expected:

In the country town/city sections, all question names should have the format Town/City for {countryName}, while in many cases, in your form, it's Town/City {countryName}, without the for. You have to fix this for all your countries in your form (or change the script correspondingly).

Because the format of the countries are sometimes all capitalized, toLowerCase has to be used for the country name to have the same format as in the following section (only first character capitalized). I added toLowerCase in the script to avoid this issue.

The property you want to track for, I assume, is Amount, not Currency. I edited that in the script.

Notes:

I am assuming that you already installed the form submit trigger. If that's not the case, you should install it, either manually or programmatically.

I am assuming you already know how to send the email. If that's not the case, you can start by checking MailApp.sendEmail(recipient, subject, body).

Reference:

Array.prototype.indexOf()

Body:
Data SheetRequirement :-

I am trying to write an Google App script to send email based on their answers while form submission for travel expenses.
i.e if form users choose  x as their city y as their per diem rate(allowance per day) script should check the google sheet attached for predefined values and if the user had entered the value more than allocated for a city then it should email admins to review the request else email users that is auto approved.

I know this can be done via if loop but pretty new to coding struggling to pull this condition any help would be great

function onformsubmit(e){
  var townCity = e.values[11];
  var currency = e.values[12];
.... // other lines of function
}

function sendEmails(townCity,currency){//var imported for other function for validation
  var ss = SpreadsheetApp.openById("ssid");
  var sheet = ss.getSheetByName("Rates for validation check");
  var lastRow = sheet.getLastRow();
  var city= sheet.getRange(2, 2, 141); // Fetch the range, including the minimums column 2 for city list in data sheet
  var budget= sheet.getRange(2, 3, 141); // Fetch the range, including the minimums column 3 for allocated budget for each city in dat sheet
  var location = city.getValues(); // Fetch values for each row in the Range.
  var location2 = budget.getValues();
  Logger.log(townCity); // log test
  if (townCity == location && currency == location2 ) {
    Logger.log('sendemail');}
  else if(townCity == location && currency != location2) {
    Logger.log('dontsendemail');
  }
}

latest form sheet

Full Code

// When Form Gets submitted
function onFormSubmit(e) {
//Get information from form and set as variables
var emailAddress = e.values[1];
var clientName = e.values[4];
var StartDate = e.values[6];
var EndDate = e.values[7];
var country = e.values[9];
var townCity = e.values[8];//this value here is not been picked correctly as the contents in the column were retried by formula from all the other city columns
var amount = e.values[12];
var currency = e.values[11];
var engagementLeaderName = e.values[2];
//Logger.log('Lets see if its here'+ townCity);
}
  //funtion to validate with data sheet
function sendEmails(amount,townCity){
  var ss = SpreadsheetApp.openById("ssid");
  var sheet = ss.getSheetByName("Rates for validation check");
  var firstRow = 2;
  var firstCol = 2;
  var numRows = sheet.getLastRow() - firstRow + 1;
  var numCols = 2;
  var allocated = sheet.getRange(firstRow, firstCol, numRows, numCols).getValues();
  var index = allocated.map(function(value) {
    return value[0];
  }).indexOf(townCity);
  if (amount > allocated[index][1]) {
   // Send email:
   Logger.log('send email')
  }
}

form screencap

Body:
If I understood you correctly, you want to do the following:

When the user submits the form, grab the values from the response (retrieved with the event object): townCity and currency.

Retrieve the data from another sheet, which contains a list of cities (column B) and the allocated budget for each city (column C).

Find the city the user submitted, and check its allocated budget.

If the currency that was submitted by the user is higher than the allocated budget, send an email.

If that's correct, you can change your function sendEmails to this one:

function sendEmails(townCity, currency){
  var ss = SpreadsheetApp.openById("ssid");
  var sheet = ss.getSheetByName("Rates for validation check");
  var firstRow = 2;
  var firstCol = 2;
  var numRows = sheet.getLastRow() - firstRow + 1;
  var numCols = 2;
  var allocated = sheet.getRange(firstRow, firstCol, numRows, numCols).getValues();
  var index = allocated.map(function(value) {
    return value[0];
  }).indexOf(townCity);
  if (currency > allocated[index][1]) {
    // Send email:
    // MailApp.sendEmail(recipient, subject, body)
  }
}

In this function, predefined cities and budgets are retrieved in a single 2D array, and indexOf is used to find the index of the submitted city in this array. Once this index is retrieved, it is used to find the corresponding budget allocated[index][1] and compare it to the submitted currency.

UPDATE:

In the form, you have several questions called Town/City for {country}, one for each country. To know city to look for, you need to first check the response from question Country. If that's the case, you can use the event property namedValues, an object that contains the question names and values from the form submission.

It could be something like this (I'm assuming you have a question called Currency:

function onFormSubmit(e) {
  var country = e.namedValues["Country"][0]; // Retrieve country from form submission
  var currency = e.namedValues["Amount"][0]; // Retrieve currency from form submission
  country = country.charAt(0).toUpperCase() + country.slice(1).toLowerCase(); // Transform country from all capitalized to first character capitalized
  var townCity = e.namedValues["Town/City for " + country][0]; // Look for value corresponding to this country town/city
  sendEmails(townCity, currency);
}

UPDATE 2:

The problem you were facing is that the question names are a bit different than expected:

In the country town/city sections, all question names should have the format Town/City for {countryName}, while in many cases, in your form, it's Town/City {countryName}, without the for. You have to fix this for all your countries in your form (or change the script correspondingly).

Because the format of the countries are sometimes all capitalized, toLowerCase has to be used for the country name to have the same format as in the following section (only first character capitalized). I added toLowerCase in the script to avoid this issue.

The property you want to track for, I assume, is Amount, not Currency. I edited that in the script.

Notes:

I am assuming that you already installed the form submit trigger. If that's not the case, you should install it, either manually or programmatically.

I am assuming you already know how to send the email. If that's not the case, you can start by checking MailApp.sendEmail(recipient, subject, body).

Reference:

Array.prototype.indexOf()


问:
How i can use context in Singleton?
I need in my Singleton -> Context. I know that I can't passing argument in constructor, because object hasn't constructor.

Then I call it from my Application class.

Here is the code:

```<code>object Singleton {

    var userAgentInfo: String = UserAgentTools.buildUserAgent(context)

    fun initializeSdk() {
        AuthenticatorApiManager.initializeSdk(userAgentInfo)
    }
}
</code>```

答:
Move the initialization of userAgentInfo to the initializeSDK method, and send the Context as an argument, make sure to send the ApplicationContext.</p>

```<code>object Singleton {

    var userAgentInfo: String? = null

    fun initializeSdk(context: Context) {
        userAgentInfo = UserAgentTools.buildUserAgent(context)
        AuthenticatorApiManager.initializeSdk(userAgentInfo)
    }
}
</code>```

Title: How i can use context in Singleton?

Body:
I need in my Singleton -> Context. I know that I can't passing argument in constructor, because object hasn't constructor.

Then I call it from my Application class.

Here is the code:

object Singleton {

    var userAgentInfo: String = UserAgentTools.buildUserAgent(context)

    fun initializeSdk() {
        AuthenticatorApiManager.initializeSdk(userAgentInfo)
    }
}

Body:
Move the initialization of userAgentInfo to the initializeSDK method, and send the Context as an argument, make sure to send the ApplicationContext.

object Singleton {

    var userAgentInfo: String? = null

    fun initializeSdk(context: Context) {
        userAgentInfo = UserAgentTools.buildUserAgent(context)
        AuthenticatorApiManager.initializeSdk(userAgentInfo)
    }
}


问:
Cannot deserialize the json file with list of events?
I have below C# class structure,

```<code>public class Event
{
    public string Id { get; set; }
    public Body Body { get; set; }
    public BodyProperty[] BodyProperties { get; set; }
    public string EventType { get; set; }
    public string CreatedTime { get; set; }
}

public class BodyProperty
{
    public string Key { get; set; }
    public string Value { get; set; }
}

public class Body
{
    public Body(string value, string type = "TextualBody", string format = "application/json")
    {
        Type = type;
        Value = value;
        Format = format;
    }

    public string Type { get; set; }
    public string Value { get; set; }
    public string Format { get; set; }
}
</code>```

and trying to read below JSON file,

```<code>{
    "Events": [
        {
            "Id": "d22fc23c-968f-4406-bebb-fca231694986",
            "Body": {
                "Type": "TextualBody",
                "Value": "test",
                "Format": "application/json"
            },
            "BodyProperties": null,
            "EventType": "Entity",
            "CreatedTime": "2020-02-20T13:57:14.1234165+05:30"
        },
        {
            "Id": "fgdgdg-968f-4406-bebb-646464",
            "Body": {
                "Type": "TextualBody",
                "Value": "test",
                "Format": "application/json"
            },
            "BodyProperties": null,
            "EventType": "Entity",
            "CreatedTime": "2020-02-21T13:57:14.1234165+05:30"
        }
    ]
}
</code>```

But this give below error while trying to read like this, I can't change JSON format, what can I change while reading?

```<code>using (StreamReader file = File.OpenText(@"C:\TEMP\json1.json"))
        using (JsonTextReader jsonreader = new JsonTextReader(file))
        {
            var serializer = new JsonSerializer();
            return serializer.Deserialize<List<Event>>(jsonreader);
        }
</code>```

Newtonsoft.Json.JsonSerializationException: 'Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Collections.Generic.List`1[uploadJSON.Event]' because the type requires a JSON array (e.g. [1,2,3]) to deserialize correctly.
  To fix this error either change the JSON to a JSON array (e.g. [1,2,3]) or change the deserialized type so that it is a normal .NET type (e.g. not a primitive type like integer, not a collection type like an array or List) that can be deserialized from a JSON object.

答:
For your JSON class structure is:

```<code>public class Body
{
    public string Type { get; set; }
    public string Value { get; set; }
    public string Format { get; set; }
}

public class Event
{
    public string Id { get; set; }
    public Body Body { get; set; }
    public object BodyProperties { get; set; }
    public string EventType { get; set; }
    public DateTime CreatedTime { get; set; }
}

public class RootObject
{
    public List<Event> Events { get; set; }
}
</code>```

Deserialize to RootObject type.

On site json2csharp.com or in VS you can generate classes from JSON.

Body:
I have below C# class structure,

public class Event
{
    public string Id { get; set; }
    public Body Body { get; set; }
    public BodyProperty[] BodyProperties { get; set; }
    public string EventType { get; set; }
    public string CreatedTime { get; set; }
}

public class BodyProperty
{
    public string Key { get; set; }
    public string Value { get; set; }
}

public class Body
{
    public Body(string value, string type = "TextualBody", string format = "application/json")
    {
        Type = type;
        Value = value;
        Format = format;
    }

    public string Type { get; set; }
    public string Value { get; set; }
    public string Format { get; set; }
}

and trying to read below JSON file,

{
    "Events": [
        {
            "Id": "d22fc23c-968f-4406-bebb-fca231694986",
            "Body": {
                "Type": "TextualBody",
                "Value": "test",
                "Format": "application/json"
            },
            "BodyProperties": null,
            "EventType": "Entity",
            "CreatedTime": "2020-02-20T13:57:14.1234165+05:30"
        },
        {
            "Id": "fgdgdg-968f-4406-bebb-646464",
            "Body": {
                "Type": "TextualBody",
                "Value": "test",
                "Format": "application/json"
            },
            "BodyProperties": null,
            "EventType": "Entity",
            "CreatedTime": "2020-02-21T13:57:14.1234165+05:30"
        }
    ]
}

But this give below error while trying to read like this, I can't change JSON format, what can I change while reading?

using (StreamReader file = File.OpenText(@"C:\TEMP\json1.json"))
        using (JsonTextReader jsonreader = new JsonTextReader(file))
        {
            var serializer = new JsonSerializer();
            return serializer.Deserialize<List<Event>>(jsonreader);
        }

Newtonsoft.Json.JsonSerializationException: 'Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Collections.Generic.List`1[uploadJSON.Event]' because the type requires a JSON array (e.g. [1,2,3]) to deserialize correctly.
  To fix this error either change the JSON to a JSON array (e.g. [1,2,3]) or change the deserialized type so that it is a normal .NET type (e.g. not a primitive type like integer, not a collection type like an array or List) that can be deserialized from a JSON object.

Body:
For your JSON class structure is:

public class Body
{
    public string Type { get; set; }
    public string Value { get; set; }
    public string Format { get; set; }
}

public class Event
{
    public string Id { get; set; }
    public Body Body { get; set; }
    public object BodyProperties { get; set; }
    public string EventType { get; set; }
    public DateTime CreatedTime { get; set; }
}

public class RootObject
{
    public List<Event> Events { get; set; }
}

Deserialize to RootObject type.

On site json2csharp.com or in VS you can generate classes from JSON.


问:
Using a CASE WHEN statement in NHibernate HQL
My Query

```<code>select oc.Id as Id, (CASE WHEN (select Count(Id) from CompanyAuthorizedInfo cai where cai.Company.Id = oc.Id and cai.IsDefault = 1 and cai.Status=1) = 1 THEN (select MAX(cai2.Name) from CompanyAuthorizedInfo cai2 where cai2.CompanyId = oc.Company.Id and cai2.IsDefault = 1 and cai2.Status=1) ELSE MAX(aut.Name) END) as AuthorizedName , MAX(oc.CustomerRepresentative.Id) as CustomerRepresentativeId, MAX(oc.RecordDate) as RecordDate, MAX(oc.TpeOwnerCode) as TpeOwnerCode, MAX(oc.CodeAttorney) as CodeAttorney, oc.Name as Name, (select c.Name  from City c where  c.Id=MAX(oca.City.Id)) as CityName, (select d.Name  from District d where  d.Id=MAX(oca.District.Id)) as DistrictName, MAX(aut.PhoneNo) as PhoneNo ,MAX(cif.Number) as PhoneNumber, MAX(oc.Email) as Email, (select u.Name+' '+u.Surname from Users u where u.Id = MAX(oc.CustomerRepresentative.Id)) as CustomerRepresentativeName, MAX(CASE WHEN oc.HaveACustomer=1 THEN 1 ELSE 0 END) as IsCustomer , MAX(CASE WHEN oc.HaveACustomer=1 THEN 'Müşteri' WHEN oc.HaveAPotantialCustomer=1 THEN 'Potansiyel Müşteri' ELSE 'Firma' END) as CustomerStatus from Company oc left join oc.Addresses oca with oca.Status = 1 left join oc.AuthorizedInfos aut with aut.Status = 1 left join oc.ContactInfos cif with cif.Status = 1 and cif.ContactType.Id < 4 where oc.Status = 1 and oc.UserCompany.Id = :userCompanyId group by oc.Id, oc.Name order by oc.Name asc
</code>```

When condition is running in query, the field in then statement returns an error. Then it works when I write a fixed value (like 1-2) in SQL instead of a query.

The error I'm getting is

QuerySyntaxException was unhandled by user code

答:
Instead of applying aggregate function MAX to entire select query, try applying it to the 'tbl2.Name' column.

Refer the below updated query.

```<code>(   CASE WHEN
        (   select  Count(Id)
            from    TableName tbl
            where   tbl.Company.Id = oc.Id
            and     tbl.IsDefault = 1
            and     tbl.Status=1
        ) = 1
    THEN
        select  MAX(tbl2.Name)
        from    CompanyAuthorizedInfo tbl2
        where   tbl2.CompanyId =c.Company.Id
        and     tbl2.IsDefault = 1
        and     tbl2.Status=1
    ELSE
        MAX(aut.Name)
    END
) as Value
</code>```

Body:
My Query

select oc.Id as Id, (CASE WHEN (select Count(Id) from CompanyAuthorizedInfo cai where cai.Company.Id = oc.Id and cai.IsDefault = 1 and cai.Status=1) = 1 THEN (select MAX(cai2.Name) from CompanyAuthorizedInfo cai2 where cai2.CompanyId = oc.Company.Id and cai2.IsDefault = 1 and cai2.Status=1) ELSE MAX(aut.Name) END) as AuthorizedName , MAX(oc.CustomerRepresentative.Id) as CustomerRepresentativeId, MAX(oc.RecordDate) as RecordDate, MAX(oc.TpeOwnerCode) as TpeOwnerCode, MAX(oc.CodeAttorney) as CodeAttorney, oc.Name as Name, (select c.Name  from City c where  c.Id=MAX(oca.City.Id)) as CityName, (select d.Name  from District d where  d.Id=MAX(oca.District.Id)) as DistrictName, MAX(aut.PhoneNo) as PhoneNo ,MAX(cif.Number) as PhoneNumber, MAX(oc.Email) as Email, (select u.Name+' '+u.Surname from Users u where u.Id = MAX(oc.CustomerRepresentative.Id)) as CustomerRepresentativeName, MAX(CASE WHEN oc.HaveACustomer=1 THEN 1 ELSE 0 END) as IsCustomer , MAX(CASE WHEN oc.HaveACustomer=1 THEN 'Müşteri' WHEN oc.HaveAPotantialCustomer=1 THEN 'Potansiyel Müşteri' ELSE 'Firma' END) as CustomerStatus from Company oc left join oc.Addresses oca with oca.Status = 1 left join oc.AuthorizedInfos aut with aut.Status = 1 left join oc.ContactInfos cif with cif.Status = 1 and cif.ContactType.Id < 4 where oc.Status = 1 and oc.UserCompany.Id = :userCompanyId group by oc.Id, oc.Name order by oc.Name asc

When condition is running in query, the field in then statement returns an error. Then it works when I write a fixed value (like 1-2) in SQL instead of a query.

The error I'm getting is

QuerySyntaxException was unhandled by user code

Body:
Instead of applying aggregate function MAX to entire select query, try applying it to the 'tbl2.Name' column.

Refer the below updated query.

(   CASE WHEN
        (   select  Count(Id)
            from    TableName tbl
            where   tbl.Company.Id = oc.Id
            and     tbl.IsDefault = 1
            and     tbl.Status=1
        ) = 1
    THEN
        select  MAX(tbl2.Name)
        from    CompanyAuthorizedInfo tbl2
        where   tbl2.CompanyId =c.Company.Id
        and     tbl2.IsDefault = 1
        and     tbl2.Status=1
    ELSE
        MAX(aut.Name)
    END
) as Value


问:
TypeError: Cannot read property 'getParam' of undefined. for react native unit test using jest and enzyme?
I am trying to write unit test cases for react native for very first time..I am getting following error

AlbumDetailView.js

import { View, Image } from 'react-native';
import { Button, Provider, Text } from 'react-native-paper';
import React from 'react';
import styles from '../style/AlbumDetailView.component.style';

export default class DetailView extends React.Component {
    static navigationOptions = {
      title: 'Album Details',
    };

    render() {
      { /* Using the navigation prop we can get the value passed from the previous screen */ }
      const { navigation } = this.props;
      const albumTitle = navigation.getParam('albumTitle', 'Default data');
      const albumImg = navigation.getParam('albumImg', 'some default value');
      const goBackToHome = () => this.props.navigation.goBack(this.props.navigation.state.key);

      return (
          <React.Fragment>
            <Provider>
              <View style={styles.mainContainer}>
                <View style={styles.albumViewContainer}>
                    <Image source = {{ uri: albumImg }} style={styles.imageView} />
                    <Text style={styles.textStyle}>{albumTitle}</Text>
                    <Button mode="contained"
                        onPress={() => this.props.navigation.navigate('HomeScreen', { goBackToHome, })}
                        style={styles.buttonStyle} testID='HomeButton'>
                        HOME
                    </Button>
                </View>
              </View>
            </Provider>
          </React.Fragment>
      );
    }
}```
</div>
</div>
</p>

<p>and I am writing test cases for same as bellow </p>

<p><div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false">
<div class="snippet-code">
<pre class="snippet-code-js lang-js prettyprint-override"><code>import 'react-native';
import React, { Component } from 'react';
import { shallow } from 'enzyme';
import AlbumDetailsView from '../component/AlbumDetailsView';

describe('Album Details Screen', () => {

  it('should render Album Details component', () => {
      const wrapper = shallow(<AlbumDetailsView />);
  });

  it('should render initial layout', () => {
  // when
  const component = shallow(<AlbumDetailsView />);
  // then
  expect(component.getElements()).toMatchSnapshot();
  });

  it('should check if BackButton exists', () => {
    const wrapper = shallow(<AlbumDetailsView />);
    wrapper.findWhere(n => n.name() === 'Button' && n.prop('testID') === 'HomeButton')

  });

});</code>```

May I know how to handle this?

答:
they recently change the way to pass props
https://reactnavigation.org/docs/en/upgrading-from-4.x.html#no-more-getparam</p>

Body:
I am trying to write unit test cases for react native for very first time..I am getting following error

AlbumDetailView.js

import { View, Image } from 'react-native';
import { Button, Provider, Text } from 'react-native-paper';
import React from 'react';
import styles from '../style/AlbumDetailView.component.style';

export default class DetailView extends React.Component {
    static navigationOptions = {
      title: 'Album Details',
    };

    render() {
      { /* Using the navigation prop we can get the value passed from the previous screen */ }
      const { navigation } = this.props;
      const albumTitle = navigation.getParam('albumTitle', 'Default data');
      const albumImg = navigation.getParam('albumImg', 'some default value');
      const goBackToHome = () => this.props.navigation.goBack(this.props.navigation.state.key);

      return (
          <React.Fragment>
            <Provider>
              <View style={styles.mainContainer}>
                <View style={styles.albumViewContainer}>
                    <Image source = {{ uri: albumImg }} style={styles.imageView} />
                    <Text style={styles.textStyle}>{albumTitle}</Text>
                    <Button mode="contained"
                        onPress={() => this.props.navigation.navigate('HomeScreen', { goBackToHome, })}
                        style={styles.buttonStyle} testID='HomeButton'>
                        HOME
                    </Button>
                </View>
              </View>
            </Provider>
          </React.Fragment>
      );
    }
}

and I am writing test cases for same as bellow

import 'react-native';
import React, { Component } from 'react';
import { shallow } from 'enzyme';
import AlbumDetailsView from '../component/AlbumDetailsView';

describe('Album Details Screen', () => {

  it('should render Album Details component', () => {
      const wrapper = shallow(<AlbumDetailsView />);
  });

  it('should render initial layout', () => {
  // when
  const component = shallow(<AlbumDetailsView />);
  // then
  expect(component.getElements()).toMatchSnapshot();
  });

  it('should check if BackButton exists', () => {
    const wrapper = shallow(<AlbumDetailsView />);
    wrapper.findWhere(n => n.name() === 'Button' && n.prop('testID') === 'HomeButton')

  });

});

May I know how to handle this?


答:
From the date given, find the difference in days then based on the no of days, make a loop and log each increment day in between using toLocaleString()..

const startDate = "02/20/2020";
const endDate = "03/01/2020";

const diffTime = Math.abs(new Date(endDate) - new Date(startDate));
const diffDays = 0|diffTime/864e5;

for(let i = 0; i <= diffDays; i++){
  const newdate = new Date(new Date(startDate).getTime()+(i*864e5));
  console.log(newdate.toLocaleString('en-us', { day:'2-digit', month: 'short', weekday:'long'}))
}```

Title: How to get the full dates between two dates using javascript / react?

Body:
My requirement is to get the number of days between two dates.

For example, the start date is 02/20/2020 to 01/03/2020 I would like to display the results like

Feb 20 Thursday, Feb 21 Friday,....01 Mar Monday.

I went through this scenario in StackOverflow but I didn't get the expected solution for the same.

Could anyone please guide in achieving this scenario using javascript or react?


问:
auto increment value in django
i have an table in django and try to auto increment it's serial no. in custom template for loop is used for the variables.

custom template

```<code>{% for i in getodeskview %}
    <tr>
        <td> 1. </td>
        <td>{{ i.odesk_id }}</td>
        <td>{{ i.hours }}</td>
        <td>{{ i.feedback }}</td>
        <td>
            <a href="/odesk/?editodeskform={{i.id}} " title="Edit"><i class="splashy-document_letter_edit"></i></a>
            <!---- <a href="/hours/?addhid={{i.app_id}}" title="Interview"><i class="splashy-document_letter_okay"></i></a>----->
            <a href="/deleteodesk/?dltodid={{i.id}}" title="Remove"><i class="splashy-document_letter_remove"></i></a>
        </td>
    </tr>
{% endfor %}
</code>```

how to increment the values.

答:
Use {{ forloop.counter }}.

Source:
Built-in template tags and filters #for

I hope it will solve you problem

Title: auto increment value in django

Body:
i have an table in django and try to auto increment it's serial no. in custom template for loop is used for the variables.

custom template

{% for i in getodeskview %}

         1.
        {{ i.odesk_id }}
        {{ i.hours }}
        {{ i.feedback }}

{% endfor %}

how to increment the values.


问:
Disabling editor in Joomla modules section
I want to disable the HTML editor(Tiny MCE/Xstandard lite 2.0) and enable Editor - No editor option in module section of Joomla. Please Advise.</p>

答:
Its part of the user settings. Go to the administration interface.

Site -> User Manager

Select what user you want to set the editor for.

Within "Parameters / Basic Settings" select box "User Editor", select "Editor - No Editor"


问:
Is there any missing functions in this code to pop-up the materialize data?
The materialize pop-up does not appear.

$(document).ready(function() {
  $('#cdn_customer_id').on('click', function() {
    //alert("hi00");
    var countCust = '<?php count($customers) ?>';
    if (countCust < 1) {
      Materialize.toast('Add a Sales/Client Master', 3000, 'red rounded')
    }
  });
```

<pre class="lang-html prettyprint-override"><code><select class="js-example-basic-single" name="cust_id" id="cdn_customer_id">
  <option value="">SELECT CLIENT</option>
  <?php foreach ($customers as $cus) { ?>
    <option value="<?php echo $cus->cust_id; ?>" <?php if(!empty($inv)){if($inv[0]->cust_id!=0){ echo ($inv[0]->cust_id==$cus->cust_id)?'selected':''; }} ?> >
    <?php echo strtoupper($cus->cust_name); ?>
  </option>
  <?php } ?>
</select>
</code>```

答:
Try the following

There's two changes I'd make to your code from what I can see, I don't know if it will fix everything but from the information you've given us, this is the best I can come up with.

First Issue:

You are setting an on click listener on a drop-down, surely you want this to fire when someone selects an option, not when they click on the select, I'd change the following line:

```<code>$('#cdn_customer_id').on('click', function() {
</code>```

To a change listener by simply changing the word click:

```<code>$('#cdn_customer_id').on('change', function() {
</code>```

Second Issue:

I don't think the customer count is being set properly, you haven't used echo to output a value, it's not best practice to place a PHP value in JavaScript but seeing as you've done this and I have limited information available to change it, we'll leave it as it is but actually set the value properly by changing the following line:

```<code>var countCust = '<?php count($customers) ?>';
</code>```

To echo the value using the short-hand version, providing you are using PHP 5.4 or later, this shouldn't be an issue:

```<code>var countCust = '<?=count($customers) ?>';
</code>```

However, if for some reason you're using an earlier version of PHP I might as well include the longer version:

```<code>var countCust = '<?php echo count($customers) ?>';
</code>```

I'd say if you make these two changes, see if anything improves and get back to me with your feedback and hopefully solve the next issue if there is one.

Body:
The materialize pop-up does not appear.

$(document).ready(function() {
  $('#cdn_customer_id').on('click', function() {
    //alert("hi00");
    var countCust = '<?php count($customers) ?>';
    if (countCust < 1) {
      Materialize.toast('Add a Sales/Client Master', 3000, 'red rounded')
    }
  });

<select class="js-example-basic-single" name="cust_id" id="cdn_customer_id">
  <option value="">SELECT CLIENT</option>
  <?php foreach ($customers as $cus) { ?>
    <option value="<?php echo $cus->cust_id; ?>" <?php if(!empty($inv)){if($inv[0]->cust_id!=0){ echo ($inv[0]->cust_id==$cus->cust_id)?'selected':''; }} ?> >
    <?php echo strtoupper($cus->cust_name); ?>
  </option>
  <?php } ?>
</select>

Body:
Try the following

There's two changes I'd make to your code from what I can see, I don't know if it will fix everything but from the information you've given us, this is the best I can come up with.

First Issue:

You are setting an on click listener on a drop-down, surely you want this to fire when someone selects an option, not when they click on the select, I'd change the following line:

$('#cdn_customer_id').on('click', function() {

To a change listener by simply changing the word click:

$('#cdn_customer_id').on('change', function() {

Second Issue:

I don't think the customer count is being set properly, you haven't used echo to output a value, it's not best practice to place a PHP value in JavaScript but seeing as you've done this and I have limited information available to change it, we'll leave it as it is but actually set the value properly by changing the following line:

var countCust = '<?php count($customers) ?>';

To echo the value using the short-hand version, providing you are using PHP 5.4 or later, this shouldn't be an issue:

var countCust = '<?=count($customers) ?>';

However, if for some reason you're using an earlier version of PHP I might as well include the longer version:

var countCust = '<?php echo count($customers) ?>';

I'd say if you make these two changes, see if anything improves and get back to me with your feedback and hopefully solve the next issue if there is one.


问:
WebdriverIO - Test fails with error Openfin
I have been trying to setup automation testing for our openfin application using the below repo as base

https://github.com/openfin/webinar-automated-integration-tests

I am using Openfin (Chrome version 61.0.3163.100) and Chromedriver 2.40.565498

When I run "npm test", the openfin application opens up. But the tests don't run. After waiting for sometime, it throws the below error in console.

```<code>ERROR: unknown error: DevToolsActivePort file doesn't exist
 (Driver info: chromedriver=2.40.565498 (ea082db3280dd6843ebfb08a625e3eb905c4f5ab),platform=Windows NT 10.0.16299 x86_64)
</code>```

chrome

I tried using other versions of chromedriver like 2.33, 2.34, 2.37, 2.38, 2.39, 2.41. Using these versions even the application doesn't appear. So, I guess the chromedriver version I am using is correct. I have also tried adding the below arguments to chromeOptions

```<code>--remote-debugging-port=9222,--no-sandbox,--headless,--disable-gpu
</code>```

They didn't solve my issue. Not sure what is causing the issue. Any help would be much appreciated. Thanks in advance. Cheers!

答:
This error message...

```<code>ERROR: unknown error: DevToolsActivePort file doesn't exist
 (Driver info: chromedriver=2.40.565498 (ea082db3280dd6843ebfb08a625e3eb905c4f5ab),platform=Windows NT 10.0.16299 x86_64)
</code>```

...implies that the ChromeDriver was unable to initiate/spawn a new Browsing Context i.e. Chrome Browser session.

Your main issue is the incompatibility between the version of the binaries you are using as follows:

You are using chromedriver=2.40

Release Notes of chromedriver=2.40 clearly mentions the following :

Supports Chrome v66-68

Presumably you are using chrome=61.0

Release Notes of ChromeDriver v2.33 clearly mentions the following :

Supports Chrome 60-62

Your Selenium Client version is unknown to us.

So there is a clear mismatch between ChromeDriver v2.40 and the Chrome Browser v60.0

Solution

Ensure that:

Selenium is upgraded to  current levels Version 3.141.59.

ChromeDriver is updated to  current ChromeDriver v80.0 level.

Chrome is updated to  current Chrome Version 80.0 level. (as per ChromeDriver v80.0 release notes)

Clean your Project Workspace through your IDE and Rebuild your project with required dependencies only.

If your base Web Client version is too old, then uninstall it and install a recent GA and released version of Web Client.

Take a System Reboot.

Execute your @Test as non-root user.

Always invoke driver.quit() within tearDown(){} method to close & destroy the WebDriver and Web Client instances gracefully.

Body:
I have been trying to setup automation testing for our openfin application using the below repo as base

https://github.com/openfin/webinar-automated-integration-tests

I am using Openfin (Chrome version 61.0.3163.100) and Chromedriver 2.40.565498

When I run "npm test", the openfin application opens up. But the tests don't run. After waiting for sometime, it throws the below error in console.

ERROR: unknown error: DevToolsActivePort file doesn't exist
 (Driver info: chromedriver=2.40.565498 (ea082db3280dd6843ebfb08a625e3eb905c4f5ab),platform=Windows NT 10.0.16299 x86_64)

chrome

I tried using other versions of chromedriver like 2.33, 2.34, 2.37, 2.38, 2.39, 2.41. Using these versions even the application doesn't appear. So, I guess the chromedriver version I am using is correct. I have also tried adding the below arguments to chromeOptions

--remote-debugging-port=9222,--no-sandbox,--headless,--disable-gpu

They didn't solve my issue. Not sure what is causing the issue. Any help would be much appreciated. Thanks in advance. Cheers!

Body:
This error message...

ERROR: unknown error: DevToolsActivePort file doesn't exist
 (Driver info: chromedriver=2.40.565498 (ea082db3280dd6843ebfb08a625e3eb905c4f5ab),platform=Windows NT 10.0.16299 x86_64)

...implies that the ChromeDriver was unable to initiate/spawn a new Browsing Context i.e. Chrome Browser session.

Your main issue is the incompatibility between the version of the binaries you are using as follows:

You are using chromedriver=2.40

Release Notes of chromedriver=2.40 clearly mentions the following :

Supports Chrome v66-68

Presumably you are using chrome=61.0

Release Notes of ChromeDriver v2.33 clearly mentions the following :

Supports Chrome 60-62

Your Selenium Client version is unknown to us.

So there is a clear mismatch between ChromeDriver v2.40 and the Chrome Browser v60.0

Solution

Ensure that:

Selenium is upgraded to  current levels Version 3.141.59.

ChromeDriver is updated to  current ChromeDriver v80.0 level.

Chrome is updated to  current Chrome Version 80.0 level. (as per ChromeDriver v80.0 release notes)

Clean your Project Workspace through your IDE and Rebuild your project with required dependencies only.

If your base Web Client version is too old, then uninstall it and install a recent GA and released version of Web Client.

Take a System Reboot.

Execute your @Test as non-root user.

Always invoke driver.quit() within tearDown(){} method to close & destroy the WebDriver and Web Client instances gracefully.


问:
How do I make the form options to pop on the left side of the label of a radio button
I have written the following:

.reveal-if-active {
  opacity: 0;
  max-height: 0;
  overflow: hidden;
}

input[type="radio"]:checked~.reveal-if-active,
input[type="checkbox"]:checked~.reveal-if-active {
  opacity: 1;
  max-height: 100px;
  /* little bit of a magic number :( */
  overflow: visible;
}```
<pre class="snippet-code-html lang-html prettyprint-override"><code><div>
  <input type="radio" name="choice-animals" id="choice-animals-dogs">
  <label for="choice-animals-dogs">I like dogs more</label>
  <div class="reveal-if-active">
    <input type="text" name="dog" placeholder="why?">
  </div>
</div>
<div>
  <input type="radio" name="choice-animals" id="choice-animals-cats">
  <label for="choice-animals-cats">I like cats more</label>
  <div class="reveal-if-active">
    <input type="text" name="cat" placeholder="why?">
  </div>
</div></code>```

And the output of this code is:

So, how do I go about creating a code by which I can make the text boxes that are being revealed by clicking on the radio buttons on the left side of the labels of those radio buttons?

I have tried using tables to actually arrange the radio buttons and then try and display the hidden text boxes on the next cell beside the label, but it hasn't helped, as using a table somehow disables the popups.

Any help on the matter would be really appreciated!

答:
As mentioned by @FabioCalderan's comment and thanks to him, we can simply add display:inline-block to the class .reveal-if-active to pop the options on the same line as the radio button and the label.

.reveal-if-active {
  display: inline-block;
  opacity: 0;
  max-height: 0;
  overflow: hidden;
}

input[type="radio"]:checked~.reveal-if-active,
input[type="checkbox"]:checked~.reveal-if-active {
  display: inline-block;
  opacity: 1;
  max-height: 100px;
  /* little bit of a magic number :( */
  overflow: visible;
}```
<pre class="snippet-code-html lang-html prettyprint-override"><code><div>
  <input type="radio" name="choice-animals" id="choice-animals-dogs">
  <label for="choice-animals-dogs">I like dogs more</label>
  <div class="reveal-if-active">
    <input type="text" name="dog" placeholder="why?">
  </div>
</div>
<div>
  <input type="radio" name="choice-animals" id="choice-animals-cats">
  <label for="choice-animals-cats">I like cats more</label>
  <div class="reveal-if-active">
    <input type="text" name="cat" placeholder="why?">
  </div>
</div></code>```

Body:
I have written the following:

.reveal-if-active {
  opacity: 0;
  max-height: 0;
  overflow: hidden;
}

input[type="radio"]:checked~.reveal-if-active,
input[type="checkbox"]:checked~.reveal-if-active {
  opacity: 1;
  max-height: 100px;
  /* little bit of a magic number :( */
  overflow: visible;
}

  <input type="radio" name="choice-animals" id="choice-animals-dogs">
  I like dogs more

    <input type="text" name="dog" placeholder="why?">

  <input type="radio" name="choice-animals" id="choice-animals-cats">
  I like cats more

    <input type="text" name="cat" placeholder="why?">

And the output of this code is:

So, how do I go about creating a code by which I can make the text boxes that are being revealed by clicking on the radio buttons on the left side of the labels of those radio buttons?

I have tried using tables to actually arrange the radio buttons and then try and display the hidden text boxes on the next cell beside the label, but it hasn't helped, as using a table somehow disables the popups.

Any help on the matter would be really appreciated!

Body:
As mentioned by @FabioCalderan's comment and thanks to him, we can simply add display:inline-block to the class .reveal-if-active to pop the options on the same line as the radio button and the label.

.reveal-if-active {
  display: inline-block;
  opacity: 0;
  max-height: 0;
  overflow: hidden;
}

input[type="radio"]:checked~.reveal-if-active,
input[type="checkbox"]:checked~.reveal-if-active {
  display: inline-block;
  opacity: 1;
  max-height: 100px;
  /* little bit of a magic number :( */
  overflow: visible;
}

<div>
  <input type="radio" name="choice-animals" id="choice-animals-dogs">
  <label for="choice-animals-dogs">I like dogs more</label>
  <div class="reveal-if-active">
    <input type="text" name="dog" placeholder="why?">
  </div>
</div>
<div>
  <input type="radio" name="choice-animals" id="choice-animals-cats">
  <label for="choice-animals-cats">I like cats more</label>
  <div class="reveal-if-active">
    <input type="text" name="cat" placeholder="why?">
  </div>
</div>


问:
iRedMail server no SMTP/IMAP connection
I have configured an iRedMail server with SSL certificates on my Ubuntu 18.04 machine, but I can't manage to connect my devices (via Outlook or Spark) via SMTP/IMAP protocols.

I have opened ports 593, 143, 993, 995 and still, devices cannot connect to the server.
The error from Spark is as following "a stable connection to the server could not be established".
I have also tried as guided in manual, but no luck.

Logs from netstat

```<code>Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name

tcp 0 0 127.0.0.53:53 0.0.0.0:\* LISTEN 644/systemd-resolve

tcp 0 0 0.0.0.0:22 0.0.0.0:\* LISTEN 907/sshd

tcp 0 0 127.0.0.1:24 0.0.0.0:\* LISTEN 804/dovecot

tcp 0 0 0.0.0.0:25 0.0.0.0:\* LISTEN 2352/master

tcp 0 0 0.0.0.0:443 0.0.0.0:\* LISTEN 969/nginx: master p

tcp 0 0 127.0.0.1:8125 0.0.0.0:\* LISTEN 2373/netdata

tcp 0 0 127.0.0.1:4190 0.0.0.0:\* LISTEN 804/dovecot

tcp 0 0 127.0.0.1:19999 0.0.0.0:\* LISTEN 2373/netdata

tcp 1 0 127.0.0.1:20000 0.0.0.0:\* LISTEN 1291/sogod

tcp 0 0 127.0.0.1:7777 0.0.0.0:\* LISTEN 1318/python2

tcp 0 0 0.0.0.0:993 0.0.0.0:\* LISTEN 804/dovecot

tcp 0 0 0.0.0.0:995 0.0.0.0:\* LISTEN 804/dovecot

tcp 0 0 127.0.0.1:10024 0.0.0.0:\* LISTEN 1871/amavisd-new (m

tcp 0 0 127.0.0.1:10025 0.0.0.0:\* LISTEN 2352/master

tcp 0 0 127.0.0.1:10026 0.0.0.0:\* LISTEN 1871/amavisd-new (m

tcp 0 0 127.0.0.1:3306 0.0.0.0:\* LISTEN 1145/mysqld

tcp 0 0 0.0.0.0:587 0.0.0.0:\* LISTEN 2352/master

tcp 0 0 127.0.0.1:10027 0.0.0.0:\* LISTEN 1871/amavisd-new (m

tcp 0 0 127.0.0.1:11211 0.0.0.0:\* LISTEN 844/memcached

tcp 0 0 127.0.0.1:10028 0.0.0.0:\* LISTEN 2352/master

tcp 0 0 127.0.0.1:9998 0.0.0.0:\* LISTEN 1871/amavisd-new (m

tcp 0 0 0.0.0.0:110 0.0.0.0:\* LISTEN 804/dovecot

tcp 0 0 127.0.0.1:7790 0.0.0.0:\* LISTEN 864/uwsgi

tcp 0 0 127.0.0.1:9999 0.0.0.0:\* LISTEN 836/php-fpm: master

tcp 0 0 0.0.0.0:143 0.0.0.0:\* LISTEN 804/dovecot

tcp 0 0 127.0.0.1:7791 0.0.0.0:\* LISTEN 866/uwsgi

tcp 0 0 0.0.0.0:80 0.0.0.0:\* LISTEN 969/nginx: master p

tcp 0 0 127.0.0.1:24242 0.0.0.0:\* LISTEN 804/dovecot

tcp 0 0 127.0.0.1:12340 0.0.0.0:\* LISTEN 804/dovecot

tcp6 0 0 :::21 :::\* LISTEN 5516/vsftpd

tcp6 0 0 :::22 :::\* LISTEN 907/sshd

tcp6 0 0 :::25 :::\* LISTEN 2352/master

tcp6 0 0 :::443 :::\* LISTEN 969/nginx: master p

tcp6 0 0 :::993 :::\* LISTEN 804/dovecot

tcp6 0 0 :::995 :::\* LISTEN 804/dovecot

tcp6 0 0 :::587 :::\* LISTEN 2352/master

tcp6 0 0 :::110 :::\* LISTEN 804/dovecot

tcp6 0 0 :::143 :::\* LISTEN 804/dovecot

tcp6 0 0 :::80 :::\* LISTEN 969/nginx: master p

**Logs from mail.log**

Feb 20 07:59:45 rod postfix/submission/smtpd\[7287\]: Anonymous TLS connection established from unknown\[52.125.141.115\]: TLSv1.2 with cipher ECDHE-RSA-AES256-SHA384 (256/256 bits)

Feb 20 07:59:45 rod postfix/submission/smtpd\[7282\]: disconnect from unknown\[52.125.141.115\] ehlo=2 starttls=1 auth=1 quit=1 commands=5

Feb 20 07:59:45 rod postfix/submission/smtpd\[7287\]: disconnect from unknown\[52.125.141.115\] ehlo=2 starttls=1 auth=1 quit=1 commands=5

Feb 20 07:59:50 rod postfix/postscreen\[7283\]: PASS NEW \[52.125.141.115\]:38656

Feb 20 07:59:50 rod postfix/postscreen\[7283\]: PASS OLD \[52.125.141.115\]:38660

Feb 20 07:59:50 rod postfix/smtpd\[7298\]: connect from unknown\[52.125.141.115\]

Feb 20 07:59:50 rod postfix/smtpd\[7297\]: connect from unknown\[52.125.141.115\]

Feb 20 07:59:50 rod postfix/smtpd\[7297\]: Anonymous TLS connection established from unknown\[52.125.141.115\]: TLSv1.2 with cipher ECDHE-RSA-AES256-SHA384 (256/256 bits)

Feb 20 07:59:50 rod postfix/smtpd\[7298\]: Anonymous TLS connection established from unknown\[52.125.141.115\]: TLSv1.2 with cipher ECDHE-RSA-AES256-SHA384 (256/256 bits)

Feb 20 07:59:50 rod postfix/smtpd\[7297\]: disconnect from unknown\[52.125.141.115\] ehlo=2 starttls=1 quit=1 commands=4

Feb 20 07:59:50 rod postfix/smtpd\[7298\]: disconnect from unknown\[52.125.141.115\] ehlo=2 starttls=1 quit=1 commands=4

Feb 20 08:03:10 rod postfix/anvil\[7234\]: statistics: max connection rate 2/60s for (submission:52.125.140.5) at Feb 20 07:59:29

Feb 20 08:03:10 rod postfix/anvil\[7234\]: statistics: max connection count 2 for (submission:52.125.140.5) at Feb 20 07:59:29

Feb 20 08:03:10 rod postfix/anvil\[7234\]: statistics: max cache size 4 at Feb 20 07:59:50

Feb 20 08:06:07 rod postfix/submission/smtpd\[7443\]: connect from unknown\[52.125.140.0\]

Feb 20 08:06:07 rod postfix/submission/smtpd\[7443\]: Anonymous TLS connection established from unknown\[52.125.140.0\]: TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)

Feb 20 08:06:07 rod postfix/submission/smtpd\[7443\]: lost connection after STARTTLS from unknown\[52.125.140.0\]

Feb 20 08:06:07 rod postfix/submission/smtpd\[7443\]: disconnect from unknown\[52.125.140.0\] ehlo=1 starttls=1 commands=2

Feb 20 08:07:13 rod postfix/submission/smtpd\[7443\]: connect from unknown\[52.125.140.0\]

Feb 20 08:07:13 rod postfix/submission/smtpd\[7443\]: Anonymous TLS connection established from unknown\[52.125.140.0\]: TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)

Feb 20 08:07:13 rod postfix/submission/smtpd\[7443\]: lost connection after STARTTLS from unknown\[52.125.140.0\]

Feb 20 08:07:13 rod postfix/submission/smtpd\[7443\]: disconnect from unknown\[52.125.140.0\] ehlo=1 starttls=1 commands=2

Feb 20 08:08:09 rod postfix/postscreen\[7485\]: CONNECT from \[45.143.223.14\]:53448 to \[165.22.193.58\]:25

Feb 20 08:08:09 rod postfix/dnsblog\[7487\]: addr 45.143.223.14 listed by domain zen.spamhaus.org as 127.0.0.3

Feb 20 08:08:09 rod postfix/dnsblog\[7487\]: addr 45.143.223.14 listed by domain zen.spamhaus.org as 127.0.0.11

Feb 20 08:08:09 rod postfix/dnsblog\[7487\]: addr 45.143.223.14 listed by domain zen.spamhaus.org as 127.0.0.4

Feb 20 08:08:15 rod postfix/postscreen\[7485\]: DNSBL rank 3 for \[45.143.223.14\]:53448

Feb 20 08:08:15 rod postfix/postscreen\[7485\]: DISCONNECT \[45.143.223.14\]:53448

Feb 20 08:10:33 rod postfix/anvil\[7447\]: statistics: max connection rate 1/60s for (submission:52.125.140.0) at Feb 20 08:06:07

Feb 20 08:10:33 rod postfix/anvil\[7447\]: statistics: max connection count 1 for (submission:52.125.140.0) at Feb 20 08:06:07

Feb 20 08:10:33 rod postfix/anvil\[7447\]: statistics: max cache size 1 at Feb 20 08:06:07

Feb 20 08:48:04 rod postfix/postscreen\[8591\]: CONNECT from \[218.1.18.154\]:54420 to \[165.22.193.58\]:25

Feb 20 08:48:04 rod postfix/dnsblog\[8592\]: addr 218.1.18.154 listed by domain zen.spamhaus.org as 127.0.0.2

Feb 20 08:48:04 rod postfix/dnsblog\[8592\]: addr 218.1.18.154 listed by domain zen.spamhaus.org as 127.0.0.4

Feb 20 08:48:10 rod postfix/postscreen\[8591\]: DNSBL rank 3 for \[218.1.18.154\]:54420

Feb 20 08:48:10 rod postfix/postscreen\[8591\]: DISCONNECT \[218.1.18.154\]:54420
</code>```

答:
Fixed the connection by

```<code>iptables -I INPUT -p tcp --dport 993 --syn -j ACCEPT
iptables -I INPUT -p tcp --dport 995 --syn -j ACCEPT
</code>```

and same for 593 and 143.
, now another problem:
Client syncs all folders, however emails cannot be sent — mail delivery slip is below:

```<code>This is the mail system at host rod.psmail.
I'm sorry to have to inform you that your message could not
be delivered to one or more recipients. It's attached below.
For further assistance, please send mail to postmaster.
If you do so, please include this problem report. You can
delete your own text from the attached returned message.
The mail system
<rodnekhaev@gmail.com>: host gmail-smtp-in.l.google.com[173.194.69.27] said:
550-5.7.26 This message does not have authentication information or fails
to 550-5.7.26 pass authentication checks. To best protect our users from
spam, the 550-5.7.26 message has been blocked. Please visit 550-5.7.26
https://support.google.com/mail/answer/81126#authentication for more 550
5.7.26 information. y22si1705449edw.131 - gsmtp (in reply to end of DATA
command)
</code>```

Title: iRedMail server no SMTP/IMAP connection

Body:
I have configured an iRedMail server with SSL certificates on my Ubuntu 18.04 machine, but I can't manage to connect my devices (via Outlook or Spark) via SMTP/IMAP protocols.

I have opened ports 593, 143, 993, 995 and still, devices cannot connect to the server.
The error from Spark is as following "a stable connection to the server could not be established".
I have also tried as guided in manual, but no luck.

Logs from netstat

Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name

tcp 0 0 127.0.0.53:53 0.0.0.0:\* LISTEN 644/systemd-resolve

tcp 0 0 0.0.0.0:22 0.0.0.0:\* LISTEN 907/sshd

tcp 0 0 127.0.0.1:24 0.0.0.0:\* LISTEN 804/dovecot

tcp 0 0 0.0.0.0:25 0.0.0.0:\* LISTEN 2352/master

tcp 0 0 0.0.0.0:443 0.0.0.0:\* LISTEN 969/nginx: master p

tcp 0 0 127.0.0.1:8125 0.0.0.0:\* LISTEN 2373/netdata

tcp 0 0 127.0.0.1:4190 0.0.0.0:\* LISTEN 804/dovecot

tcp 0 0 127.0.0.1:19999 0.0.0.0:\* LISTEN 2373/netdata

tcp 1 0 127.0.0.1:20000 0.0.0.0:\* LISTEN 1291/sogod

tcp 0 0 127.0.0.1:7777 0.0.0.0:\* LISTEN 1318/python2

tcp 0 0 0.0.0.0:993 0.0.0.0:\* LISTEN 804/dovecot

tcp 0 0 0.0.0.0:995 0.0.0.0:\* LISTEN 804/dovecot

tcp 0 0 127.0.0.1:10024 0.0.0.0:\* LISTEN 1871/amavisd-new (m

tcp 0 0 127.0.0.1:10025 0.0.0.0:\* LISTEN 2352/master

tcp 0 0 127.0.0.1:10026 0.0.0.0:\* LISTEN 1871/amavisd-new (m

tcp 0 0 127.0.0.1:3306 0.0.0.0:\* LISTEN 1145/mysqld

tcp 0 0 0.0.0.0:587 0.0.0.0:\* LISTEN 2352/master

tcp 0 0 127.0.0.1:10027 0.0.0.0:\* LISTEN 1871/amavisd-new (m

tcp 0 0 127.0.0.1:11211 0.0.0.0:\* LISTEN 844/memcached

tcp 0 0 127.0.0.1:10028 0.0.0.0:\* LISTEN 2352/master

tcp 0 0 127.0.0.1:9998 0.0.0.0:\* LISTEN 1871/amavisd-new (m

tcp 0 0 0.0.0.0:110 0.0.0.0:\* LISTEN 804/dovecot

tcp 0 0 127.0.0.1:7790 0.0.0.0:\* LISTEN 864/uwsgi

tcp 0 0 127.0.0.1:9999 0.0.0.0:\* LISTEN 836/php-fpm: master

tcp 0 0 0.0.0.0:143 0.0.0.0:\* LISTEN 804/dovecot

tcp 0 0 127.0.0.1:7791 0.0.0.0:\* LISTEN 866/uwsgi

tcp 0 0 0.0.0.0:80 0.0.0.0:\* LISTEN 969/nginx: master p

tcp 0 0 127.0.0.1:24242 0.0.0.0:\* LISTEN 804/dovecot

tcp 0 0 127.0.0.1:12340 0.0.0.0:\* LISTEN 804/dovecot

tcp6 0 0 :::21 :::\* LISTEN 5516/vsftpd

tcp6 0 0 :::22 :::\* LISTEN 907/sshd

tcp6 0 0 :::25 :::\* LISTEN 2352/master

tcp6 0 0 :::443 :::\* LISTEN 969/nginx: master p

tcp6 0 0 :::993 :::\* LISTEN 804/dovecot

tcp6 0 0 :::995 :::\* LISTEN 804/dovecot

tcp6 0 0 :::587 :::\* LISTEN 2352/master

tcp6 0 0 :::110 :::\* LISTEN 804/dovecot

tcp6 0 0 :::143 :::\* LISTEN 804/dovecot

tcp6 0 0 :::80 :::\* LISTEN 969/nginx: master p

**Logs from mail.log**

Feb 20 07:59:45 rod postfix/submission/smtpd\[7287\]: Anonymous TLS connection established from unknown\[52.125.141.115\]: TLSv1.2 with cipher ECDHE-RSA-AES256-SHA384 (256/256 bits)

Feb 20 07:59:45 rod postfix/submission/smtpd\[7282\]: disconnect from unknown\[52.125.141.115\] ehlo=2 starttls=1 auth=1 quit=1 commands=5

Feb 20 07:59:45 rod postfix/submission/smtpd\[7287\]: disconnect from unknown\[52.125.141.115\] ehlo=2 starttls=1 auth=1 quit=1 commands=5

Feb 20 07:59:50 rod postfix/postscreen\[7283\]: PASS NEW \[52.125.141.115\]:38656

Feb 20 07:59:50 rod postfix/postscreen\[7283\]: PASS OLD \[52.125.141.115\]:38660

Feb 20 07:59:50 rod postfix/smtpd\[7298\]: connect from unknown\[52.125.141.115\]

Feb 20 07:59:50 rod postfix/smtpd\[7297\]: connect from unknown\[52.125.141.115\]

Feb 20 07:59:50 rod postfix/smtpd\[7297\]: Anonymous TLS connection established from unknown\[52.125.141.115\]: TLSv1.2 with cipher ECDHE-RSA-AES256-SHA384 (256/256 bits)

Feb 20 07:59:50 rod postfix/smtpd\[7298\]: Anonymous TLS connection established from unknown\[52.125.141.115\]: TLSv1.2 with cipher ECDHE-RSA-AES256-SHA384 (256/256 bits)

Feb 20 07:59:50 rod postfix/smtpd\[7297\]: disconnect from unknown\[52.125.141.115\] ehlo=2 starttls=1 quit=1 commands=4

Feb 20 07:59:50 rod postfix/smtpd\[7298\]: disconnect from unknown\[52.125.141.115\] ehlo=2 starttls=1 quit=1 commands=4

Feb 20 08:03:10 rod postfix/anvil\[7234\]: statistics: max connection rate 2/60s for (submission:52.125.140.5) at Feb 20 07:59:29

Feb 20 08:03:10 rod postfix/anvil\[7234\]: statistics: max connection count 2 for (submission:52.125.140.5) at Feb 20 07:59:29

Feb 20 08:03:10 rod postfix/anvil\[7234\]: statistics: max cache size 4 at Feb 20 07:59:50

Feb 20 08:06:07 rod postfix/submission/smtpd\[7443\]: connect from unknown\[52.125.140.0\]

Feb 20 08:06:07 rod postfix/submission/smtpd\[7443\]: Anonymous TLS connection established from unknown\[52.125.140.0\]: TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)

Feb 20 08:06:07 rod postfix/submission/smtpd\[7443\]: lost connection after STARTTLS from unknown\[52.125.140.0\]

Feb 20 08:06:07 rod postfix/submission/smtpd\[7443\]: disconnect from unknown\[52.125.140.0\] ehlo=1 starttls=1 commands=2

Feb 20 08:07:13 rod postfix/submission/smtpd\[7443\]: connect from unknown\[52.125.140.0\]

Feb 20 08:07:13 rod postfix/submission/smtpd\[7443\]: Anonymous TLS connection established from unknown\[52.125.140.0\]: TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)

Feb 20 08:07:13 rod postfix/submission/smtpd\[7443\]: lost connection after STARTTLS from unknown\[52.125.140.0\]

Feb 20 08:07:13 rod postfix/submission/smtpd\[7443\]: disconnect from unknown\[52.125.140.0\] ehlo=1 starttls=1 commands=2

Feb 20 08:08:09 rod postfix/postscreen\[7485\]: CONNECT from \[45.143.223.14\]:53448 to \[165.22.193.58\]:25

Feb 20 08:08:09 rod postfix/dnsblog\[7487\]: addr 45.143.223.14 listed by domain zen.spamhaus.org as 127.0.0.3

Feb 20 08:08:09 rod postfix/dnsblog\[7487\]: addr 45.143.223.14 listed by domain zen.spamhaus.org as 127.0.0.11

Feb 20 08:08:09 rod postfix/dnsblog\[7487\]: addr 45.143.223.14 listed by domain zen.spamhaus.org as 127.0.0.4

Feb 20 08:08:15 rod postfix/postscreen\[7485\]: DNSBL rank 3 for \[45.143.223.14\]:53448

Feb 20 08:08:15 rod postfix/postscreen\[7485\]: DISCONNECT \[45.143.223.14\]:53448

Feb 20 08:10:33 rod postfix/anvil\[7447\]: statistics: max connection rate 1/60s for (submission:52.125.140.0) at Feb 20 08:06:07

Feb 20 08:10:33 rod postfix/anvil\[7447\]: statistics: max connection count 1 for (submission:52.125.140.0) at Feb 20 08:06:07

Feb 20 08:10:33 rod postfix/anvil\[7447\]: statistics: max cache size 1 at Feb 20 08:06:07

Feb 20 08:48:04 rod postfix/postscreen\[8591\]: CONNECT from \[218.1.18.154\]:54420 to \[165.22.193.58\]:25

Feb 20 08:48:04 rod postfix/dnsblog\[8592\]: addr 218.1.18.154 listed by domain zen.spamhaus.org as 127.0.0.2

Feb 20 08:48:04 rod postfix/dnsblog\[8592\]: addr 218.1.18.154 listed by domain zen.spamhaus.org as 127.0.0.4

Feb 20 08:48:10 rod postfix/postscreen\[8591\]: DNSBL rank 3 for \[218.1.18.154\]:54420

Feb 20 08:48:10 rod postfix/postscreen\[8591\]: DISCONNECT \[218.1.18.154\]:54420

Body:
Fixed the connection by

iptables -I INPUT -p tcp --dport 993 --syn -j ACCEPT
iptables -I INPUT -p tcp --dport 995 --syn -j ACCEPT

and same for 593 and 143.
, now another problem:
Client syncs all folders, however emails cannot be sent — mail delivery slip is below:

This is the mail system at host rod.psmail.
I'm sorry to have to inform you that your message could not
be delivered to one or more recipients. It's attached below.
For further assistance, please send mail to postmaster.
If you do so, please include this problem report. You can
delete your own text from the attached returned message.
The mail system
<rodnekhaev@gmail.com>: host gmail-smtp-in.l.google.com[173.194.69.27] said:
550-5.7.26 This message does not have authentication information or fails
to 550-5.7.26 pass authentication checks. To best protect our users from
spam, the 550-5.7.26 message has been blocked. Please visit 550-5.7.26
https://support.google.com/mail/answer/81126#authentication for more 550
5.7.26 information. y22si1705449edw.131 - gsmtp (in reply to end of DATA
command)


问:
How to represent Tcl code output graphically?
Want to represent Tcl output data graphically using tree, graph, block-diagram, flow-chart etc. What will be best way to do this?</p>

答:
Tcl has bindings to a number of GUI toolkits, but by far the most commonly used one is Tk. I've used it to write an IDE in the past (for a very weird graphical programming system that nobody cares about any more) so it is quite capable. (The text hypertext widget and the canvas hypergraphics widget are both very interesting for doing complex applications around.)

But for charting and graphing there are other libraries. In particular, integrations with graphviz and gnuplot are (very!) good ways to make many ways of displaying data that have some integration capabilities with Tk, RBC has some good widgets (especially for live plotting), and there are Tklib modules (especially plotchart) that may also be highly relevant.

You'll need to ask a more specific question to get a more helpful answer. I'm also sure I've missed things.


问:
VS2010 "Add Item" directory change
Is there any way to change the default directory Visual Studio 2010 uses when you add a source file through Add -> New Item?</p>

答: Try going to tools -> options -> Project and Solutions.</p>

Title: VS2010 "Add Item" directory change


问:
create an ID column with randomly generated values in R
I am using the package called mtcars and I want to get a randomly generated number for every observations. I have written a function:

```<code>mtcars$ID <- NULL
for (i in mtcars){
  mtcars$ID <- runif(1, min=0, max=100)
}
</code>```

However, this assigns the same number to all cars.

I tried:

```<code>mtcars$ID <- NULL
for (i in mtcars){
  mtcars$ID[i] <- runif(1, min=0, max=100)
}
</code>```

which results in an error. I would like to get two type of results (two functions):

to assign a random number to each observation

to assign a unique random number to each observation

答:
There are of course a plenty of easier ways to assign random values to ID column.

Seems OP is only interested in the solutions with for loop, then here are some examples to make it

to assign a random number to each observation:

```<code>for (i in seq(nrow(mtcars))){
  mtcars$ID[i] <- runif(1, min=0, max=100) # assign random value which might be duplicated (but with low probability if you don't have super many rows)
}

</code>```

to assign a unique random number to each observation

```<code>for (i in seq(nrow(mtcars))){
  repeat {
    r <- runif(1, min=0, max=100)
    if (!r %in% mtcars$ID) break # if generated random number is not in the existing values, then terminate the loop and go to value assignment in the next step
  }
  mtcars$ID[i] <- r
}
</code>```

Body:
I am using the package called mtcars and I want to get a randomly generated number for every observations. I have written a function:

mtcars$ID <- NULL
for (i in mtcars){
  mtcars$ID <- runif(1, min=0, max=100)
}

However, this assigns the same number to all cars.

I tried:

mtcars$ID <- NULL
for (i in mtcars){
  mtcars$ID[i] <- runif(1, min=0, max=100)
}

which results in an error. I would like to get two type of results (two functions):

to assign a random number to each observation

to assign a unique random number to each observation

Body:
There are of course a plenty of easier ways to assign random values to ID column.

Seems OP is only interested in the solutions with for loop, then here are some examples to make it

to assign a random number to each observation:

for (i in seq(nrow(mtcars))){
  mtcars$ID[i] <- runif(1, min=0, max=100) # assign random value which might be duplicated (but with low probability if you don't have super many rows)
}

to assign a unique random number to each observation

for (i in seq(nrow(mtcars))){
  repeat {
    r <- runif(1, min=0, max=100)
    if (!r %in% mtcars$ID) break # if generated random number is not in the existing values, then terminate the loop and go to value assignment in the next step
  }
  mtcars$ID[i] <- r
}


问:
How to replace only part of a word from a string in Python
I have a list of street names

```<code>streetNames = ['WELSESTRAAT', 'HENDRIKLAAN', 'LOMMERWEG']
</code>```

And another list with street abbreviations

```<code>streetAbbr = [['WEG', 'WG'], ['STRAAT', 'STR'],['LAAN', 'LN']]
</code>```

I am trying to loop through street names and replace straat with str, weg with wg and so on
but I am stuck in the replace part as there is no such method for only part of a word.

```<code>for name in streetNames:
    for abbr in streetAbbr:
        if str(abbr[0]) in str(name):
            name.replace('straat', abbr[1]) #doesn't work
</code>```

答:
```<code>result = [name.replace(abbr[0], abbr[1]) for name in streetNames for abbr in streetAbbr if abbr[0] in name]
</code>```

Body:
I have a list of street names

streetNames = ['WELSESTRAAT', 'HENDRIKLAAN', 'LOMMERWEG']

And another list with street abbreviations

streetAbbr = [['WEG', 'WG'], ['STRAAT', 'STR'],['LAAN', 'LN']]

I am trying to loop through street names and replace straat with str, weg with wg and so on
but I am stuck in the replace part as there is no such method for only part of a word.

for name in streetNames:
    for abbr in streetAbbr:
        if str(abbr[0]) in str(name):
            name.replace('straat', abbr[1]) #doesn't work


问:
How to switch n columns to rows of a r rows pandas dataframe (n*r rows in the final dataframe)?
Let's take this dataframe :

```<code>pd.DataFrame(dict(Col1=["a","c"],Col2=["b","d"],Col3=[1,3],Col4=[2,4]))
  Col1 Col2  Col3  Col4
0    a    b     1     2
1    c    d     3     4
</code>```

I would like to have one row per value in column Col1 and column Col2 (n=2 and r=2 so the expected dataframe have 2*2 = 4 rows).

Expected result :

```<code>    Ind Value  Col3  Col4
0  Col1     a     1     2
1  Col1     c     3     4
2  Col2     b     1     2
3  Col2     d     3     4
</code>```

How please could I do ?

答:
Pandas melt does the job here; the rest just has to do with repositioning and renaming the columns appropriately.

Use pandas melt to transform the dataframe, using Col3 and 4 as the index variables. melt typically converts from wide to long.

Next step - reindex the columns, with variable and value as lead columns.

Finally, rename the columns appropriately.

```<code> (df.melt(id_vars=['Col3','Col4'])
  .reindex(['variable','value','Col3','Col4'],axis=1)
  .rename({'variable':'Ind','value':'Value'},axis=1)
  )

    Ind Value   Col3   Col4
0   Col1    a   1      2
1   Col1    c   3      4
2   Col2    b   1      2
3   Col2    d   3      4
</code>```

Body:
Let's take this dataframe :

pd.DataFrame(dict(Col1=["a","c"],Col2=["b","d"],Col3=[1,3],Col4=[2,4]))
  Col1 Col2  Col3  Col4
0    a    b     1     2
1    c    d     3     4

I would like to have one row per value in column Col1 and column Col2 (n=2 and r=2 so the expected dataframe have 2*2 = 4 rows).

Expected result :

    Ind Value  Col3  Col4
0  Col1     a     1     2
1  Col1     c     3     4
2  Col2     b     1     2
3  Col2     d     3     4

How please could I do ?

Body:
Pandas melt does the job here; the rest just has to do with repositioning and renaming the columns appropriately.

Use pandas melt to transform the dataframe, using Col3 and 4 as the index variables. melt typically converts from wide to long.

Next step - reindex the columns, with variable and value as lead columns.

Finally, rename the columns appropriately.

 (df.melt(id_vars=['Col3','Col4'])
  .reindex(['variable','value','Col3','Col4'],axis=1)
  .rename({'variable':'Ind','value':'Value'},axis=1)
  )

    Ind Value   Col3   Col4
0   Col1    a   1      2
1   Col1    c   3      4
2   Col2    b   1      2
3   Col2    d   3      4