问:
Autocomplete textbox highlighting the typed character in the suggestion list
I have been working on AutoCompleteTextView. I was able to get the suggestion and all in the drop down list as we type.

My question is: Can we highlight the typed character in the suggestion drop down list?

答:
Thanks to vadher jitendra I wrote the same and fixed some bugs.

Changed a dropdown layout to own.

Added showing a full list when clicking inside AutoCompleteTextView.

Fixed a bug of freezing the list when showing (added a check for empty string in highlight).

row_dropdown.xml (item layout):

```<code><?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/text1"
    style="?android:attr/dropDownItemStyle"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginLeft="10dp"
    android:layout_marginRight="10dp"
    android:ellipsize="marquee"
    android:paddingTop="8dp"
    android:paddingBottom="8dp"
    android:singleLine="true"
    android:textColor="#333333"
    android:textSize="15sp"
    tools:text="text"
    tools:textAppearance="?android:attr/textAppearanceLargePopupMenu" />
</code>```

To filter a list when typing we should implement ArrayAdapter. It depends on items (T class). You can later use AutoCompleteAdapter<String> or any data class you like.

AutoCompleteAdapter:

```<code>import android.content.Context;
import android.graphics.Typeface;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.style.StyleSpan;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Filter;
import android.widget.Filterable;
import android.widget.TextView;

import androidx.annotation.IdRes;
import androidx.annotation.LayoutRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import java.text.Normalizer;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

public class AutoCompleteAdapter<T> extends ArrayAdapter<T> implements Filterable {

    private Context context;
    @LayoutRes
    private int layoutRes;
    @IdRes
    private int textViewResId;
    private ArrayList<T> fullList;
    private ArrayList<T> originalValues;
    private ArrayFilter filter;
    private LayoutInflater inflater;
    private String query = "";

    public AutoCompleteAdapter(@NonNull Context context, @LayoutRes int resource, @IdRes int textViewResourceId, @NonNull List<T> objects) {
        super(context, resource, textViewResourceId, objects);
        this.context = context;
        layoutRes = resource;
        textViewResId = textViewResourceId;
        fullList = (ArrayList<T>) objects;
        originalValues = new ArrayList<>(fullList);
        inflater = LayoutInflater.from(context);
    }

    @Override
    public int getCount() {
        return fullList.size();
    }

    @Override
    public T getItem(int position) {
        return fullList.get(position);
    }

    /**
     * You can use either
     * vadher jitendra method (getView)
     * or get the method from ArrayAdapter.java.
     */
//    @NotNull
//    @Override
//    public View getView(int position, View convertView, ViewGroup parent) {
//        View view = convertView;
//        T item = getItem(position);
//        Log.d("item", "" + item);
//        if (convertView == null) {
//            convertView = view = inflater.inflate(layoutRes, null);
//        }
//        // Lookup view for data population
//        TextView myTv = convertView.findViewById(textViewResId);
//        myTv.setText(highlight(query, item));
//        return view;
//    }
    @Override
    public @NonNull
    View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
        return createViewFromResource(inflater, position, convertView, parent, layoutRes);
    }

    private @NonNull
    View createViewFromResource(@NonNull LayoutInflater inflater, int position,
                                @Nullable View convertView, @NonNull ViewGroup parent, int resource) {
        final View view;
        final TextView text;

        if (convertView == null) {
            view = inflater.inflate(resource, parent, false);
        } else {
            view = convertView;
        }

        try {
            if (textViewResId == 0) {
                //  If no custom field is assigned, assume the whole resource is a TextView
                text = (TextView) view;
            } else {
                //  Otherwise, find the TextView field within the layout
                text = view.findViewById(textViewResId);

                if (text == null) {
                    throw new RuntimeException("Failed to find view with ID "
                            + context.getResources().getResourceName(textViewResId)
                            + " in item layout");
                }
            }
        } catch (ClassCastException e) {
            Log.e("ArrayAdapter", "You must supply a resource ID for a TextView");
            throw new IllegalStateException(
                    "ArrayAdapter requires the resource ID to be a TextView", e);
        }

        final T item = getItem(position);
        text.setText(highlight(query, item.toString()));
//        if (item instanceof CharSequence) {
//            text.setText(highlight(query, (CharSequence) item));
//        } else {
//            text.setText(item.toString());
//        }

        return view;
    }

    @Override
    public @NonNull
    Filter getFilter() {
        if (filter == null) {
            filter = new ArrayFilter();
        }
        return filter;
    }

    private class ArrayFilter extends Filter {
        private final Object lock = new Object();

        @Override
        protected FilterResults performFiltering(CharSequence prefix) {
            FilterResults results = new FilterResults();
            if (prefix == null) {
                query = "";
            } else {
                query = prefix.toString();
            }
            if (originalValues == null) {
                synchronized (lock) {
                    originalValues = new ArrayList<>(fullList);
                }
            }

            if (prefix == null || prefix.length() == 0) {
                synchronized (lock) {
                    ArrayList<T> list = new ArrayList<>(originalValues);
                    results.values = list;
                    results.count = list.size();
                }
            } else {
                final String prefixString = prefix.toString().toLowerCase();
                ArrayList<T> values = originalValues;
                int count = values.size();

                ArrayList<T> newValues = new ArrayList<>(count);

                for (int i = 0; i < count; i++) {
                    T item = values.get(i);
                    if (item.toString().toLowerCase().contains(prefixString)) {
                        newValues.add(item);
                    }

                }

                results.values = newValues;
                results.count = newValues.size();
            }

            return results;
        }

        @SuppressWarnings("unchecked")
        @Override
        protected void publishResults(CharSequence constraint, FilterResults results) {
            if (results.values != null) {
                fullList = (ArrayList<T>) results.values;
            } else {
                fullList = new ArrayList<>();
            }
            if (results.count > 0) {
                notifyDataSetChanged();
            } else {
                notifyDataSetInvalidated();
            }
        }

    }

    private static CharSequence highlight(@NonNull String search, @NonNull CharSequence originalText) {
        if (search.isEmpty())
            return originalText;

        // ignore case and accents
        // the same thing should have been done for the search text
        String normalizedText = Normalizer
                .normalize(originalText, Normalizer.Form.NFD)
                .replaceAll("\\p{InCombiningDiacriticalMarks}+", "")
                .toLowerCase(Locale.ENGLISH);

        int start = normalizedText.indexOf(search.toLowerCase(Locale.ENGLISH));
        if (start < 0) {
            // not found, nothing to do
            return originalText;
        } else {
            // highlight each appearance in the original text
            // while searching in normalized text
            Spannable highlighted = new SpannableString(originalText);
            while (start >= 0) {
                int spanStart = Math.min(start, originalText.length());
                int spanEnd = Math.min(start + search.length(),
                        originalText.length());

                highlighted.setSpan(new StyleSpan(Typeface.BOLD), spanStart, spanEnd, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

                start = normalizedText.indexOf(search, spanEnd);
            }

            return highlighted;
        }
    }
}
</code>```

In order to show dropdown list when clicked inside AutoCompleteTextView we need to override setOnTouchListener as described in https://stackoverflow.com/a/26036902/2914140. Lint also prints warnings, so we have to write a custom view:

```<code>import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;

import androidx.appcompat.widget.AppCompatAutoCompleteTextView;

/*
Avoids a warning "Custom view `AutoCompleteTextView` has setOnTouchListener called on it but does not override performClick".
 */
public class AutoCompleteTV extends AppCompatAutoCompleteTextView {

    public AutoCompleteTV(Context context) {
        super(context);
    }

    public AutoCompleteTV(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public AutoCompleteTV(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_DOWN) {
            performClick();
        }
        return super.onTouchEvent(event);
    }

    @Override
    public boolean performClick() {
        super.performClick();
        return true;
    }
}
</code>```

Then use it in activity_main.xml:

```<code><?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <com.google.android.material.textfield.TextInputLayout
        style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <com.example.autocompletetextview1.AutoCompleteTV
            android:id="@+id/languages"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginLeft="15dp"
            android:layout_marginRight="15dp"
            android:completionThreshold="1"
            android:hint="language"
            android:imeOptions="actionNext"
            android:maxLines="1"
            android:paddingLeft="10dp"
            android:paddingTop="15dp"
            android:paddingRight="10dp"
            android:paddingBottom="15dp"
            android:singleLine="true"
            android:textColor="#333333"
            android:textColorHint="#808080"
            android:textSize="12sp" />

    </com.google.android.material.textfield.TextInputLayout>

</LinearLayout>
</code>```

I use TextInputLayout here for better decoration, in this case we have to add Material Design Components:

in build.gradle:

```<code>implementation 'com.google.android.material:material:1.3.0-alpha01'
</code>```

and in styles.xml:

```<code><style name="AppTheme" parent="Theme.MaterialComponents.Light.DarkActionBar">
...
</code>```

MainActivity:

```<code>import android.os.Bundle;
import android.view.MotionEvent;
import android.widget.AutoCompleteTextView;

import androidx.appcompat.app.AppCompatActivity;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity {

    String[] items = {"C", "C++", "Java", "C#", "PHP", "JavaScript", "jQuery", "AJAX", "JSON"};

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        List<DataClass> wordList = new ArrayList<>();
        for (int i = 0; i < items.length; i++) {
            DataClass data = new DataClass(i, items[i]);
            wordList.add(data);
        }
        AutoCompleteAdapter<DataClass> adapter = new AutoCompleteAdapter<>(this,
                R.layout.row_dropdown, R.id.text1, wordList);
        //adapter.setDropDownViewResource(R.layout.row_dropdown);
        AutoCompleteTV acTextView = findViewById(R.id.languages);
        acTextView.setThreshold(1);
        acTextView.setAdapter(adapter);
        acTextView.setText("Java");
        acTextView.setOnTouchListener((v, event) -> {
                    if (event.getAction() == MotionEvent.ACTION_DOWN) {
                        ((AutoCompleteTextView) v).showDropDown();
                        v.requestFocus();
                        v.performClick(); // Added to avoid warning "onTouch lambda should call View#performClick when a click is detected".
                    }
                    return false;
                }
        );
    }
}
</code>```

Body:
Thanks to vadher jitendra I wrote the same and fixed some bugs.

Changed a dropdown layout to own.

Added showing a full list when clicking inside AutoCompleteTextView.

Fixed a bug of freezing the list when showing (added a check for empty string in highlight).

row_dropdown.xml (item layout):

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/text1"
    style="?android:attr/dropDownItemStyle"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginLeft="10dp"
    android:layout_marginRight="10dp"
    android:ellipsize="marquee"
    android:paddingTop="8dp"
    android:paddingBottom="8dp"
    android:singleLine="true"
    android:textColor="#333333"
    android:textSize="15sp"
    tools:text="text"
    tools:textAppearance="?android:attr/textAppearanceLargePopupMenu" />

To filter a list when typing we should implement ArrayAdapter. It depends on items (T class). You can later use AutoCompleteAdapter<String> or any data class you like.

AutoCompleteAdapter:

import android.content.Context;
import android.graphics.Typeface;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.style.StyleSpan;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Filter;
import android.widget.Filterable;
import android.widget.TextView;

import androidx.annotation.IdRes;
import androidx.annotation.LayoutRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import java.text.Normalizer;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

public class AutoCompleteAdapter<T> extends ArrayAdapter<T> implements Filterable {

    private Context context;
    @LayoutRes
    private int layoutRes;
    @IdRes
    private int textViewResId;
    private ArrayList<T> fullList;
    private ArrayList<T> originalValues;
    private ArrayFilter filter;
    private LayoutInflater inflater;
    private String query = "";

    public AutoCompleteAdapter(@NonNull Context context, @LayoutRes int resource, @IdRes int textViewResourceId, @NonNull List<T> objects) {
        super(context, resource, textViewResourceId, objects);
        this.context = context;
        layoutRes = resource;
        textViewResId = textViewResourceId;
        fullList = (ArrayList<T>) objects;
        originalValues = new ArrayList<>(fullList);
        inflater = LayoutInflater.from(context);
    }

    @Override
    public int getCount() {
        return fullList.size();
    }

    @Override
    public T getItem(int position) {
        return fullList.get(position);
    }

    /**
     * You can use either
     * vadher jitendra method (getView)
     * or get the method from ArrayAdapter.java.
     */
//    @NotNull
//    @Override
//    public View getView(int position, View convertView, ViewGroup parent) {
//        View view = convertView;
//        T item = getItem(position);
//        Log.d("item", "" + item);
//        if (convertView == null) {
//            convertView = view = inflater.inflate(layoutRes, null);
//        }
//        // Lookup view for data population
//        TextView myTv = convertView.findViewById(textViewResId);
//        myTv.setText(highlight(query, item));
//        return view;
//    }
    @Override
    public @NonNull
    View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
        return createViewFromResource(inflater, position, convertView, parent, layoutRes);
    }

    private @NonNull
    View createViewFromResource(@NonNull LayoutInflater inflater, int position,
                                @Nullable View convertView, @NonNull ViewGroup parent, int resource) {
        final View view;
        final TextView text;

        if (convertView == null) {
            view = inflater.inflate(resource, parent, false);
        } else {
            view = convertView;
        }

        try {
            if (textViewResId == 0) {
                //  If no custom field is assigned, assume the whole resource is a TextView
                text = (TextView) view;
            } else {
                //  Otherwise, find the TextView field within the layout
                text = view.findViewById(textViewResId);

                if (text == null) {
                    throw new RuntimeException("Failed to find view with ID "
                            + context.getResources().getResourceName(textViewResId)
                            + " in item layout");
                }
            }
        } catch (ClassCastException e) {
            Log.e("ArrayAdapter", "You must supply a resource ID for a TextView");
            throw new IllegalStateException(
                    "ArrayAdapter requires the resource ID to be a TextView", e);
        }

        final T item = getItem(position);
        text.setText(highlight(query, item.toString()));
//        if (item instanceof CharSequence) {
//            text.setText(highlight(query, (CharSequence) item));
//        } else {
//            text.setText(item.toString());
//        }

        return view;
    }

    @Override
    public @NonNull
    Filter getFilter() {
        if (filter == null) {
            filter = new ArrayFilter();
        }
        return filter;
    }

    private class ArrayFilter extends Filter {
        private final Object lock = new Object();

        @Override
        protected FilterResults performFiltering(CharSequence prefix) {
            FilterResults results = new FilterResults();
            if (prefix == null) {
                query = "";
            } else {
                query = prefix.toString();
            }
            if (originalValues == null) {
                synchronized (lock) {
                    originalValues = new ArrayList<>(fullList);
                }
            }

            if (prefix == null || prefix.length() == 0) {
                synchronized (lock) {
                    ArrayList<T> list = new ArrayList<>(originalValues);
                    results.values = list;
                    results.count = list.size();
                }
            } else {
                final String prefixString = prefix.toString().toLowerCase();
                ArrayList<T> values = originalValues;
                int count = values.size();

                ArrayList<T> newValues = new ArrayList<>(count);

                for (int i = 0; i < count; i++) {
                    T item = values.get(i);
                    if (item.toString().toLowerCase().contains(prefixString)) {
                        newValues.add(item);
                    }

                }

                results.values = newValues;
                results.count = newValues.size();
            }

            return results;
        }

        @SuppressWarnings("unchecked")
        @Override
        protected void publishResults(CharSequence constraint, FilterResults results) {
            if (results.values != null) {
                fullList = (ArrayList<T>) results.values;
            } else {
                fullList = new ArrayList<>();
            }
            if (results.count > 0) {
                notifyDataSetChanged();
            } else {
                notifyDataSetInvalidated();
            }
        }

    }

    private static CharSequence highlight(@NonNull String search, @NonNull CharSequence originalText) {
        if (search.isEmpty())
            return originalText;

        // ignore case and accents
        // the same thing should have been done for the search text
        String normalizedText = Normalizer
                .normalize(originalText, Normalizer.Form.NFD)
                .replaceAll("\\p{InCombiningDiacriticalMarks}+", "")
                .toLowerCase(Locale.ENGLISH);

        int start = normalizedText.indexOf(search.toLowerCase(Locale.ENGLISH));
        if (start < 0) {
            // not found, nothing to do
            return originalText;
        } else {
            // highlight each appearance in the original text
            // while searching in normalized text
            Spannable highlighted = new SpannableString(originalText);
            while (start >= 0) {
                int spanStart = Math.min(start, originalText.length());
                int spanEnd = Math.min(start + search.length(),
                        originalText.length());

                highlighted.setSpan(new StyleSpan(Typeface.BOLD), spanStart, spanEnd, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

                start = normalizedText.indexOf(search, spanEnd);
            }

            return highlighted;
        }
    }
}

In order to show dropdown list when clicked inside AutoCompleteTextView we need to override setOnTouchListener as described in https://stackoverflow.com/a/26036902/2914140. Lint also prints warnings, so we have to write a custom view:

import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;

import androidx.appcompat.widget.AppCompatAutoCompleteTextView;

/*
Avoids a warning "Custom view `AutoCompleteTextView` has setOnTouchListener called on it but does not override performClick".
 */
public class AutoCompleteTV extends AppCompatAutoCompleteTextView {

    public AutoCompleteTV(Context context) {
        super(context);
    }

    public AutoCompleteTV(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public AutoCompleteTV(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_DOWN) {
            performClick();
        }
        return super.onTouchEvent(event);
    }

    @Override
    public boolean performClick() {
        super.performClick();
        return true;
    }
}

Then use it in activity_main.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <com.google.android.material.textfield.TextInputLayout
        style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <com.example.autocompletetextview1.AutoCompleteTV
            android:id="@+id/languages"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginLeft="15dp"
            android:layout_marginRight="15dp"
            android:completionThreshold="1"
            android:hint="language"
            android:imeOptions="actionNext"
            android:maxLines="1"
            android:paddingLeft="10dp"
            android:paddingTop="15dp"
            android:paddingRight="10dp"
            android:paddingBottom="15dp"
            android:singleLine="true"
            android:textColor="#333333"
            android:textColorHint="#808080"
            android:textSize="12sp" />

    </com.google.android.material.textfield.TextInputLayout>

</LinearLayout>

I use TextInputLayout here for better decoration, in this case we have to add Material Design Components:

in build.gradle:

implementation 'com.google.android.material:material:1.3.0-alpha01'

and in styles.xml:

<style name="AppTheme" parent="Theme.MaterialComponents.Light.DarkActionBar">
...

MainActivity:

import android.os.Bundle;
import android.view.MotionEvent;
import android.widget.AutoCompleteTextView;

import androidx.appcompat.app.AppCompatActivity;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity {

    String[] items = {"C", "C++", "Java", "C#", "PHP", "JavaScript", "jQuery", "AJAX", "JSON"};

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        List<DataClass> wordList = new ArrayList<>();
        for (int i = 0; i < items.length; i++) {
            DataClass data = new DataClass(i, items[i]);
            wordList.add(data);
        }
        AutoCompleteAdapter<DataClass> adapter = new AutoCompleteAdapter<>(this,
                R.layout.row_dropdown, R.id.text1, wordList);
        //adapter.setDropDownViewResource(R.layout.row_dropdown);
        AutoCompleteTV acTextView = findViewById(R.id.languages);
        acTextView.setThreshold(1);
        acTextView.setAdapter(adapter);
        acTextView.setText("Java");
        acTextView.setOnTouchListener((v, event) -> {
                    if (event.getAction() == MotionEvent.ACTION_DOWN) {
                        ((AutoCompleteTextView) v).showDropDown();
                        v.requestFocus();
                        v.performClick(); // Added to avoid warning "onTouch lambda should call View#performClick when a click is detected".
                    }
                    return false;
                }
        );
    }
}


来源: stackexchange

问:
Submitting a HTML form in and onload function
I want send a form as soon as the page is loaded. All variables in the form are written dynamically and there is no button for submitting.

Does following JS script work in all browsers ?

```<code><script type='text/javascript'> window.onload = function(){ window.document.forms[0].submit(); }; </script>
</code>```

I doubt window.onload will work in all without any problems.

Thanks in advance...

答:
If you're worried about compatibility in all browsers, how about using jQuery's ready function?</p>

```<code><script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js"></script>
<script type="text/javascript">
  $(document).ready(function() {
    window.document.forms[0].submit();
  });
</script>
</code>```

ContentLicense: CC BY-SA 3.0

Body:
I want send a form as soon as the page is loaded. All variables in the form are written dynamically and there is no button for submitting.

Does following JS script work in all browsers ?

I doubt window.onload will work in all without any problems.

Thanks in advance...

Body:
If you're worried about compatibility in all browsers, how about using jQuery's ready function?

<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js"></script>
<script type="text/javascript">
  $(document).ready(function() {
    window.document.forms[0].submit();
  });
</script>


问:
Removing days and hours from a countdown timer
I'm using a countdown timer from this jQuery file but I want to remove the days and hours from it so it only shows minutes and seconds. Can anyone help me out? The digits are displayed from a png file which creates a flip board effect as it displays the countdown.

jQuery.fn.countdown = function(userOptions)
{
  // Default options
  var options = {
    stepTime: 60,
    // startTime and format MUST follow the same format.
    // also you cannot specify a format unordered (e.g. hh:ss:mm is wrong)
    format: "dd:hh:mm:ss",
    startTime: "01:12:32:55",
    digitImages: 6,
    digitWidth: 53,
    digitHeight: 77,
    timerEnd: function(){},
    image: "digits.png"
  };
  var digits = [], interval;

  // Draw digits in given container
  var createDigits = function(where)
  {
    var c = 0;
    // Iterate each startTime digit, if it is not a digit
    // we'll asume that it's a separator
    for (var i = 0; i < options.startTime.length; i++)
    {
      if (parseInt(options.startTime[i]) >= 0)
      {
        elem = $('
').css({
          height: options.digitHeight * options.digitImages * 10,
          float: 'left', background: 'url(\'' + options.image + '\')',
          width: options.digitWidth});
        digits.push(elem);
        margin(c, -((parseInt(options.startTime[i]) * options.digitHeight *
                              options.digitImages)));
        digits[c].__max = 9;
        // Add max digits, for example, first digit of minutes (mm) has
        // a max of 5. Conditional max is used when the left digit has reach
        // the max. For example second "hours" digit has a conditional max of 4
        switch (options.format[i]) {
          case 'h':
            digits[c].__max = (c % 2 == 0) ? 2: 9;
            if (c % 2 == 0)
              digits[c].__condmax = 4;
            break;
          case 'd':
            digits[c].__max = 9;
            break;
          case 'm':
          case 's':
            digits[c].__max = (c % 2 == 0) ? 5: 9;
        }
        ++c;
      }
      else
        elem = $('
').css({float: 'left'})
                .text(options.startTime[i]);

      where.append(elem)
    }
  };

  // Set or get element margin
  var margin = function(elem, val)
  {
    if (val !== undefined)
      return digits[elem].css({'marginTop': val + 'px'});

    return parseInt(digits[elem].css('marginTop').replace('px', ''));
  };

  // Makes the movement. This is done by "digitImages" steps.
  var moveStep = function(elem)
  {
    digits[elem]._digitInitial = -(digits[elem].__max * options.digitHeight * options.digitImages);
    return function _move() {
      mtop = margin(elem) + options.digitHeight;
      if (mtop == options.digitHeight) {
        margin(elem, digits[elem]._digitInitial);
        if (elem > 0) moveStep(elem - 1)();
        else
        {
          clearInterval(interval);
          for (var i=0; i < digits.length; i++) margin(i, 0);
          options.timerEnd();
          return;
        }
        if ((elem > 0) && (digits[elem].__condmax !== undefined) &&
            (digits[elem - 1]._digitInitial == margin(elem - 1)))
          margin(elem, -(digits[elem].__condmax * options.digitHeight * options.digitImages));
        return;
      }

      margin(elem, mtop);
      if (margin(elem) / options.digitHeight % options.digitImages != 0)
        setTimeout(_move, options.stepTime);

      if (mtop == 0) digits[elem].__ismax = true;
    }
  };

  $.extend(options, userOptions);
  this.css({height: options.digitHeight, overflow: 'hidden'});
  createDigits(this);
  interval = setInterval(moveStep(digits.length - 1), 1000);
};```
<pre class="snippet-code-html lang-html prettyprint-override"><code><html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
  <head>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
    <title>Countdown that doesn't sucks</title>
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3/jquery.min.js" type="text/javascript" charset="utf-8"></script>
    <script src="js/jquery.countdown.js" type="text/javascript" charset="utf-8"></script>
    <script type="text/javascript">
      $(function(){
        $('#counter').countdown({
          image: 'img/digits.png',
          startTime: '00:00:05:00'
        });

      });
    </script>

    <style type="text/css">
      br { clear: both; }
      .cntSeparator {
        font-size: 54px;
        margin: 10px 7px;
        color: #000;
      }
      .desc { margin: 7px 3px; }
      .desc div {
        float: left;
        font-family: Arial;
        width: 70px;
        margin-right: 65px;
        font-size: 13px;
        font-weight: bold;
        color: #000;
      }
    </style>
  </head>
<body></code>```

答:
The countdown generates html inside the loop for (var i = 0; i < options.startTime.length; i++){} and it works on the basis of your init input startTime, so in your case "00:00:05:00". instead of full length you just need to pass "05:00" will work for you.

Here the changed code.

```<code><script type="text/javascript">
  $(function(){
    $('#counter').countdown({
      image: 'img/digits.png',
      startTime: '05:00'
    });
  });
</script>
</code>```

ContentLicense: CC BY-SA 4.0

Body:
I'm using a countdown timer from this jQuery file but I want to remove the days and hours from it so it only shows minutes and seconds. Can anyone help me out? The digits are displayed from a png file which creates a flip board effect as it displays the countdown.

jQuery.fn.countdown = function(userOptions)
{
  // Default options
  var options = {
    stepTime: 60,
    // startTime and format MUST follow the same format.
    // also you cannot specify a format unordered (e.g. hh:ss:mm is wrong)
    format: "dd:hh:mm:ss",
    startTime: "01:12:32:55",
    digitImages: 6,
    digitWidth: 53,
    digitHeight: 77,
    timerEnd: function(){},
    image: "digits.png"
  };
  var digits = [], interval;

  // Draw digits in given container
  var createDigits = function(where)
  {
    var c = 0;
    // Iterate each startTime digit, if it is not a digit
    // we'll asume that it's a separator
    for (var i = 0; i < options.startTime.length; i++)
    {
      if (parseInt(options.startTime[i]) >= 0)
      {
        elem = $('
').css({
          height: options.digitHeight * options.digitImages * 10,
          float: 'left', background: 'url(\'' + options.image + '\')',
          width: options.digitWidth});
        digits.push(elem);
        margin(c, -((parseInt(options.startTime[i]) * options.digitHeight *
                              options.digitImages)));
        digits[c].__max = 9;
        // Add max digits, for example, first digit of minutes (mm) has
        // a max of 5. Conditional max is used when the left digit has reach
        // the max. For example second "hours" digit has a conditional max of 4
        switch (options.format[i]) {
          case 'h':
            digits[c].__max = (c % 2 == 0) ? 2: 9;
            if (c % 2 == 0)
              digits[c].__condmax = 4;
            break;
          case 'd':
            digits[c].__max = 9;
            break;
          case 'm':
          case 's':
            digits[c].__max = (c % 2 == 0) ? 5: 9;
        }
        ++c;
      }
      else
        elem = $('
').css({float: 'left'})
                .text(options.startTime[i]);

      where.append(elem)
    }
  };

  // Set or get element margin
  var margin = function(elem, val)
  {
    if (val !== undefined)
      return digits[elem].css({'marginTop': val + 'px'});

    return parseInt(digits[elem].css('marginTop').replace('px', ''));
  };

  // Makes the movement. This is done by "digitImages" steps.
  var moveStep = function(elem)
  {
    digits[elem]._digitInitial = -(digits[elem].__max * options.digitHeight * options.digitImages);
    return function _move() {
      mtop = margin(elem) + options.digitHeight;
      if (mtop == options.digitHeight) {
        margin(elem, digits[elem]._digitInitial);
        if (elem > 0) moveStep(elem - 1)();
        else
        {
          clearInterval(interval);
          for (var i=0; i < digits.length; i++) margin(i, 0);
          options.timerEnd();
          return;
        }
        if ((elem > 0) && (digits[elem].__condmax !== undefined) &&
            (digits[elem - 1]._digitInitial == margin(elem - 1)))
          margin(elem, -(digits[elem].__condmax * options.digitHeight * options.digitImages));
        return;
      }

      margin(elem, mtop);
      if (margin(elem) / options.digitHeight % options.digitImages != 0)
        setTimeout(_move, options.stepTime);

      if (mtop == 0) digits[elem].__ismax = true;
    }
  };

  $.extend(options, userOptions);
  this.css({height: options.digitHeight, overflow: 'hidden'});
  createDigits(this);
  interval = setInterval(moveStep(digits.length - 1), 1000);
};

    <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
    <title>Countdown that doesn't sucks</title>

Body:
The countdown generates html inside the loop for (var i = 0; i < options.startTime.length; i++){} and it works on the basis of your init input startTime, so in your case "00:00:05:00". instead of full length you just need to pass "05:00" will work for you.

Here the changed code.

<script type="text/javascript">
  $(function(){
    $('#counter').countdown({
      image: 'img/digits.png',
      startTime: '05:00'
    });
  });
</script>


问:
How do I create a column in a pandas dataframe using values from two rows?
How do I do this operation?

Initial Df :

```<code>    A B C D
0   0 1 0 0
1   1 1 1 1
2   0 0 1 1
3   0 1 0 1
4   1 1 0 0
5   1 1 1 0
</code>```

Final Df :

```<code>    A B C D Param1 Param2 Param3
0   0 1 0 0      0      0      0
1   1 1 1 1      3      1      0
2   0 0 1 1      0      2      2
3   0 1 0 1      1      1      1
4   1 1 0 0      1      1      1
5   1 1 1 0      1      2      0
</code>```

Basically what I want to do is compare values on two consecutive rows and store the count of those comparison in a new column.

Details of the calculation :

    For the first row (index 0): Param1, Param2, Param3 will be equal to 0

Param1 : This is the count of the number of times a 0 from preview row changed to 1 in the current row, example(look at index 1) : three 0 from index 0 converts to 1, in index 1, hence Param1 for index 1 = 3

Param2 : This is the count of the number of 1 from previous row which remain unchanged in the current row, example(look at index 3) : one 1 from index 2 remains unchanged, in index 3, hence Param2 for index 3 = 1

Param3 : This is the count of the number of 1 from previous row which changed to 0 in the current row, example(look at index 2) : two 1 from index 1 changed to 0, in index 2, hence Param3 for index 3 = 2

Body:
How do I do this operation?

Initial Df :

    A B C D
0   0 1 0 0
1   1 1 1 1
2   0 0 1 1
3   0 1 0 1
4   1 1 0 0
5   1 1 1 0

Final Df :

    A B C D Param1 Param2 Param3
0   0 1 0 0      0      0      0
1   1 1 1 1      3      1      0
2   0 0 1 1      0      2      2
3   0 1 0 1      1      1      1
4   1 1 0 0      1      1      1
5   1 1 1 0      1      2      0

Basically what I want to do is compare values on two consecutive rows and store the count of those comparison in a new column.

Details of the calculation :

    For the first row (index 0): Param1, Param2, Param3 will be equal to 0

Param1 : This is the count of the number of times a 0 from preview row changed to 1 in the current row, example(look at index 1) : three 0 from index 0 converts to 1, in index 1, hence Param1 for index 1 = 3

Param2 : This is the count of the number of 1 from previous row which remain unchanged in the current row, example(look at index 3) : one 1 from index 2 remains unchanged, in index 3, hence Param2 for index 3 = 1

Param3 : This is the count of the number of 1 from previous row which changed to 0 in the current row, example(look at index 2) : two 1 from index 1 changed to 0, in index 2, hence Param3 for index 3 = 2

Body:
Try this:

shift = df.shift()
df['Param1'] = (df.eq(1) & shift.eq(0)).sum(1).astype(int)
df['Param2'] = (df.eq(1) & shift.eq(1)).sum(1).astype(int)
df['Param3'] = (df.eq(0) & shift.eq(1)).sum(1).astype(int)

Output:

   A  B  C  D  Param1  Param2  Param3
0  0  1  0  0       0       0       0
1  1  1  1  1       3       1       0
2  0  0  1  1       0       2       2
3  0  1  0  1       1       1       1
4  1  1  0  0       1       1       1
5  1  1  1  0       1       2       0


问:
Type '<T>(array: T[], pred: (x: T) => boolean, index: number) => void' is not assignable to type '() => void'
I'm trying to create an extension method for Array.

This is what I've created:

```<code>interface Array<T> {
    moveServiceBranchInArray(): void;
}

Array.prototype.moveServiceBranchInArray = function<T> (array: T[], pred: (x: T) => boolean, index: number): void
{
    const curPos: number = array.findIndex(pred);
    index = Math.max(Math.min(index, array.length - 1), 0);

    if (curPos < 0) {
      return;
    }
    [array[curPos], array[index]] = [array[index], array[curPos]];
}
</code>```

Unfortunately I'm getting the error

"Type
'(array: T[], pred: (x: T) => boolean, index: number) => void' is not assignable to type '() => void'."

as shown in the title.  What gives, help appreciated.

答:
Your interface has a method that takes no parameter, hence () => void, but in the implementation you get some parameters, specifically with the signature (array: T[], pred: (x: T) => boolean, index: number) => void.

That is exactly what the compiler is trying to tell you.

Fixing the interface to make it match your implementation should be enough.

Body:
I'm trying to create an extension method for Array.

This is what I've created:

interface Array<T> {
    moveServiceBranchInArray(): void;
}

Array.prototype.moveServiceBranchInArray = function<T> (array: T[], pred: (x: T) => boolean, index: number): void
{
    const curPos: number = array.findIndex(pred);
    index = Math.max(Math.min(index, array.length - 1), 0);

    if (curPos < 0) {
      return;
    }
    [array[curPos], array[index]] = [array[index], array[curPos]];
}

Unfortunately I'm getting the error

"Type
'(array: T[], pred: (x: T) => boolean, index: number) => void' is not assignable to type '() => void'."

as shown in the title.  What gives, help appreciated.


问:
C# Windows Form displaying PDF file use Ppdfview4net (Display the first page only)
I am using Ppdfview4net to display PDF file, the issue that I have and not able to find a solution the   Ppdfview4net display the first page only. However, when checking the PDF file it contains more than one page.

```<code>        public void LoadDocument(Stream fileNameStream, DisplayMode displayMode)
    {
        ShowHideLoaderForm(true);
        DisplayMode = displayMode;
        SetDisplayMode();
        pdfDocument.Load(fileNameStream);
        BindAnnotations();
        ShowHideLoaderForm(false);
    }
</code>```

答:
The PageLayout set in the PDF file is SinglePage so PDFView4NET displays a single page. You can switch between pages by setting the PageNumber property.

You can display all pages and navigate between them using the scrollbar if you set the PageDisplayLayout property on the viewer to OneColumn.

Disclaimer: I work for the company that develops PDFView4NET.

Body:
I am using Ppdfview4net to display PDF file, the issue that I have and not able to find a solution the   Ppdfview4net display the first page only. However, when checking the PDF file it contains more than one page.

        public void LoadDocument(Stream fileNameStream, DisplayMode displayMode)
    {
        ShowHideLoaderForm(true);
        DisplayMode = displayMode;
        SetDisplayMode();
        pdfDocument.Load(fileNameStream);
        BindAnnotations();
        ShowHideLoaderForm(false);
    }


问:
Group by all columns in a data.table
I'm working with iris data.table in R.

To remind how it looks I paste six five rows here

```<code>   Sepal.Length Sepal.Width Petal.Length Petal.Width Species
1:          5.1         3.5          1.4         0.2  setosa
2:          4.9         3.0          1.4         0.2  setosa
3:          4.7         3.2          1.3         0.2  setosa
4:          4.6         3.1          1.5         0.2  setosa
5:          5.0         3.6          1.4         0.2  setosa
6:          5.4         3.9          1.7         0.4  setosa
</code>```

I would like to calculate the number of rows, grouped by all columns. Of course we may write all variables in by, like this:

```<code>iris[, .(Freq = .N), by = .(Sepal.Length, Sepal.Width, Petal.Length, Petal.Width, Species)]

   Sepal.Length Sepal.Width Petal.Length Petal.Width Species Freq
1:          5.1         3.5          1.4         0.2  setosa    1
2:          4.9         3.0          1.4         0.2  setosa    1
3:          4.7         3.2          1.3         0.2  setosa    1
4:          4.6         3.1          1.5         0.2  setosa    1
5:          5.0         3.6          1.4         0.2  setosa    1
6:          5.4         3.9          1.7         0.4  setosa    1
</code>```

However, I wonder if there is a method to group by all variables without needing to type all the columns names?

答:
Here is an approach in Base-R

```<code>Freq <- table(apply(iris,1,paste0, collapse=" "))
iris$Freq <- apply(iris,1, function(x) Freq[names(Freq) %in% paste0(x,collapse=" ")])
</code>```

output:

```<code>> iris
    Sepal.Length Sepal.Width Petal.Length Petal.Width    Species Freq
...          ...         ...          ...         ...  ...        ...
140          6.9         3.1          5.4         2.1  virginica    1
141          6.7         3.1          5.6         2.4  virginica    1
142          6.9         3.1          5.1         2.3  virginica    1
143          5.8         2.7          5.1         1.9  virginica    2
144          6.8         3.2          5.9         2.3  virginica    1
145          6.7         3.3          5.7         2.5  virginica    1
</code>```

Title: Group by all columns in a data.table

Body:
I'm working with iris data.table in R.

To remind how it looks I paste six five rows here

   Sepal.Length Sepal.Width Petal.Length Petal.Width Species
1:          5.1         3.5          1.4         0.2  setosa
2:          4.9         3.0          1.4         0.2  setosa
3:          4.7         3.2          1.3         0.2  setosa
4:          4.6         3.1          1.5         0.2  setosa
5:          5.0         3.6          1.4         0.2  setosa
6:          5.4         3.9          1.7         0.4  setosa

I would like to calculate the number of rows, grouped by all columns. Of course we may write all variables in by, like this:

iris[, .(Freq = .N), by = .(Sepal.Length, Sepal.Width, Petal.Length, Petal.Width, Species)]

   Sepal.Length Sepal.Width Petal.Length Petal.Width Species Freq
1:          5.1         3.5          1.4         0.2  setosa    1
2:          4.9         3.0          1.4         0.2  setosa    1
3:          4.7         3.2          1.3         0.2  setosa    1
4:          4.6         3.1          1.5         0.2  setosa    1
5:          5.0         3.6          1.4         0.2  setosa    1
6:          5.4         3.9          1.7         0.4  setosa    1

However, I wonder if there is a method to group by all variables without needing to type all the columns names?

Body:
Here is an approach in Base-R

Freq <- table(apply(iris,1,paste0, collapse=" "))
iris$Freq <- apply(iris,1, function(x) Freq[names(Freq) %in% paste0(x,collapse=" ")])

output:

> iris
    Sepal.Length Sepal.Width Petal.Length Petal.Width    Species Freq
...          ...         ...          ...         ...  ...        ...
140          6.9         3.1          5.4         2.1  virginica    1
141          6.7         3.1          5.6         2.4  virginica    1
142          6.9         3.1          5.1         2.3  virginica    1
143          5.8         2.7          5.1         1.9  virginica    2
144          6.8         3.2          5.9         2.3  virginica    1
145          6.7         3.3          5.7         2.5  virginica    1


问:
Directory Searcher not returning all the results
I have created 2400 security groups and added all these security groups to the user. When I query Active Directory using a DirectorySearcher, I get only 2049 security groups. The remaining security groups are missing. I tried the pagination approach as mentioned below, it still doesn't work. What's the ideal way of getting all the security groups?

```<code>$gcName = "blahblah.com"
$dn =  "CN=blahblah,OU=Tenants,OU=INT,DC=dom,DC=abc,DC=def,DC=com"
$searchRoot = [ADSI]("LDAP://" + $gcName + "/" + $dn)
$searcher = New-Object System.DirectoryServices.DirectorySearcher($searchRoot, "(objectClass=*)", @("tokenGroups"), [System.DirectoryServices.SearchScope]::Base)
$searcher.PageSize=500
foreach ($SearchResult  in $searcher.FindAll()){$SearchResult.Properties["tokenGroups"].Count}
</code>```

Edit 1:
When I use the following commands, it doesn't return the complete list of security groups. Ideally, I expect all the groups here along with some other user properties.

```<code>$searchRoot = [ADSI]("LDAP://" + $gcName)
$searcher = New-Object System.DirectoryServices.DirectorySearcher($searchRoot, "(|((msOnline-WindowsLiveNetId=xxxxxx))((msOnline-AlternativeSecurityId=YYYYYYYY)))", @("name"))
$searcher.PropertiesToLoad.AddRange(@("msOnline-UserPrincipalName","objectClass","msOnline-AccountEnabled","displayName","proxyaddresses","memberOf"))
$sr = $searcher.FindOne()
$de= $sr.GetDirectoryEntry()
$de.RefreshCache(@("tokenGroups"))
$de.Properties["tokenGroups"].Count
</code>```

When I use the following, it returns all the groups but I don't get the user properties.

```<code>$searchRoot = [ADSI]("LDAP://" + $gcName)
$searcher = [adsisearcher]::new($searchRoot, "(&(objectClass=group)(member=$dn))", @("name"))
$searcher.PageSize=500
$searcher.FindAll().Count
</code>```

This doesn't work either.

```<code>$searchRoot = [ADSI]("LDAP://" + $gcName)
$searcher = [adsisearcher]::new($searchRoot, "((member=$dn))", @("name","msOnline-UserPrincipalName","tokenGroups"))
$searcher.PageSize=500
$searcher.FindAll().Count
</code>```

All I want to achieve is get all the tokenGroups and few user properties with a single search.

答:
The PageSize only affects the number of search results, but there is only one search result. You're counting the number of records in the tokenGroups attribute of that one result.

One possible issue is that tokenGroups will only show security groups, because it is designed for determining the user's permissions. If the user is in any groups where the 'Group type' is "distribution", those will not be included in tokenGroups.

If you only have one domain in your AD forest, then you can look at the memberOf attribute instead of tokenGroups. If you have more than one domain in your forest, then memberOf may not give you all the groups.

You could also change the search so that it looks for all groups that have that user as a member. That would look like this:

```<code>$gcName = "blahblah.com"
$dn =  "CN=blahblah,OU=Tenants,OU=INT,DC=dom,DC=abc,DC=def,DC=com"
$searchRoot = [ADSI]("LDAP://" + $gcName)
$searcher = [adsisearcher]::new($searchRoot, "(&(objectClass=group)(member=$dn))", @("name"))
$searcher.PageSize=500
$searcher.FindAll().Count
</code>```

Notice that you can use [adsisearcher]::new as a short form for New-Object System.DirectoryServices.DirectorySearcher.

Body:
I have created 2400 security groups and added all these security groups to the user. When I query Active Directory using a DirectorySearcher, I get only 2049 security groups. The remaining security groups are missing. I tried the pagination approach as mentioned below, it still doesn't work. What's the ideal way of getting all the security groups?

$gcName = "blahblah.com"
$dn =  "CN=blahblah,OU=Tenants,OU=INT,DC=dom,DC=abc,DC=def,DC=com"
$searchRoot = [ADSI]("LDAP://" + $gcName + "/" + $dn)
$searcher = New-Object System.DirectoryServices.DirectorySearcher($searchRoot, "(objectClass=*)", @("tokenGroups"), [System.DirectoryServices.SearchScope]::Base)
$searcher.PageSize=500
foreach ($SearchResult  in $searcher.FindAll()){$SearchResult.Properties["tokenGroups"].Count}

Edit 1:
When I use the following commands, it doesn't return the complete list of security groups. Ideally, I expect all the groups here along with some other user properties.

$searchRoot = [ADSI]("LDAP://" + $gcName)
$searcher = New-Object System.DirectoryServices.DirectorySearcher($searchRoot, "(|((msOnline-WindowsLiveNetId=xxxxxx))((msOnline-AlternativeSecurityId=YYYYYYYY)))", @("name"))
$searcher.PropertiesToLoad.AddRange(@("msOnline-UserPrincipalName","objectClass","msOnline-AccountEnabled","displayName","proxyaddresses","memberOf"))
$sr = $searcher.FindOne()
$de= $sr.GetDirectoryEntry()
$de.RefreshCache(@("tokenGroups"))
$de.Properties["tokenGroups"].Count

When I use the following, it returns all the groups but I don't get the user properties.

$searchRoot = [ADSI]("LDAP://" + $gcName)
$searcher = [adsisearcher]::new($searchRoot, "(&(objectClass=group)(member=$dn))", @("name"))
$searcher.PageSize=500
$searcher.FindAll().Count

This doesn't work either.

$searchRoot = [ADSI]("LDAP://" + $gcName)
$searcher = [adsisearcher]::new($searchRoot, "((member=$dn))", @("name","msOnline-UserPrincipalName","tokenGroups"))
$searcher.PageSize=500
$searcher.FindAll().Count

All I want to achieve is get all the tokenGroups and few user properties with a single search.

Body:
The PageSize only affects the number of search results, but there is only one search result. You're counting the number of records in the tokenGroups attribute of that one result.

One possible issue is that tokenGroups will only show security groups, because it is designed for determining the user's permissions. If the user is in any groups where the 'Group type' is "distribution", those will not be included in tokenGroups.

If you only have one domain in your AD forest, then you can look at the memberOf attribute instead of tokenGroups. If you have more than one domain in your forest, then memberOf may not give you all the groups.

You could also change the search so that it looks for all groups that have that user as a member. That would look like this:

$gcName = "blahblah.com"
$dn =  "CN=blahblah,OU=Tenants,OU=INT,DC=dom,DC=abc,DC=def,DC=com"
$searchRoot = [ADSI]("LDAP://" + $gcName)
$searcher = [adsisearcher]::new($searchRoot, "(&(objectClass=group)(member=$dn))", @("name"))
$searcher.PageSize=500
$searcher.FindAll().Count

Notice that you can use [adsisearcher]::new as a short form for New-Object System.DirectoryServices.DirectorySearcher.


问:
Where is spring context stored and what is the data structure?
Where is spring context stored? In which data structure? ( I heard it's just a Map, is it?)
( I don't mean the path to the xml file, I mean when Spring read bean definitions it stored the information about it somewhere and injects it)</p>

答:
```<code>org.springframework.beans.factory.support.DefaultSingletonBeanRegistry

private final Map<String, Object> singletonObjects = new ConcurrentHashMap(256);
</code>```

Singleton beans are stored here.

Body:
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry

private final Map<String, Object> singletonObjects = new ConcurrentHashMap(256);

Singleton beans are stored here.


问:
How to play a Youtube video in python
What modules should I use to make a Python script where Python gets the name of a video, opens up a Chrome window, opens Youtube and plays the first result. I've tried Youtube Data API but it's not for that kind of things.</p>

答:
You can use the subprocess to call a browser and run the url you request. With this minimal code you can ask for a website to go, and open in firefox. But you can use it as a bootstrap code for your application using chrome.

```<code>import subprocess
url = input('What site you would to go: ')
subprocess.Popen(['firefox',url])
</code>```

Using this template, you can just change the code to ask for a youtube link. If you have firefox installed you can just run it.

Title: How to play a Youtube video in python

Body:
You can use the subprocess to call a browser and run the url you request. With this minimal code you can ask for a website to go, and open in firefox. But you can use it as a bootstrap code for your application using chrome.

import subprocess
url = input('What site you would to go: ')
subprocess.Popen(['firefox',url])

Using this template, you can just change the code to ask for a youtube link. If you have firefox installed you can just run it.


问:
WP7 - How can I retrieve the mini form of a Path at runtime?
I've got a databound series of predefined shapes (Path with Data="" set) which each trigger the same event when clicked.
I'd like to programmatically access the mini form of the Path.Data property at runtime to be able to persist it.

In this case I could just name the elements and on click check which one, however I'd prefer a more generic solution.
There seem to be some WPF workarounds but I haven't seen any for WP7.

Does anyone know if this is possible? and if so, how to do it?

Thanks.

答:
Looking in to if and how this may be possible I came across http://www.eightyeightpercentnerd.dreamhosters.com/?p=40 and even though it's quite old it explains how a paths data/geometry is parsed in Siverlight.

It leads me to think that you may be better off trying to find a different approach to solving your problem. :(


问:
Unable to grab the ID generated by firebase when converting to array
I'm using CRA & axios to pull down some JSON as an object from firebase, then convert it into an array for it to be rendered.

This appears to be successful, and I can log the array, however I appear to be unable to grab the ID generated by firebase (e.g. -M9SUPLwY3KgRNmOLS17)

Which I require in order to be able to navigate to the correct tour page.

Expected outcome:
/tours/-M9SUPLwY3KgRNmOLS17/tour

Current outcome:
/tours/undefined/tour

JSX

```<code>
  componentDidMount() {
    axios.get('FIREBASEURL/tours.json')
    .then(response => {
      const obj = response.data;
      const resArr = []
        for (let key in obj) {
          resArr.push(obj[key])
        }
      this.tours = resArr
      this.setState({tours: resArr})
    })
  }

  render() {
    const { tours } = this.state
   return (
      <div>
        <div className="tours">
        {tours ? (tours.map(tours => (
           <Link to={`/tours/${tours.id}/tour`} className="trslink">
            <div key={tours.id + Math.random()} className="trsIndiv">
              <h3 className="title">{tours.tour.name}</h3>
              <div className="desc">{tours.tour.description}</div>
              <p className="longdesc">
                <strong>City:</strong> {tours.tour.city}<br/>
                <strong>Duration:</strong> {tours.tour.duration} hrs<br/><br/>
              </p>

            </div>
          </Link>
          ))
        ) : (
        <div></div>
        )}
        </div>
      </div>
      )
  }
</code>```

JSON example

```<code>{
 "-GHJSDAGFAD1" : {
   "tour" : {
     "city" : "London, England",
     "description" : "Drink to your hearts content.",
     "duration" : 5,
     "full_description" : "Long Description TBC",
     "name" : "The Fighting Lion",
     "rating" : 4
   }
 },
 "-QEWURYK2" : {
   "tour" : {
     "city" : "London, England",
     "description" : "Top Pub!",
     "duration" : 2,
     "full_description" : "Long Description TBC",
     "name" : "The Frisky Goose",
     "rating" : 3.5
   }
 }
}
</code>```

I'm sure I'm missing something simple, has anyone any advice? Thanks,

答:
The key of a document is the JavaScript object key -- it is not otherwise embedded in the content. I think you probably want something like:

```<code>  axios.get('FIREBASEURL/tours.json')
    .then(response => {
      const obj = response.data;
      const resArr = []
        for (let key in obj) {
          resArr.push(Object.assign({id: key}, obj[key]))
        }
      this.tours = resArr
      this.setState({tours: resArr})
    })
</code>```

The difference being that Object.assign is adding an id property to the resulting objects in the array.

Body:
I'm using CRA & axios to pull down some JSON as an object from firebase, then convert it into an array for it to be rendered.

This appears to be successful, and I can log the array, however I appear to be unable to grab the ID generated by firebase (e.g. -M9SUPLwY3KgRNmOLS17)

Which I require in order to be able to navigate to the correct tour page.

Expected outcome:
/tours/-M9SUPLwY3KgRNmOLS17/tour

Current outcome:
/tours/undefined/tour

JSX

  componentDidMount() {
    axios.get('FIREBASEURL/tours.json')
    .then(response => {
      const obj = response.data;
      const resArr = []
        for (let key in obj) {
          resArr.push(obj[key])
        }
      this.tours = resArr
      this.setState({tours: resArr})
    })
  }

  render() {
    const { tours } = this.state
   return (

        {tours ? (tours.map(tours => (
           <Link to={`/tours/${tours.id}/tour`} className="trslink">

{tours.tour.name}

{tours.tour.description}

                City: {tours.tour.city}

                Duration: {tours.tour.duration} hrs

          </Link>
          ))
        ) : (

        )}

      )
  }

JSON example

{
 "-GHJSDAGFAD1" : {
   "tour" : {
     "city" : "London, England",
     "description" : "Drink to your hearts content.",
     "duration" : 5,
     "full_description" : "Long Description TBC",
     "name" : "The Fighting Lion",
     "rating" : 4
   }
 },
 "-QEWURYK2" : {
   "tour" : {
     "city" : "London, England",
     "description" : "Top Pub!",
     "duration" : 2,
     "full_description" : "Long Description TBC",
     "name" : "The Frisky Goose",
     "rating" : 3.5
   }
 }
}

I'm sure I'm missing something simple, has anyone any advice? Thanks,

Body:
The key of a document is the JavaScript object key -- it is not otherwise embedded in the content. I think you probably want something like:

  axios.get('FIREBASEURL/tours.json')
    .then(response => {
      const obj = response.data;
      const resArr = []
        for (let key in obj) {
          resArr.push(Object.assign({id: key}, obj[key]))
        }
      this.tours = resArr
      this.setState({tours: resArr})
    })

The difference being that Object.assign is adding an id property to the resulting objects in the array.


问:
Time complexity of contains(Object o), in an ArrayList of Objects
As the title says, I was wondering what the time complexity of the contains() method of an ArrayList is.

答:
its O(n). contains(Object o) is implemented on indexOf() which takes O(n). So complexity of contains(Object o) is defensively O(n)

Here are some other if you need:

```<code>add() - O(1)
add(index, element) – O(n)
get() – O(1)
set() – O(1)
remove() –  (n)
indexOf()` – O(n)
</code>```

Body:
its O(n). contains(Object o) is implemented on indexOf() which takes O(n). So complexity of contains(Object o) is defensively O(n)

Here are some other if you need:

add() - O(1)
add(index, element) – O(n)
get() – O(1)
set() – O(1)
remove() –  (n)
indexOf()` – O(n)


问:
Suppressing parentheses in a function that uses the pipe operator
Can somebody explain why I have to suppress the parentheses for the function is.factor  in the command shown below? Student-data was read from a .csv file. I can see the structure of Student-data and I want to select only the factor variables. The command works fine but I cannot see why I cannot write the parentheses. I saw an example in the forum. Sorry if the question is silly or has been asked before. I could not find any similar question.

studentData%>%select_if(is.factor)

答:
It's not the pipe, %>%, that requires you to "drop the brackets, it's select_if.  From the documentation:

.predicate "A predicate function to be applied to the columns or a logical vector. The variables for which .predicate is or returns TRUE are selected. This argument is passed to rlang::as_function() and thus supports quosure-style lambda functions and strings representing function names."

You're not evaluating the function here.  You're passing an R object.  (Functions are objects, just as data.frames or scalars are).  The evaluation happens later, in the guts of select_if.  Including the brackets would tell R to evaluate the function at the time the select_if call was executed.  That's not correct.  It needs to be evaluated later.


问:
Directory traversal security issue
I have a Java webapp which is vulnerable to the directory transversal (aka path transversal) attack via URL encoding. After being authenticated:

if I hit http://localhost:8080/Web/WEB-INF/web.xml, I get a 404 (which is fine)

if I hit http://localhost:8080/Web/%c0%ae/WEB-INF/web.xml, I can read the file (which is obviously not fine)

As per the Servlet spec., the WEB-INF folder is not supposed to be accessible publicly, but somehow it works in this case.
I'm using Websphere 5.1 with Java 1.4, Spring Security 2.0.5 and Struts 1.3.
From what I read, it seems to be related to the encoding, %c0%ae being '.' (dot) in UTF-8.

I tried the same thing on a different webapp which runs in a different environment (Tomcat 6 with Java 7, Spring Security 3 and Spring MVC) and I wasn't able to reproduce the problem. This second webapp has a filter to force encode the pages in UTF-8 (org.springframework.web.filter.CharacterEncodingFilter), so I tried the same configuration on the first webapp, but it didn't do the trick.
Any ideas?

Thanks.

答:
The filter changes the character encoding for the body of the request, not the URL.

To set the URL encoding in tomcat, you need to add an attribute in the <Connector> element of server.xml:

```<code><Connector port="8080" protocol="HTTP/1.1"
           connectionTimeout="20000"
           URIEncoding="UTF-8"
           redirectPort="8443" />
</code>```

Title: Directory traversal security issue

Body:
The filter changes the character encoding for the body of the request, not the URL.

To set the URL encoding in tomcat, you need to add an attribute in the <Connector> element of server.xml:

<Connector port="8080" protocol="HTTP/1.1"
           connectionTimeout="20000"
           URIEncoding="UTF-8"
           redirectPort="8443" />


问:
Different sort-by by one key Clojure
Hey I have this Code but I would like to reverse only the :a key.

```<code>(sort-by (juxt :a :b) [{:a 1 :b 3} {:a 1 :b 2} {:a 2 :b 1}])
;;=> [{:a 1 :b 2} {:a 1 :b 3} {:a 2 :b 1}]
</code>```

I tried this but this was in the wrong order.

```<code>(sort-by (juxt :a :b) #(compare %2 %1)  [{:a 1 :b 3} {:a 1 :b 2} {:a 2 :b 1}])
;;=> ({:a 2, :b 1} {:a 1, :b 3} {:a 1, :b 2})
</code>```

I would like to get.

```<code>;;=> ({:a 2, :b 1} {:a 1, :b 2} {:a 1, :b 3})
</code>```

Any Ideas?
Can I do this also in juxt?

答: This and related questions about comparators and sorting in Clojure are covered in this guide article: https://clojure.org/guides/comparators</p>

Title: Different sort-by by one key Clojure

Body:
Hey I have this Code but I would like to reverse only the :a key.

(sort-by (juxt :a :b) [{:a 1 :b 3} {:a 1 :b 2} {:a 2 :b 1}])
;;=> [{:a 1 :b 2} {:a 1 :b 3} {:a 2 :b 1}]

I tried this but this was in the wrong order.

(sort-by (juxt :a :b) #(compare %2 %1)  [{:a 1 :b 3} {:a 1 :b 2} {:a 2 :b 1}])
;;=> ({:a 2, :b 1} {:a 1, :b 3} {:a 1, :b 2})

I would like to get.

;;=> ({:a 2, :b 1} {:a 1, :b 2} {:a 1, :b 3})

Any Ideas?
Can I do this also in juxt?


问:
Flutter: Remove space between widgets
By using CustomPainter i have created a half circle.Now i have this widget tree:

```<code>return Scaffold(
  body: Center(
    child: SingleChildScrollView(
      child: Column(
        mainAxisSize: MainAxisSize.min,
        children: <Widget>[
          Container(
            // card view
            height: 100,
            alignment: Alignment.center,
            margin: EdgeInsets.only(
                top: 20.0, bottom: 0.0, left: 50.0, right: 50.0),
            decoration: BoxDecoration(
              boxShadow: ([
                BoxShadow(
                  color: color_transparent_black,
                  spreadRadius: 5,
                  blurRadius: 3.0,
                  offset: Offset(2, 3),
                ),
              ]),
              borderRadius: BorderRadius.circular(14.0),
            ),),
            MyArc(diameter: 200),
</code>```

This is MyArc:

```<code>class MyArc extends StatelessWidget {
  final double diameter;

  const MyArc({Key key, this.diameter = 200}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return CustomPaint(
      painter: MyPainter(),
      size: Size(diameter, diameter),
    );
  }
}

// This is the Painter class
class MyPainter extends CustomPainter {
  @override
  void paint(Canvas canvas, Size size) {
    Paint paint = Paint()..color = Colors.blue;
    canvas.drawArc(
      Rect.fromCenter(
        center: Offset(size.height / 2, 0),
        height: size.height,
        width: size.width,
      ),
      6.4,
      2.9,
      false,
      paint,
    );
  }

  @override
  bool shouldRepaint(CustomPainter oldDelegate) => false;
}
</code>```

But i got this problem:

I don't want any space between gray and blue shape!!!

答:
I finally figured it out...

```<code>import 'dart:math' as math;

//...

class MyPainter extends CustomPainter {
  @override
  void paint(Canvas canvas, Size size) {
    Paint blue = Paint()..color = Colors.blue;

    canvas.translate(0, -size.height / 2);
    canvas.drawArc(
      Offset.zero & size,
      -math.pi,
      -math.pi,
      false,
      blue,
    );
  }

  @override
  bool shouldRepaint(CustomPainter oldDelegate) => false;
}
</code>```

If you want to make your canvas fit nicely also you can make it rectangular like so...

```<code>CustomPaint(
  painter: MyPainter(),
  size: Size(diamieter, diameter / 2),
)
</code>```

Then have you custom painter as...

```<code>class MyPainter extends CustomPainter {
  @override
  void paint(Canvas canvas, Size size) {
    Paint blue = Paint()..color = Colors.blue;
    Paint red = Paint()..color = Colors.red;

    canvas.drawRect(Offset.zero & size, red);

    canvas.translate(0, -size.height);
    canvas.drawArc(
      Offset.zero & Size(size.width, size.height * 2),
      -math.pi,
      -math.pi,
      false,
      blue,
    );
  }

  @override
  bool shouldRepaint(CustomPainter oldDelegate) => false;
}
</code>```

It'll fit snug this way...

Title: Flutter: Remove space between widgets

Body:
By using CustomPainter i have created a half circle.Now i have this widget tree:

return Scaffold(
  body: Center(
    child: SingleChildScrollView(
      child: Column(
        mainAxisSize: MainAxisSize.min,
        children: <Widget>[
          Container(
            // card view
            height: 100,
            alignment: Alignment.center,
            margin: EdgeInsets.only(
                top: 20.0, bottom: 0.0, left: 50.0, right: 50.0),
            decoration: BoxDecoration(
              boxShadow: ([
                BoxShadow(
                  color: color_transparent_black,
                  spreadRadius: 5,
                  blurRadius: 3.0,
                  offset: Offset(2, 3),
                ),
              ]),
              borderRadius: BorderRadius.circular(14.0),
            ),),
            MyArc(diameter: 200),

This is MyArc:

class MyArc extends StatelessWidget {
  final double diameter;

  const MyArc({Key key, this.diameter = 200}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return CustomPaint(
      painter: MyPainter(),
      size: Size(diameter, diameter),
    );
  }
}

// This is the Painter class
class MyPainter extends CustomPainter {
  @override
  void paint(Canvas canvas, Size size) {
    Paint paint = Paint()..color = Colors.blue;
    canvas.drawArc(
      Rect.fromCenter(
        center: Offset(size.height / 2, 0),
        height: size.height,
        width: size.width,
      ),
      6.4,
      2.9,
      false,
      paint,
    );
  }

  @override
  bool shouldRepaint(CustomPainter oldDelegate) => false;
}

But i got this problem:

I don't want any space between gray and blue shape!!!

Body:
I finally figured it out...

import 'dart:math' as math;

//...

class MyPainter extends CustomPainter {
  @override
  void paint(Canvas canvas, Size size) {
    Paint blue = Paint()..color = Colors.blue;

    canvas.translate(0, -size.height / 2);
    canvas.drawArc(
      Offset.zero & size,
      -math.pi,
      -math.pi,
      false,
      blue,
    );
  }

  @override
  bool shouldRepaint(CustomPainter oldDelegate) => false;
}

If you want to make your canvas fit nicely also you can make it rectangular like so...

CustomPaint(
  painter: MyPainter(),
  size: Size(diamieter, diameter / 2),
)

Then have you custom painter as...

class MyPainter extends CustomPainter {
  @override
  void paint(Canvas canvas, Size size) {
    Paint blue = Paint()..color = Colors.blue;
    Paint red = Paint()..color = Colors.red;

    canvas.drawRect(Offset.zero & size, red);

    canvas.translate(0, -size.height);
    canvas.drawArc(
      Offset.zero & Size(size.width, size.height * 2),
      -math.pi,
      -math.pi,
      false,
      blue,
    );
  }

  @override
  bool shouldRepaint(CustomPainter oldDelegate) => false;
}

It'll fit snug this way...


问:
Pyspark -- How to left merge dataframes
In Pandas I can merge two dataframes like so:

```<code>df1 = pd.DataFrame({'lkey': ['foo', 'bar', 'baz', 'foo'],
                    'value': [1, 2, 3, 5]})
df2 = pd.DataFrame({'rkey': ['foo', 'bar', 'baz', 'foo'],
                    'value': [5, 6, 7, 8]})

df1.merge(df2, how='left', left_on='lkey', right_on='rkey')

  lkey  value_x rkey  value_y
0  foo        1  foo        5
1  foo        1  foo        8
2  bar        2  bar        6
3  baz        3  baz        7
4  foo        5  foo        5
5  foo        5  foo        8
</code>```

What would the equivalent of this be in pyspark? A left join?

答:
You can apply join in pyspark as</p>

```<code>df = df1.join(df2, df1.lkey==df2.rkey, 'left_outer')
</code>```

Title: Pyspark -- How to left merge dataframes

Body:
In Pandas I can merge two dataframes like so:

df1 = pd.DataFrame({'lkey': ['foo', 'bar', 'baz', 'foo'],
                    'value': [1, 2, 3, 5]})
df2 = pd.DataFrame({'rkey': ['foo', 'bar', 'baz', 'foo'],
                    'value': [5, 6, 7, 8]})

df1.merge(df2, how='left', left_on='lkey', right_on='rkey')

  lkey  value_x rkey  value_y
0  foo        1  foo        5
1  foo        1  foo        8
2  bar        2  bar        6
3  baz        3  baz        7
4  foo        5  foo        5
5  foo        5  foo        8

What would the equivalent of this be in pyspark? A left join?

Body:
You can apply join in pyspark as

df = df1.join(df2, df1.lkey==df2.rkey, 'left_outer')


问:
Why does Github Package Registry say my token is not scoped to read packages?
I'm trying to publish a Gradle project. I have followed all the documentation provided by GitHub, but when I send the command to publish I am getting a 401 error from the server.

```<code>Execution failed for task ':publishGprPublicationToGitHubPackagesRepository'.
> Failed to publish publication 'gpr' to repository 'GitHubPackages'
   > Could not GET 'https://maven.pkg.github.com/PowerInnovations/Data-Model/com/powerinnovations/data-model/0.0.1-SNAPSHOT/maven-metadata.xml'. Received status code 401 from server: Unauthorized
</code>```

Upon going to the page and logging in to Github, it says:

```<code>Your token has not been granted the required scopes to execute this query. The 'id' field requires one of the following scopes: ['read:packages'], but your token has only been granted the: [''] scopes. Please modify your token's scopes at: https://github.com/settings/tokens.
</code>```

The thing is, I am already using the personal access token which I created to do this, and it does have the read packages scope enabled.

答:
I did get a resolution from a member of Github's support.

The support person said in an email "When publishing packages, your PAT needs the repo scope as well as write access to the repo you package will be associated with."

They agreed that the response from the server, in this case, was misleading.

Body:
I'm trying to publish a Gradle project. I have followed all the documentation provided by GitHub, but when I send the command to publish I am getting a 401 error from the server.

Execution failed for task ':publishGprPublicationToGitHubPackagesRepository'.
> Failed to publish publication 'gpr' to repository 'GitHubPackages'
   > Could not GET 'https://maven.pkg.github.com/PowerInnovations/Data-Model/com/powerinnovations/data-model/0.0.1-SNAPSHOT/maven-metadata.xml'. Received status code 401 from server: Unauthorized

Upon going to the page and logging in to Github, it says:

Your token has not been granted the required scopes to execute this query. The 'id' field requires one of the following scopes: ['read:packages'], but your token has only been granted the: [''] scopes. Please modify your token's scopes at: https://github.com/settings/tokens.

The thing is, I am already using the personal access token which I created to do this, and it does have the read packages scope enabled.


问:
Is there a script to compress every single file in a directory and ouput it to another Directory?
So I'm looking to compress the files in a given directory, for example /etc/input and output the files in /etc/output, and it should be like: </p>

<pre class="lang-sh prettyprint-override"><code>$ ls /etc/input
file1
file2
file3

$ script.sh

$ ls /etc/output
file1.zip
file2.zip
file3.zip

$ ls /etc/input

</code>```

<p>For now, what i wrote looks like this:</p>

<pre class="lang-sh prettyprint-override"><code>find . -type f -print | while read fname ; do
    mkdir -p "../output/`dirname \"$fname\"`"
    gzip -c "$fname" > "../output/$fname.gz"
done
</code>```

答:
You could use find, but I think it's simpler with pure Bash.

INPUT=/etc/input
OUTPUT=/etc/output

mkdir -p "$OUTPUT"
for file in "$INPUT"/* ; do
  gzip -c "$file" > "${OUTPUT}/${file}.gz"
done
```

Change INPUT and OUTPUT to match what you want.

Body:
So I'm looking to compress the files in a given directory, for example /etc/input and output the files in /etc/output, and it should be like:

$ ls /etc/input
file1
file2
file3

$ script.sh

$ ls /etc/output
file1.zip
file2.zip
file3.zip

$ ls /etc/input

For now, what i wrote looks like this:

find . -type f -print | while read fname ; do
    mkdir -p "../output/`dirname \"$fname\"`"
    gzip -c "$fname" > "../output/$fname.gz"
done

Body:
You could use find, but I think it's simpler with pure Bash.

INPUT=/etc/input
OUTPUT=/etc/output

mkdir -p "$OUTPUT"
for file in "$INPUT"/* ; do
  gzip -c "$file" > "${OUTPUT}/${file}.gz"
done

Change INPUT and OUTPUT to match what you want.


问:
Cant access Artemis console
I have just install a new artemis in my new server, able to run the service normally but not able to access from outside.

I also have followed this question that seems have the similar issue with me, but
seems not able to work.

Artemis-2.6.3 console: Service Unavailable

my current jolokia-access :

```<code><restrict>
    <remote>
      <host>localhost</host>
      <host>10.85.102.148</host><!--This is my computer ip-->
    </remote>
    <!--
    <cors>
        <allow-origin>*://localhost*</allow-origin>
        <strict-checking/>
    </cors>
    -->
</restrict>
</code>```

current logging

```<code>    2019-04-25 20:16:07,013 INFO  [org.apache.activemq.artemis.integration.bootstrap] AMQ101000: Starting ActiveMQ Artemis Server
2019-04-25 20:16:07,046 INFO  [org.apache.activemq.artemis.core.server] AMQ221000: live Message Broker is starting with configuration Broker Configuration (clustered=false,journalDirectory=data/journal,bindingsDirectory=data/bindings,largeMessagesDirectory=data/large-messages,pagingDirectory=data/paging)
2019-04-25 20:16:07,080 INFO  [org.apache.activemq.artemis.core.server] AMQ221012: Using AIO Journal
2019-04-25 20:16:07,133 INFO  [org.apache.activemq.artemis.core.server] AMQ221057: Global Max Size is being adjusted to 1/2 of the JVM max size (-Xmx). being defined as 1,073,741,824
2019-04-25 20:16:07,162 INFO  [org.apache.activemq.artemis.core.server] AMQ221043: Protocol module found: [artemis-server]. Adding protocol support for: CORE
2019-04-25 20:16:07,163 INFO  [org.apache.activemq.artemis.core.server] AMQ221043: Protocol module found: [artemis-amqp-protocol]. Adding protocol support for: AMQP
2019-04-25 20:16:07,164 INFO  [org.apache.activemq.artemis.core.server] AMQ221043: Protocol module found: [artemis-hornetq-protocol]. Adding protocol support for: HORNETQ
2019-04-25 20:16:07,164 INFO  [org.apache.activemq.artemis.core.server] AMQ221043: Protocol module found: [artemis-mqtt-protocol]. Adding protocol support for: MQTT
2019-04-25 20:16:07,165 INFO  [org.apache.activemq.artemis.core.server] AMQ221043: Protocol module found: [artemis-openwire-protocol]. Adding protocol support for: OPENWIRE
2019-04-25 20:16:07,166 INFO  [org.apache.activemq.artemis.core.server] AMQ221043: Protocol module found: [artemis-stomp-protocol]. Adding protocol support for: STOMP
2019-04-25 20:16:07,222 INFO  [org.apache.activemq.artemis.core.server] AMQ221034: Waiting indefinitely to obtain live lock
2019-04-25 20:16:07,223 INFO  [org.apache.activemq.artemis.core.server] AMQ221035: Live Server Obtained live lock
2019-04-25 20:16:08,143 INFO  [org.apache.activemq.artemis.core.server] AMQ221080: Deploying address DLQ supporting [ANYCAST]
2019-04-25 20:16:08,144 INFO  [org.apache.activemq.artemis.core.server] AMQ221003: Deploying ANYCAST queue DLQ on address DLQ
2019-04-25 20:16:08,144 INFO  [org.apache.activemq.artemis.core.server] AMQ221080: Deploying address ExpiryQueue supporting [ANYCAST]
2019-04-25 20:16:08,144 INFO  [org.apache.activemq.artemis.core.server] AMQ221003: Deploying ANYCAST queue ExpiryQueue on address ExpiryQueue
2019-04-25 20:16:08,513 INFO  [org.apache.activemq.artemis.core.server] AMQ221020: Started EPOLL Acceptor at 0.0.0.0:61619 for protocols [CORE,MQTT,AMQP,STOMP,HORNETQ,OPENWIRE]
2019-04-25 20:16:08,521 INFO  [org.apache.activemq.artemis.core.server] AMQ221020: Started EPOLL Acceptor at 0.0.0.0:5446 for protocols [HORNETQ,STOMP]
2019-04-25 20:16:08,536 INFO  [org.apache.activemq.artemis.core.server] AMQ221020: Started EPOLL Acceptor at 0.0.0.0:5673 for protocols [AMQP]
2019-04-25 20:16:08,540 INFO  [org.apache.activemq.artemis.core.server] AMQ221020: Started EPOLL Acceptor at 0.0.0.0:1884 for protocols [MQTT]
2019-04-25 20:16:08,545 INFO  [org.apache.activemq.artemis.core.server] AMQ221020: Started EPOLL Acceptor at 0.0.0.0:61614 for protocols [STOMP]
2019-04-25 20:16:08,547 INFO  [org.apache.activemq.artemis.core.server] AMQ221007: Server is now live
2019-04-25 20:16:08,548 INFO  [org.apache.activemq.artemis.core.server] AMQ221001: Apache ActiveMQ Artemis Message Broker version 2.6.4 [0.0.0.0, nodeID=c4f07cfd-6745-11e9-bfbc-005056b0ef9d]
2019-04-25 20:16:09,647 INFO  [org.apache.activemq.hawtio.branding.PluginContextListener] Initialized activemq-branding plugin
2019-04-25 20:16:09,749 INFO  [org.apache.activemq.hawtio.plugin.PluginContextListener] Initialized artemis-plugin plugin
2019-04-25 20:16:10,199 INFO  [io.hawt.HawtioContextListener] Initialising hawtio services
2019-04-25 20:16:10,269 INFO  [io.hawt.system.ConfigManager] Configuration will be discovered via system properties
2019-04-25 20:16:10,273 INFO  [io.hawt.jmx.JmxTreeWatcher] Welcome to hawtio 1.5.5 : http://hawt.io/ : Don't cha wish your console was hawt like me? ;-)
2019-04-25 20:16:10,298 INFO  [io.hawt.jmx.UploadManager] Using file upload directory: /opt/CMS/dev/artemisCMSDEV2.6.4/tmp/uploads
2019-04-25 20:16:10,318 INFO  [io.hawt.web.AuthenticationFilter] Starting hawtio authentication filter, JAAS realm: "activemq" authorized role(s): "amq" role principal classes: "org.apache.activemq.artemis.spi.core.security.jaas.RolePrincipal"
2019-04-25 20:16:10,362 INFO  [io.hawt.web.JolokiaConfiguredAgentServlet] Jolokia overridden property: [key=policyLocation, value=file:/opt/CMS/dev/artemisCMSDEV2.6.4/etc/jolokia-access.xml]
2019-04-25 20:16:10,403 INFO  [io.hawt.web.RBACMBeanInvoker] Using MBean [hawtio:type=security,area=jmx,rank=0,name=HawtioDummyJMXSecurity] for role based access control
2019-04-25 20:16:10,581 INFO  [io.hawt.system.ProxyWhitelist] Initial proxy whitelist: [localhost, 127.0.0.1, 10.92.202.52, mask.myserver.com, 192.168.46.52, mask-p1.myserver.com]
2019-04-25 20:16:10,882 INFO  [org.apache.activemq.artemis] AMQ241001: HTTP Server started at http://localhost:8162
2019-04-25 20:16:10,883 INFO  [org.apache.activemq.artemis] AMQ241002: Artemis Jolokia REST API available at http://localhost:8162/console/jolokia
2019-04-25 20:16:10,883 INFO  [org.apache.activemq.artemis] AMQ241004: Artemis Console available at http://localhost:8162/console
</code>```

答:
You need just to modify these two files us below :

$[broker_artemis_path]/etc/bootstrap.xml

```<code><web bind="http://0.0.0.0:8161" path="web">
       <app url="activemq-branding" war="activemq-branding.war"/>
       <app url="artemis-plugin" war="artemis-plugin.war"/>
       <app url="console" war="console.war"/>
</web>
</code>```

and  $[broker_artemis_path]/etc/jolokia-access.xml

```<code><cors>
            <!-- Allow cross origin access from localhost ... -->
            <allow-origin>*://*</allow-origin>
            <!-- Options from this point on are auto-generated by Create.java from the Artemis CLI -->
            <!-- Check for the proper origin on the server side, too -->
            <strict-checking/>
</cors>
</code>```

For more information you can check this link :
https://medium.com/@hasnat.saeed/setup-activemq-artemis-on-ubuntu-18-04-76bb4975308b

Title: Cant access Artemis console

Body:
I have just install a new artemis in my new server, able to run the service normally but not able to access from outside.

I also have followed this question that seems have the similar issue with me, but
seems not able to work.

Artemis-2.6.3 console: Service Unavailable

my current jolokia-access :

<restrict>
    <remote>
      <host>localhost</host>
      <host>10.85.102.148</host>
    </remote>

</restrict>

current logging

    2019-04-25 20:16:07,013 INFO  [org.apache.activemq.artemis.integration.bootstrap] AMQ101000: Starting ActiveMQ Artemis Server
2019-04-25 20:16:07,046 INFO  [org.apache.activemq.artemis.core.server] AMQ221000: live Message Broker is starting with configuration Broker Configuration (clustered=false,journalDirectory=data/journal,bindingsDirectory=data/bindings,largeMessagesDirectory=data/large-messages,pagingDirectory=data/paging)
2019-04-25 20:16:07,080 INFO  [org.apache.activemq.artemis.core.server] AMQ221012: Using AIO Journal
2019-04-25 20:16:07,133 INFO  [org.apache.activemq.artemis.core.server] AMQ221057: Global Max Size is being adjusted to 1/2 of the JVM max size (-Xmx). being defined as 1,073,741,824
2019-04-25 20:16:07,162 INFO  [org.apache.activemq.artemis.core.server] AMQ221043: Protocol module found: [artemis-server]. Adding protocol support for: CORE
2019-04-25 20:16:07,163 INFO  [org.apache.activemq.artemis.core.server] AMQ221043: Protocol module found: [artemis-amqp-protocol]. Adding protocol support for: AMQP
2019-04-25 20:16:07,164 INFO  [org.apache.activemq.artemis.core.server] AMQ221043: Protocol module found: [artemis-hornetq-protocol]. Adding protocol support for: HORNETQ
2019-04-25 20:16:07,164 INFO  [org.apache.activemq.artemis.core.server] AMQ221043: Protocol module found: [artemis-mqtt-protocol]. Adding protocol support for: MQTT
2019-04-25 20:16:07,165 INFO  [org.apache.activemq.artemis.core.server] AMQ221043: Protocol module found: [artemis-openwire-protocol]. Adding protocol support for: OPENWIRE
2019-04-25 20:16:07,166 INFO  [org.apache.activemq.artemis.core.server] AMQ221043: Protocol module found: [artemis-stomp-protocol]. Adding protocol support for: STOMP
2019-04-25 20:16:07,222 INFO  [org.apache.activemq.artemis.core.server] AMQ221034: Waiting indefinitely to obtain live lock
2019-04-25 20:16:07,223 INFO  [org.apache.activemq.artemis.core.server] AMQ221035: Live Server Obtained live lock
2019-04-25 20:16:08,143 INFO  [org.apache.activemq.artemis.core.server] AMQ221080: Deploying address DLQ supporting [ANYCAST]
2019-04-25 20:16:08,144 INFO  [org.apache.activemq.artemis.core.server] AMQ221003: Deploying ANYCAST queue DLQ on address DLQ
2019-04-25 20:16:08,144 INFO  [org.apache.activemq.artemis.core.server] AMQ221080: Deploying address ExpiryQueue supporting [ANYCAST]
2019-04-25 20:16:08,144 INFO  [org.apache.activemq.artemis.core.server] AMQ221003: Deploying ANYCAST queue ExpiryQueue on address ExpiryQueue
2019-04-25 20:16:08,513 INFO  [org.apache.activemq.artemis.core.server] AMQ221020: Started EPOLL Acceptor at 0.0.0.0:61619 for protocols [CORE,MQTT,AMQP,STOMP,HORNETQ,OPENWIRE]
2019-04-25 20:16:08,521 INFO  [org.apache.activemq.artemis.core.server] AMQ221020: Started EPOLL Acceptor at 0.0.0.0:5446 for protocols [HORNETQ,STOMP]
2019-04-25 20:16:08,536 INFO  [org.apache.activemq.artemis.core.server] AMQ221020: Started EPOLL Acceptor at 0.0.0.0:5673 for protocols [AMQP]
2019-04-25 20:16:08,540 INFO  [org.apache.activemq.artemis.core.server] AMQ221020: Started EPOLL Acceptor at 0.0.0.0:1884 for protocols [MQTT]
2019-04-25 20:16:08,545 INFO  [org.apache.activemq.artemis.core.server] AMQ221020: Started EPOLL Acceptor at 0.0.0.0:61614 for protocols [STOMP]
2019-04-25 20:16:08,547 INFO  [org.apache.activemq.artemis.core.server] AMQ221007: Server is now live
2019-04-25 20:16:08,548 INFO  [org.apache.activemq.artemis.core.server] AMQ221001: Apache ActiveMQ Artemis Message Broker version 2.6.4 [0.0.0.0, nodeID=c4f07cfd-6745-11e9-bfbc-005056b0ef9d]
2019-04-25 20:16:09,647 INFO  [org.apache.activemq.hawtio.branding.PluginContextListener] Initialized activemq-branding plugin
2019-04-25 20:16:09,749 INFO  [org.apache.activemq.hawtio.plugin.PluginContextListener] Initialized artemis-plugin plugin
2019-04-25 20:16:10,199 INFO  [io.hawt.HawtioContextListener] Initialising hawtio services
2019-04-25 20:16:10,269 INFO  [io.hawt.system.ConfigManager] Configuration will be discovered via system properties
2019-04-25 20:16:10,273 INFO  [io.hawt.jmx.JmxTreeWatcher] Welcome to hawtio 1.5.5 : http://hawt.io/ : Don't cha wish your console was hawt like me? ;-)
2019-04-25 20:16:10,298 INFO  [io.hawt.jmx.UploadManager] Using file upload directory: /opt/CMS/dev/artemisCMSDEV2.6.4/tmp/uploads
2019-04-25 20:16:10,318 INFO  [io.hawt.web.AuthenticationFilter] Starting hawtio authentication filter, JAAS realm: "activemq" authorized role(s): "amq" role principal classes: "org.apache.activemq.artemis.spi.core.security.jaas.RolePrincipal"
2019-04-25 20:16:10,362 INFO  [io.hawt.web.JolokiaConfiguredAgentServlet] Jolokia overridden property: [key=policyLocation, value=file:/opt/CMS/dev/artemisCMSDEV2.6.4/etc/jolokia-access.xml]
2019-04-25 20:16:10,403 INFO  [io.hawt.web.RBACMBeanInvoker] Using MBean [hawtio:type=security,area=jmx,rank=0,name=HawtioDummyJMXSecurity] for role based access control
2019-04-25 20:16:10,581 INFO  [io.hawt.system.ProxyWhitelist] Initial proxy whitelist: [localhost, 127.0.0.1, 10.92.202.52, mask.myserver.com, 192.168.46.52, mask-p1.myserver.com]
2019-04-25 20:16:10,882 INFO  [org.apache.activemq.artemis] AMQ241001: HTTP Server started at http://localhost:8162
2019-04-25 20:16:10,883 INFO  [org.apache.activemq.artemis] AMQ241002: Artemis Jolokia REST API available at http://localhost:8162/console/jolokia
2019-04-25 20:16:10,883 INFO  [org.apache.activemq.artemis] AMQ241004: Artemis Console available at http://localhost:8162/console

Body:
You need just to modify these two files us below :

$[broker_artemis_path]/etc/bootstrap.xml

<web bind="http://0.0.0.0:8161" path="web">
       <app url="activemq-branding" war="activemq-branding.war"/>
       <app url="artemis-plugin" war="artemis-plugin.war"/>
       <app url="console" war="console.war"/>
</web>

and  $[broker_artemis_path]/etc/jolokia-access.xml

<cors>
            <!-- Allow cross origin access from localhost ... -->
            <allow-origin>*://*</allow-origin>
            <!-- Options from this point on are auto-generated by Create.java from the Artemis CLI -->
            <!-- Check for the proper origin on the server side, too -->
            <strict-checking/>
</cors>

For more information you can check this link :
https://medium.com/@hasnat.saeed/setup-activemq-artemis-on-ubuntu-18-04-76bb4975308b


问:
History goBack not working at function component
I can't make a button that send de user to the previous page and I don´t know why, I've already done it at a class component and works, but know I'm trying to do it at a function component and it crashes

See the code:

```<code>import React, { Fragment } from "react";
import { connect } from "react-redux";
import { withRouter } from "react-router-dom";
import Header from "../components/recursableComponents/Header";
import { BASE_URL } from "../consts";

    function Collections(props) {
  const { classes } = props;
  const [collections, setCollection] = useState([]);
  const [choosedCollection, setChoosedCollection] = useState("");

  const getCollections = () => {
    const user = new User();
    const id_marca_estilo = user.user.id_marca_estilo;

  return (
    <Fragment>
      <Header
        title="Coleções"
        rightIcon={null}
        leftIcon={
          <IconButton
            aria-label="upload picture"
            component="span"
            className={classes.whiteButton}
            onClick={() => props.history.goBack()}
          >
            <ArrowBack></ArrowBack>
          </IconButton>
        }
      />
</code>```

答:
Please check this example

```<code>import React from "react";
import {BrowserRouter as Router, Switch, Route, Link} from "react-router-dom";
import {withRouter} from "react-router";

export default function RoutingGoBackExample() {
    return (
        <Router>
            <div>
                <ul>
                    <li>
                        <Link to="/">Home</Link>
                    </li>
                    <li>
                        <Link to="/about">About</Link>
                    </li>
                    <li>
                        <Link to="/about/insideabout">Inside About</Link>
                    </li>
                </ul>
                <hr/>
                <Switch>
                    <Route exact path="/">
                        <Home/>
                    </Route>
                    <Route exact path="/about">
                        <About/>
                    </Route>
                    <Route path="/about/insideabout">
                        <InsideAbout/>
                    </Route>
                </Switch>
            </div>
        </Router>
    );
}

function Home() {
    return (
        <div>
            <h2>Home</h2>
        </div>
    );
}

const About = withRouter(({history, ...props}) => (
    <div>
        <h1>
            About
            <hr/>
            <button onClick={() => {
                // history.push('/')
                history.goBack(-1);
            }}>go back
            </button>
        </h1>
    </div>
));

const InsideAbout = withRouter(({history, ...props}) => (
    <h1 {...props}>
        Inside About
        <hr/>

        <button onClick={() => {
            history.goBack();
        }}>go back
        </button>
        <button onClick={() => {
            history.go(-2);
        }}>go home
        </button>
    </h1>
));
</code>```

More Detail

Body:
I can't make a button that send de user to the previous page and I don´t know why, I've already done it at a class component and works, but know I'm trying to do it at a function component and it crashes

See the code:

import React, { Fragment } from "react";
import { connect } from "react-redux";
import { withRouter } from "react-router-dom";
import Header from "../components/recursableComponents/Header";
import { BASE_URL } from "../consts";

    function Collections(props) {
  const { classes } = props;
  const [collections, setCollection] = useState([]);
  const [choosedCollection, setChoosedCollection] = useState("");

  const getCollections = () => {
    const user = new User();
    const id_marca_estilo = user.user.id_marca_estilo;

  return (
    <Fragment>
      <Header
        title="Coleções"
        rightIcon={null}
        leftIcon={
          <IconButton
            aria-label="upload picture"
            component="span"
            className={classes.whiteButton}
            onClick={() => props.history.goBack()}
          >
            <ArrowBack></ArrowBack>
          </IconButton>
        }
      />

Body:
Please check this example

import React from "react";
import {BrowserRouter as Router, Switch, Route, Link} from "react-router-dom";
import {withRouter} from "react-router";

export default function RoutingGoBackExample() {
    return (
        <Router>
            <div>
                <ul>
                    <li>
                        <Link to="/">Home</Link>
                    </li>
                    <li>
                        <Link to="/about">About</Link>
                    </li>
                    <li>
                        <Link to="/about/insideabout">Inside About</Link>
                    </li>
                </ul>
                <hr/>
                <Switch>
                    <Route exact path="/">
                        <Home/>
                    </Route>
                    <Route exact path="/about">
                        <About/>
                    </Route>
                    <Route path="/about/insideabout">
                        <InsideAbout/>
                    </Route>
                </Switch>
            </div>
        </Router>
    );
}

function Home() {
    return (
        <div>
            <h2>Home</h2>
        </div>
    );
}

const About = withRouter(({history, ...props}) => (
    <div>
        <h1>
            About
            <hr/>
            <button onClick={() => {
                // history.push('/')
                history.goBack(-1);
            }}>go back
            </button>
        </h1>
    </div>
));

const InsideAbout = withRouter(({history, ...props}) => (
    <h1 {...props}>
        Inside About
        <hr/>

        <button onClick={() => {
            history.goBack();
        }}>go back
        </button>
        <button onClick={() => {
            history.go(-2);
        }}>go home
        </button>
    </h1>
));

More Detail