问:
How to select drop-down value in Protractor using framework: 'jasmine',
I am trying to select drop down list using protractor. None of this code works.

```<code>it("Select Block from District", function() {

    const selectElement={}
    selectElement.selectElementDropdown =function(element,index,milliseconds){
     console.log("Selecting element by drop down","OK");

     element.all(by.tagName('option')).then(function(options){

         options[2].click();
    //here index 2 is hardcoded, which can be changed to options[index]
     });

     if(typeof milliseconds!=='undefined'){
         browser.sleep(milliseconds);
     }

    }

    module.exports =selectElement;

    const methodDropDown = {} //require('../Src/SelectElement.js');

    var DistrictDetails = function(){

    this.DistrictName = element.all(by.xpath("//label[text()='Select Block']")).get(7).element(by.xpath("//option[contains(text(),'Ambabhona')]"));
    //the selector is clicked to open the drop down
</code>```

I have already gone through pass the value using send keys to text box

```<code><div _ngcontent-c9="" class="col-sm-6">
    <label _ngcontent-c9="" class="col-md-5 control-label">District
        <span _ngcontent-c9="" class="err-msg">*</span>
    </label>
    <div _ngcontent-c9="" class="col-md-7">
        <p-dropdown _ngcontent-c9="" formcontrolname="districtId" placeholder="Select District"
            class="ng-tns-c6-189 ng-pristine ng-invalid ng-touched">
            <div class="ng-tns-c6-189 ui-dropdown ui-widget ui-state-default ui-corner-all ui-helper-clearfix"
                style="width: 138px;">
                <!---->
                <div class="ui-helper-hidden-accessible ng-tns-c6-189 ng-star-inserted">
                    <select class="ng-tns-c6-189" aria-hidden="true" tabindex="-1" aria-label=" ">
                        <!---->
                        <option class="ng-tns-c6-189 ng-star-inserted">Select District</option>
                        <!---->
                        <!---->
                        <!---->
                        <!---->
                        <option class="ng-tns-c6-189 ng-star-inserted" value="390" style="">Bargarh</option>
                        <option class="ng-tns-c6-189 ng-star-inserted" value="391" style="">Jharsuguda</option>
                        <option class="ng-tns-c6-189 ng-star-inserted" value="392" style="">Sambalpur</option>
                        <option class="ng-tns-c6-189 ng-star-inserted" value="393" style="">Deogarh</option>
                        <option class="ng-tns-c6-189 ng-star-inserted" value="394" style="">Sundergarh</option>
                        <option class="ng-tns-c6-189 ng-star-inserted" value="395" style="">Keonjhar</option>
                        <option class="ng-tns-c6-189 ng-star-inserted" value="396" style="">Mayurbhanj</option>
                        <option class="ng-tns-c6-189 ng-star-inserted" value="397" style="">Balasore</option>
                        <option class="ng-tns-c6-189 ng-star-inserted" value="398" style="">Bhadrak</option>
                        <option class="ng-tns-c6-189 ng-star-inserted" value="399" style="">Kendrapara</option>
                        <option class="ng-tns-c6-189 ng-star-inserted" value="400" style="">Jagatsinghpur</option>
                        <option class="ng-tns-c6-189 ng-star-inserted" value="401" style="">Cuttack</option>
                        <option class="ng-tns-c6-189 ng-star-inserted" value="402" style="">Jajpur</option>
                        <option class="ng-tns-c6-189 ng-star-inserted" value="403" style="">Dhenkanal</option>
                        <option class="ng-tns-c6-189 ng-star-inserted" value="404" style="">Angul</option>
                        <option class="ng-tns-c6-189 ng-star-inserted" value="405" style="">Nayagarh</option>
                        <option class="ng-tns-c6-189 ng-star-inserted" value="406" style="">Khordha</option>
                        <option class="ng-tns-c6-189 ng-star-inserted" value="407" style="">Puri</option>
                        <option class="ng-tns-c6-189 ng-star-inserted" value="408" style="">Ganjam</option>
                        <option class="ng-tns-c6-189 ng-star-inserted" value="409" style="">Gajapati</option>
                        <option class="ng-tns-c6-189 ng-star-inserted" value="410" style="">Kandhamal</option>
                        <option class="ng-tns-c6-189 ng-star-inserted" value="411" style="">Boudh</option>
                        <option class="ng-tns-c6-189 ng-star-inserted" value="412" style="">Sonepur</option>
                        <option class="ng-tns-c6-189 ng-star-inserted" value="413" style="">Bolangir</option>
                        <option class="ng-tns-c6-189 ng-star-inserted" value="414" style="">Nuapada</option>
                        <option class="ng-tns-c6-189 ng-star-inserted" value="415" style="">Kalahandi</option>
                        <option class="ng-tns-c6-189 ng-star-inserted" value="416" style="">Rayagada</option>
                        <option class="ng-tns-c6-189 ng-star-inserted" value="417" style="">Nabarangpur</option>
                        <option class="ng-tns-c6-189 ng-star-inserted" value="418" style="">Koraput</option>
                        <option class="ng-tns-c6-189 ng-star-inserted" value="419" style="">Malkangiri</option>
                        <!---->
                    </select>
                </div>
                <div class="ui-helper-hidden-accessible">
                    <input class="ng-tns-c6-189" readonly="" role="listbox" type="text" aria-label=" ">
                </div>
                <!---->
                <!----><label
                    class="ng-tns-c6-189 ui-dropdown-label ui-inputtext ui-corner-all ui-placeholder ng-star-inserted">
                    Select District
                </label>
                <!---->
                <!---->
                <div class="ui-dropdown-trigger ui-state-default ui-corner-right"><span
                        class="ui-dropdown-trigger-icon ui-clickable pi pi-caret-down"></span>
                </div>
                <div class="ng-tns-c6-189 ui-dropdown-panel ui-widget-content ui-corner-all ui-shadow ng-trigger ng-trigger-panelState"
                    style="display: none; z-index: 1181; top: 27px; left: 0px; opacity: 0;">
                    <!---->
                    <div class="ui-dropdown-items-wrapper" style="max-height: 200px;">
                        <!---->
                    </div>
                </div>
            </div>
        </p-dropdown>
        <!---->
    </div>
</div>
</code>```

Want to select value form drop-down list like  Deogarh

答:
i think first you should check where options are by :

click drop-down-wrap

wait to drop down, options are shown.

click right mouse to an option and choose "inspect" .
Now you can see where options are.

follow your html code

```<code><select class="ng-tns-c6-189" aria-hidden="true" tabindex="-1" aria-label=" ">
</code>```

there is aria-hidden field in "select"

when you clicked drop-down-wrap, drop down and options are shown, aria-hidden field is false : (aria-hidden="false")

when drop-down closed, options aren't shown, aria-hidden="true".

So i think options and drop-down-wrap are same html page.

when you known where options are, you will write code right.
Recommend,your code should be written step by step :

var EC = protractor.ExpectedConditions;

click drop-down-wrap : choose one in two ways

element(by.css('p-dropdown div.ui-dropdown.ui-widget')).click();

browser.executeScript("arguments[0].click();", element(by.css('p-dropdown div.ui-dropdown.ui-widget')).getWebElement());

browser wait until options are shown

browser.wait(EC.presenceOf(element(by.css("select[aria-hidden="false"]"))));

or

browser.wait(EC.presenceOf(element(by.css("select[aria-hidden="false"] option:nth-child(2)"))));

or

browser.wait(EC.presenceOf(element(by.css("select[aria-hidden="false"] option[value="391"]"))));

Click the option what you want

browser.executeScript("arguments[0].click();", element(by.css("select[aria-hidden="false"] option[value="391"]")).getWebElement());

Body:
I am trying to select drop down list using protractor. None of this code works.

it("Select Block from District", function() {

    const selectElement={}
    selectElement.selectElementDropdown =function(element,index,milliseconds){
     console.log("Selecting element by drop down","OK");

     element.all(by.tagName('option')).then(function(options){

         options[2].click();
    //here index 2 is hardcoded, which can be changed to options[index]
     });

     if(typeof milliseconds!=='undefined'){
         browser.sleep(milliseconds);
     }

    }

    module.exports =selectElement;

    const methodDropDown = {} //require('../Src/SelectElement.js');

    var DistrictDetails = function(){

    this.DistrictName = element.all(by.xpath("//label[text()='Select Block']")).get(7).element(by.xpath("//option[contains(text(),'Ambabhona')]"));
    //the selector is clicked to open the drop down

I have already gone through pass the value using send keys to text box

    District
        *

                    <select class="ng-tns-c6-189" aria-hidden="true" tabindex="-1" aria-label=" ">

                        <option class="ng-tns-c6-189 ng-star-inserted">Select District</option>

                        <option class="ng-tns-c6-189 ng-star-inserted" value="390" style="">Bargarh</option>
                        <option class="ng-tns-c6-189 ng-star-inserted" value="391" style="">Jharsuguda</option>
                        <option class="ng-tns-c6-189 ng-star-inserted" value="392" style="">Sambalpur</option>
                        <option class="ng-tns-c6-189 ng-star-inserted" value="393" style="">Deogarh</option>
                        <option class="ng-tns-c6-189 ng-star-inserted" value="394" style="">Sundergarh</option>
                        <option class="ng-tns-c6-189 ng-star-inserted" value="395" style="">Keonjhar</option>
                        <option class="ng-tns-c6-189 ng-star-inserted" value="396" style="">Mayurbhanj</option>
                        <option class="ng-tns-c6-189 ng-star-inserted" value="397" style="">Balasore</option>
                        <option class="ng-tns-c6-189 ng-star-inserted" value="398" style="">Bhadrak</option>
                        <option class="ng-tns-c6-189 ng-star-inserted" value="399" style="">Kendrapara</option>
                        <option class="ng-tns-c6-189 ng-star-inserted" value="400" style="">Jagatsinghpur</option>
                        <option class="ng-tns-c6-189 ng-star-inserted" value="401" style="">Cuttack</option>
                        <option class="ng-tns-c6-189 ng-star-inserted" value="402" style="">Jajpur</option>
                        <option class="ng-tns-c6-189 ng-star-inserted" value="403" style="">Dhenkanal</option>
                        <option class="ng-tns-c6-189 ng-star-inserted" value="404" style="">Angul</option>
                        <option class="ng-tns-c6-189 ng-star-inserted" value="405" style="">Nayagarh</option>
                        <option class="ng-tns-c6-189 ng-star-inserted" value="406" style="">Khordha</option>
                        <option class="ng-tns-c6-189 ng-star-inserted" value="407" style="">Puri</option>
                        <option class="ng-tns-c6-189 ng-star-inserted" value="408" style="">Ganjam</option>
                        <option class="ng-tns-c6-189 ng-star-inserted" value="409" style="">Gajapati</option>
                        <option class="ng-tns-c6-189 ng-star-inserted" value="410" style="">Kandhamal</option>
                        <option class="ng-tns-c6-189 ng-star-inserted" value="411" style="">Boudh</option>
                        <option class="ng-tns-c6-189 ng-star-inserted" value="412" style="">Sonepur</option>
                        <option class="ng-tns-c6-189 ng-star-inserted" value="413" style="">Bolangir</option>
                        <option class="ng-tns-c6-189 ng-star-inserted" value="414" style="">Nuapada</option>
                        <option class="ng-tns-c6-189 ng-star-inserted" value="415" style="">Kalahandi</option>
                        <option class="ng-tns-c6-189 ng-star-inserted" value="416" style="">Rayagada</option>
                        <option class="ng-tns-c6-189 ng-star-inserted" value="417" style="">Nabarangpur</option>
                        <option class="ng-tns-c6-189 ng-star-inserted" value="418" style="">Koraput</option>
                        <option class="ng-tns-c6-189 ng-star-inserted" value="419" style="">Malkangiri</option>

                    </select>

                    <input class="ng-tns-c6-189" readonly="" role="listbox" type="text" aria-label=" ">

                    Select District

Want to select value form drop-down list like  Deogarh

Body:
i think first you should check where options are by :

click drop-down-wrap

wait to drop down, options are shown.

click right mouse to an option and choose "inspect" .
Now you can see where options are.

follow your html code

<select class="ng-tns-c6-189" aria-hidden="true" tabindex="-1" aria-label=" ">

there is aria-hidden field in "select"

when you clicked drop-down-wrap, drop down and options are shown, aria-hidden field is false : (aria-hidden="false")

when drop-down closed, options aren't shown, aria-hidden="true".

So i think options and drop-down-wrap are same html page.

when you known where options are, you will write code right.
Recommend,your code should be written step by step :

var EC = protractor.ExpectedConditions;

click drop-down-wrap : choose one in two ways

element(by.css('p-dropdown div.ui-dropdown.ui-widget')).click();

browser.executeScript("arguments[0].click();", element(by.css('p-dropdown div.ui-dropdown.ui-widget')).getWebElement());

browser wait until options are shown

browser.wait(EC.presenceOf(element(by.css("select[aria-hidden="false"]"))));

or

browser.wait(EC.presenceOf(element(by.css("select[aria-hidden="false"] option:nth-child(2)"))));

or

browser.wait(EC.presenceOf(element(by.css("select[aria-hidden="false"] option[value="391"]"))));

Click the option what you want

browser.executeScript("arguments[0].click();", element(by.css("select[aria-hidden="false"] option[value="391"]")).getWebElement());


来源: stackexchange

问:
How does SSL use symmetric and asymmetric encryption? And how do I manage certificated for multiple sites on one host?
First, some quotation from Microsoft TechNet's Managing Microsoft Certificate Services and SSL:

To recap, secure SSL sessions are established using the following technique:

The user's Web browser contacts the server using a secure URL.

The IIS server sends the browser its public key and server certificate.

The client and server negotiate the level of encryption to use for the
  secure communications.

The client browser encrypts a session key with the server's public
  key and sends the encrypted data back
  to the server.

The IIS Server decrypts the message sent by the client using its private
  key, and the session is established.

Both the client and the server use the session key to encrypt and decrypt
  transmitted data.

So, basically speaking, the SSL use the asymmetric encryption (public/private key pair) to deliver the shared session key, and finally achieved a communication way with symmetric encryption.

Is this right?

Add - 1 - 5:55 PM 12/17/2010

I am using IIS to host my websites. Suppose I have multiple sites on my single machine, and I want the client brower to use SSL URL to connect my sites. How many certificates do I need? Which of the following approach should I take?

1 - Apply for a single certicate and associate it to my single server machine which hosts mutiple sites.

2 - Apply for several certificates and associate each of my sites with its own certificate.

In IIS7, it seems I could only do approach 1.

Update - 1 - 6:09 PM 12/17/2010

I figure it out. I could install mutiple certificates on my server machine and bind each site with seperate certificate as necessary.

答:
.

The answer is both. You will find a nice explanation in 4 steps from digicert.com below:

.

Server sends a copy of its asymmetric public key.

Browser creates a symmetric session key and encrypts it with the server's asymmetric public key. Then sends it to the server.

Server decrypts the encrypted session key using its asymmetric private key to get the symmetric session key.

Server and Browser now encrypt and decrypt all transmitted data with the symmetric session key. This allows for a secure channel because
only the browser and the server know the symmetric session key, and
the session key is only used for that session. If the browser was to
connect to the same server the next day, a new session key would be
created.

https://www.digicert.com/ssl-cryptography.htm

ContentLicense: CC BY-SA 3.0

ContentLicense: CC BY-SA 4.0


问:
I have a folder that contains multiple folders which contain images. I want to filter the images based on dimensions
This code displays the ImageName and FolderName properly, but the Dimension remains blank.And the data which is displayed properly is not getting saved in a csv file.

Also, If condition based on dimension is not working.

```<code>#-----------powershell script------------
foreach ($folder in $Folders) {
    $Images = Get-ChildItem  -Path $Folder -Filter *.png
    $Results = @()
    foreach ($image  in $Images) {
        $dimensions = $image.Dimensions
        # $dimensions = "$($image.Width) x $($image.Height)"
        If ($dimensions -ne '1000 x 1000') {

            $Results += [pscustomobject]@{
                ImageName  = $image
                FolderName = $Folder
                Dimension  = $dimensions
            }
        }
    }

    $Results | FT -auto

    # $ExcelData= Format-Table -property @{n="$image";e='$Folder'}
    $Results | Export-csv "C:\Users\M1036098\Documents\Imagelessthan1000pi.txt" -NoTypeInformation

}
</code>```

Dimension property in output remains blank

答:
Thanks for the solution. I rewrote the code using System.Drawing.
    Code Snippet:

```<code>try{
    $FolderBase= "E:\D\Demo\Demo\"
    $Folders= get-ChildItem "$FolderBase*" |

    foreach ($folder in $Folders){

        $Images=Get-ChildItem  -Path $Folder -Filter *.png
        $Results = @()

        #$image=(Get-ChildItem  -Path $Folder *.png)
        $Images | ForEach-Object {
            $img = [Drawing.Image].FromFile($_);
            $dimensions = "$($img.Width) x $($img.Height)"

            If ($dimensions -ne "1000 x 1000") {
                $Results +=  [pscustomobject]@{
                    ImageName = $img
                    FolderName = $Folder
                    Dimension= $dimensions
                }
            }
        }
    }
    $Results | FT -auto
    # $ExcelData= Format-Table -property @{n="$image";e='$Folder'}
    $Results|Export-csv "C:\Users\****\Documents\Imagelessthan1000pi.txt" -NoTypeInformation
}catch{
}
</code>```

Now, I get the desired results but

I am not able to write the data to a file.(excel (preferred),csv,text). I tried out-File and Export-csv.

One of the folder contains a large no of big size(700 kb max) images. and while executing the loop on that particular folder,
memory exception is thrown and it does not loop through all the
images.

Body:
This code displays the ImageName and FolderName properly, but the Dimension remains blank.And the data which is displayed properly is not getting saved in a csv file.

Also, If condition based on dimension is not working.

#-----------powershell script------------
foreach ($folder in $Folders) {
    $Images = Get-ChildItem  -Path $Folder -Filter *.png
    $Results = @()
    foreach ($image  in $Images) {
        $dimensions = $image.Dimensions
        # $dimensions = "$($image.Width) x $($image.Height)"
        If ($dimensions -ne '1000 x 1000') {

            $Results += [pscustomobject]@{
                ImageName  = $image
                FolderName = $Folder
                Dimension  = $dimensions
            }
        }
    }

    $Results | FT -auto

    # $ExcelData= Format-Table -property @{n="$image";e='$Folder'}
    $Results | Export-csv "C:\Users\M1036098\Documents\Imagelessthan1000pi.txt" -NoTypeInformation

}

Dimension property in output remains blank

Body:
Thanks for the solution. I rewrote the code using System.Drawing.
    Code Snippet:

try{
    $FolderBase= "E:\D\Demo\Demo\"
    $Folders= get-ChildItem "$FolderBase*" |

    foreach ($folder in $Folders){

        $Images=Get-ChildItem  -Path $Folder -Filter *.png
        $Results = @()

        #$image=(Get-ChildItem  -Path $Folder *.png)
        $Images | ForEach-Object {
            $img = [Drawing.Image].FromFile($_);
            $dimensions = "$($img.Width) x $($img.Height)"

            If ($dimensions -ne "1000 x 1000") {
                $Results +=  [pscustomobject]@{
                    ImageName = $img
                    FolderName = $Folder
                    Dimension= $dimensions
                }
            }
        }
    }
    $Results | FT -auto
    # $ExcelData= Format-Table -property @{n="$image";e='$Folder'}
    $Results|Export-csv "C:\Users\****\Documents\Imagelessthan1000pi.txt" -NoTypeInformation
}catch{
}

Now, I get the desired results but

I am not able to write the data to a file.(excel (preferred),csv,text). I tried out-File and Export-csv.

One of the folder contains a large no of big size(700 kb max) images. and while executing the loop on that particular folder,
memory exception is thrown and it does not loop through all the
images.


问:
How to transform image to target image? Source image is dark gray, the target image has black, gray and white colors
The source image, it's result by gray converting from opencv.

```<code>cvtColor(img,COLOR_BGR2GRAY);
</code>```

How I can convert this image to target:

答:
histogram equalization function can be used to distribute intensity values range equally.

```<code>#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h>

using namespace cv;
using namespace std;

/**  @function main */
int main( int argc, char** argv )
{
  Mat src, dst;

  char* source_window = "Source image";
  char* equalized_window = "Equalized Image";

  /// Load image
  src = imread( "path_to_image", CV_LOAD_IMAGE_GRAYSCALE );

  /// Convert to grayscale
  //cvtColor( src, src, CV_BGR2GRAY );

  /// Apply Histogram Equalization
  equalizeHist( src, dst );

  /// Display results
  namedWindow( source_window, CV_WINDOW_AUTOSIZE );
  namedWindow( equalized_window, CV_WINDOW_AUTOSIZE );

  imshow( source_window, src );
  imshow( equalized_window, dst );

  /// Wait until user exits the program
  waitKey(0);

  return 0;
}
</code>```

Body:
The source image, it's result by gray converting from opencv.

cvtColor(img,COLOR_BGR2GRAY);

How I can convert this image to target:

Body:
histogram equalization function can be used to distribute intensity values range equally.

#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h>

using namespace cv;
using namespace std;

/**  @function main */
int main( int argc, char** argv )
{
  Mat src, dst;

  char* source_window = "Source image";
  char* equalized_window = "Equalized Image";

  /// Load image
  src = imread( "path_to_image", CV_LOAD_IMAGE_GRAYSCALE );

  /// Convert to grayscale
  //cvtColor( src, src, CV_BGR2GRAY );

  /// Apply Histogram Equalization
  equalizeHist( src, dst );

  /// Display results
  namedWindow( source_window, CV_WINDOW_AUTOSIZE );
  namedWindow( equalized_window, CV_WINDOW_AUTOSIZE );

  imshow( source_window, src );
  imshow( equalized_window, dst );

  /// Wait until user exits the program
  waitKey(0);

  return 0;
}


问:
RecyclerView search filter getting wrong position after filtering result
Hello friend please help me i am using Recylerview and implemented searchfilter but problem is that after searching the item in recylerview when i click on item   it always return 0 position of the item i want actual position of list item please me help here is my code how get actual position recylerview after searching item in recylerview

here is my code

```<code>package bible.swordof.God;

import android.content.Intent;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.speech.RecognizerIntent;
import android.support.design.widget.NavigationView;
import android.support.v4.app.Fragment;
import android.support.v4.view.GravityCompat;
import android.support.v4.view.MenuItemCompat;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.SearchView;
import android.support.v7.widget.Toolbar;
import android.text.TextUtils;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.Toast;

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

public class MainActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener, SearchView.OnQueryTextListener {
    private ListView listView;
    private ArrayList<String> books;
    private ArrayList<String> bookid;
    private ListViewAdapter adapter;
    private DatabaseHelper mDBHelper = null;
    private SQLiteDatabase mDb = null;
    BookRecyclerAdopter bookRecyclerAdopter;

//life is awesome

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
        ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
                this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
        drawer.addDrawerListener(toggle);
        toggle.syncState();

        NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
        navigationView.setNavigationItemSelectedListener(this);

        setData();
        RecyclerView bookanme = findViewById(R.id.list);
        bookanme.setLayoutManager(new LinearLayoutManager(this));

    bookRecyclerAdopter = new BookRecyclerAdopter(this, books);

        bookanme.setAdapter(bookRecyclerAdopter);

        /*    adapter = new ListViewAdapter(MainActivity.this, R.layout.item_listview, books, bookid);
        listView.setAdapter(adapter);*/

        /* listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {

                 int booknumber=position;
                 String  bookname=bookid.get(position);

                Toast.makeText(MainActivity.this, ""+bookname, Toast.LENGTH_SHORT).show();

             *//*   Intent intent=new Intent(MainActivity.this,Chapters.class);
                intent.putExtra("booknumber",booknumber);

                intent.putExtra("bookname",bookname);

                startActivity(intent);*//*

            }
        });
    }

*/
    }

    @Override
    public void onBackPressed() {
        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
        if (drawer.isDrawerOpen(GravityCompat.START)) {
            drawer.closeDrawer(GravityCompat.START);
        } else {
            super.onBackPressed();
        }
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {

        switch (item.getItemId()) {
            case R.id.search_voice_btn:
                Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
                intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
                intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, Locale.getDefault());
                if (intent.resolveActivity(getPackageManager()) != null) {
                    startActivityForResult(intent, 10);
                } else {
                    Toast.makeText(this, "Your Device Don't Support Speech Input", Toast.LENGTH_SHORT).show();
                }

                break;
        }
        return super.onOptionsItemSelected(item);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        switch (requestCode) {
            case 10:
                if (resultCode == RESULT_OK && data != null) {

                    ArrayList<String> result = data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS);

                    Toast.makeText(this, "" + result.get(0), Toast.LENGTH_SHORT).show();

                }
                break;
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.main, menu);

        MenuItem myActionMenuItem = menu.findItem(R.id.action_search);
        final SearchView searchView = (SearchView) MenuItemCompat.getActionView(myActionMenuItem);

        searchView.setOnQueryTextListener(this);

        return true;
    }

    @SuppressWarnings("StatementWithEmptyBody")
    @Override
    public boolean onNavigationItemSelected(MenuItem item) {
        // Handle navigation view item clicks here.
        Fragment fragment;
        int id = item.getItemId();

        if (id == R.id.home) {

            Intent intent = new Intent(this, MainActivity.class);
            startActivity(intent);

        } else if (id == R.id.favoruite) {
            Intent intent = new Intent(this, Favourite.class);

            startActivity(intent);
        } else if (id == R.id.nav_manage) {

        } else if (id == R.id.nav_share) {

        } else if (id == R.id.nav_send) {

        }

        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
        drawer.closeDrawer(GravityCompat.START);
        return true;
    }

    private void setData() {

        books = new ArrayList<>();
        bookid = new ArrayList<>();

        mDBHelper = new DatabaseHelper(this);
        mDb = mDBHelper.getReadableDatabase();

        Cursor cursor = mDb.rawQuery("select b,n from key_english", new String[]{});

        if (cursor != null && cursor.getCount() > 0) {
            if (cursor.moveToFirst()) {
                do {
                    books.add(cursor.getString(1));
                    bookid.add(cursor.getString(0));

                } while (cursor.moveToNext());
            }
        }
    }

    @Override
    public boolean onQueryTextSubmit(String s) {
        return false;
    }

    @Override
    public boolean onQueryTextChange(String newtext) {

        String userinput = newtext.toLowerCase();
        List<String> newlist = new ArrayList<>();
        for (String name : books) {

            if (name.toLowerCase().contains(userinput)) {

                newlist.add(name);

            }

        }

        bookRecyclerAdopter.updatelist(newlist);
        return true;

    }

}

package bible.swordof.God;

import android.app.Activity;
import android.content.Context;
import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Filter;
import android.widget.Filterable;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import com.amulyakhare.textdrawable.TextDrawable;
import com.amulyakhare.textdrawable.util.ColorGenerator;

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

public class BookRecyclerAdopter extends RecyclerView.Adapter<BookRecyclerAdopter.Booksholder>{

    private List<String> bookname;

Context context;

    public BookRecyclerAdopter(Context context,List<String> bookname) {
        this.bookname = bookname;
        this.context=context;

    }

    public class Booksholder extends RecyclerView.ViewHolder {
        private ImageView imageView;
        private TextView bookname;

        public Booksholder(@NonNull View itemView) {
            super(itemView);
            imageView = (ImageView) itemView.findViewById(R.id.image_view);
            bookname = (TextView) itemView.findViewById(R.id.text);

            itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {

                }
            });
        }
    }

    @Override
    public Booksholder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {

        LayoutInflater inflater = LayoutInflater.from(viewGroup.getContext());
        View view = inflater.inflate(R.layout.item_listview, viewGroup, false);

        return new Booksholder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull Booksholder booksholder, final int i) {
        booksholder.bookname.setText(bookname.get(i));

        //get first letter of each String item
        String firstLetter = String.valueOf(bookname.get(i).charAt(0));

        ColorGenerator generator = ColorGenerator.MATERIAL; // or use DEFAULT
        // generate random color
        int color = generator.getColor(bookname.get(i));

        TextDrawable drawable = TextDrawable.builder()
                .buildRound(firstLetter, color); // radius in px

        booksholder.imageView.setImageDrawable(drawable);

    }

    @Override
    public int getItemCount() {
        return bookname.size();
    }

public  void  updatelist(List<String>newlist){
        bookname=new ArrayList<>();
        bookname.addAll(newlist);
        notifyDataSetChanged();
}

}
</code>```

答:
You will need to maintain a separate list of bookname. Let's call it filteredBookname. Initially set it as bookname.

```<code>public class BookRecyclerAdopter extends RecyclerView.Adapter<BookRecyclerAdopter.Booksholder>{

    private List<String> bookname;
    private List<String> filteredBookname;

Context context;

    public BookRecyclerAdopter(Context context,List<String> bookname) {
        this.bookname = bookname;
        this.filteredBookname = bookname
        this.context=context;

    }
...
// other pieces of code.

</code>```

and instead of using bookname to populate RecyclerView items, use filteredBookname

and your update list method will be,

```<code>public  void  updatelist(List<String>newlist){
        filteredBookname=new ArrayList<>();
        filteredBookname.addAll(newlist);
        notifyDataSetChanged();
}
</code>```

Using the above approach, you can always find the proper position of your item in the original list bookname

Body:
Hello friend please help me i am using Recylerview and implemented searchfilter but problem is that after searching the item in recylerview when i click on item   it always return 0 position of the item i want actual position of list item please me help here is my code how get actual position recylerview after searching item in recylerview

here is my code

package bible.swordof.God;

import android.content.Intent;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.speech.RecognizerIntent;
import android.support.design.widget.NavigationView;
import android.support.v4.app.Fragment;
import android.support.v4.view.GravityCompat;
import android.support.v4.view.MenuItemCompat;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.SearchView;
import android.support.v7.widget.Toolbar;
import android.text.TextUtils;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.Toast;

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

public class MainActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener, SearchView.OnQueryTextListener {
    private ListView listView;
    private ArrayList<String> books;
    private ArrayList<String> bookid;
    private ListViewAdapter adapter;
    private DatabaseHelper mDBHelper = null;
    private SQLiteDatabase mDb = null;
    BookRecyclerAdopter bookRecyclerAdopter;

//life is awesome

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
        ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
                this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
        drawer.addDrawerListener(toggle);
        toggle.syncState();

        NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
        navigationView.setNavigationItemSelectedListener(this);

        setData();
        RecyclerView bookanme = findViewById(R.id.list);
        bookanme.setLayoutManager(new LinearLayoutManager(this));

    bookRecyclerAdopter = new BookRecyclerAdopter(this, books);

        bookanme.setAdapter(bookRecyclerAdopter);

        /*    adapter = new ListViewAdapter(MainActivity.this, R.layout.item_listview, books, bookid);
        listView.setAdapter(adapter);*/

        /* listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {

                 int booknumber=position;
                 String  bookname=bookid.get(position);

                Toast.makeText(MainActivity.this, ""+bookname, Toast.LENGTH_SHORT).show();

             *//*   Intent intent=new Intent(MainActivity.this,Chapters.class);
                intent.putExtra("booknumber",booknumber);

                intent.putExtra("bookname",bookname);

                startActivity(intent);*//*

            }
        });
    }

*/
    }

    @Override
    public void onBackPressed() {
        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
        if (drawer.isDrawerOpen(GravityCompat.START)) {
            drawer.closeDrawer(GravityCompat.START);
        } else {
            super.onBackPressed();
        }
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {

        switch (item.getItemId()) {
            case R.id.search_voice_btn:
                Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
                intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
                intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, Locale.getDefault());
                if (intent.resolveActivity(getPackageManager()) != null) {
                    startActivityForResult(intent, 10);
                } else {
                    Toast.makeText(this, "Your Device Don't Support Speech Input", Toast.LENGTH_SHORT).show();
                }

                break;
        }
        return super.onOptionsItemSelected(item);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        switch (requestCode) {
            case 10:
                if (resultCode == RESULT_OK && data != null) {

                    ArrayList<String> result = data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS);

                    Toast.makeText(this, "" + result.get(0), Toast.LENGTH_SHORT).show();

                }
                break;
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.main, menu);

        MenuItem myActionMenuItem = menu.findItem(R.id.action_search);
        final SearchView searchView = (SearchView) MenuItemCompat.getActionView(myActionMenuItem);

        searchView.setOnQueryTextListener(this);

        return true;
    }

    @SuppressWarnings("StatementWithEmptyBody")
    @Override
    public boolean onNavigationItemSelected(MenuItem item) {
        // Handle navigation view item clicks here.
        Fragment fragment;
        int id = item.getItemId();

        if (id == R.id.home) {

            Intent intent = new Intent(this, MainActivity.class);
            startActivity(intent);

        } else if (id == R.id.favoruite) {
            Intent intent = new Intent(this, Favourite.class);

            startActivity(intent);
        } else if (id == R.id.nav_manage) {

        } else if (id == R.id.nav_share) {

        } else if (id == R.id.nav_send) {

        }

        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
        drawer.closeDrawer(GravityCompat.START);
        return true;
    }

    private void setData() {

        books = new ArrayList<>();
        bookid = new ArrayList<>();

        mDBHelper = new DatabaseHelper(this);
        mDb = mDBHelper.getReadableDatabase();

        Cursor cursor = mDb.rawQuery("select b,n from key_english", new String[]{});

        if (cursor != null && cursor.getCount() > 0) {
            if (cursor.moveToFirst()) {
                do {
                    books.add(cursor.getString(1));
                    bookid.add(cursor.getString(0));

                } while (cursor.moveToNext());
            }
        }
    }

    @Override
    public boolean onQueryTextSubmit(String s) {
        return false;
    }

    @Override
    public boolean onQueryTextChange(String newtext) {

        String userinput = newtext.toLowerCase();
        List<String> newlist = new ArrayList<>();
        for (String name : books) {

            if (name.toLowerCase().contains(userinput)) {

                newlist.add(name);

            }

        }

        bookRecyclerAdopter.updatelist(newlist);
        return true;

    }

}

package bible.swordof.God;

import android.app.Activity;
import android.content.Context;
import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Filter;
import android.widget.Filterable;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import com.amulyakhare.textdrawable.TextDrawable;
import com.amulyakhare.textdrawable.util.ColorGenerator;

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

public class BookRecyclerAdopter extends RecyclerView.Adapter<BookRecyclerAdopter.Booksholder>{

    private List<String> bookname;

Context context;

    public BookRecyclerAdopter(Context context,List<String> bookname) {
        this.bookname = bookname;
        this.context=context;

    }

    public class Booksholder extends RecyclerView.ViewHolder {
        private ImageView imageView;
        private TextView bookname;

        public Booksholder(@NonNull View itemView) {
            super(itemView);
            imageView = (ImageView) itemView.findViewById(R.id.image_view);
            bookname = (TextView) itemView.findViewById(R.id.text);

            itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {

                }
            });
        }
    }

    @Override
    public Booksholder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {

        LayoutInflater inflater = LayoutInflater.from(viewGroup.getContext());
        View view = inflater.inflate(R.layout.item_listview, viewGroup, false);

        return new Booksholder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull Booksholder booksholder, final int i) {
        booksholder.bookname.setText(bookname.get(i));

        //get first letter of each String item
        String firstLetter = String.valueOf(bookname.get(i).charAt(0));

        ColorGenerator generator = ColorGenerator.MATERIAL; // or use DEFAULT
        // generate random color
        int color = generator.getColor(bookname.get(i));

        TextDrawable drawable = TextDrawable.builder()
                .buildRound(firstLetter, color); // radius in px

        booksholder.imageView.setImageDrawable(drawable);

    }

    @Override
    public int getItemCount() {
        return bookname.size();
    }

public  void  updatelist(List<String>newlist){
        bookname=new ArrayList<>();
        bookname.addAll(newlist);
        notifyDataSetChanged();
}

}

Body:
You will need to maintain a separate list of bookname. Let's call it filteredBookname. Initially set it as bookname.

public class BookRecyclerAdopter extends RecyclerView.Adapter<BookRecyclerAdopter.Booksholder>{

    private List<String> bookname;
    private List<String> filteredBookname;

Context context;

    public BookRecyclerAdopter(Context context,List<String> bookname) {
        this.bookname = bookname;
        this.filteredBookname = bookname
        this.context=context;

    }
...
// other pieces of code.

and instead of using bookname to populate RecyclerView items, use filteredBookname

and your update list method will be,

public  void  updatelist(List<String>newlist){
        filteredBookname=new ArrayList<>();
        filteredBookname.addAll(newlist);
        notifyDataSetChanged();
}

Using the above approach, you can always find the proper position of your item in the original list bookname


问:
Is there a way to overload an abstract method in a functional interface?
I would like to be able to provide a functional interface that accepts several different types of lambda functions.

I read this. The first answer to this question clarifies why overloading an abstract method in a functional interface could cause undefined behavior. However, is there a way to do the equivalent of overloading an abstract method in a functional interface if I supply all of the defaults?

I would like to be able to write something like the following code:

Ball b = () -> System.out.println("You hit it!");
Ball ba = (boolean miss) -> System.out.println(miss);

b.hit();
b.hit(false);
ba.hit();
ba.hit(false);
```

<p>The desired result would be:</p>

```You hit it!
default false
default hit
false
```

<p>Consider the following (non-compilable) code (mostly copied from the linked question):</p>

```@FunctionalInterface
public interface Ball
{
    void hit();
    void hit(boolean miss);
    default void hit(){
        System.out.println("default hit");
    }
    default void hit(boolean miss){
        System.out.println("default" + miss);
    }

}
```

I am looking for an alternative to this code that would compile.

答:
You could wrap the interface in a class and then pass on the method calls to the interfaces internally.

Example code:

public class Test{
    public static void main(String... args) throws Exception{
        Ball b = new Ball(() -> System.out.println("You hit it!"));
        Ball ba = new Ball((boolean miss) -> System.out.println(miss));

        b.hit();
        b.hit(false);
        ba.hit();
        ba.hit(false);
    }

    public static class Ball{
        final Hit a;
        final HitBoolean b;

        public Ball(Hit a){
            this.a = a;
            b = (miss) -> System.out.println("default " + miss);
        }

        public Ball(HitBoolean b){
            this.b = b;
            a = () -> System.out.println("default hit");
        }

        public void hit(){
            a.hit();
        }

        public void hit(boolean miss){
            b.hit(miss);
        }
    }

    public interface Hit{
        void hit();
    }

    public interface HitBoolean{
        void hit(boolean miss);
    }
}
```
<p>Output of the program:</p>
```You hit it!
default false
default hit
false
```

Body:
I would like to be able to provide a functional interface that accepts several different types of lambda functions.

I read this. The first answer to this question clarifies why overloading an abstract method in a functional interface could cause undefined behavior. However, is there a way to do the equivalent of overloading an abstract method in a functional interface if I supply all of the defaults?

I would like to be able to write something like the following code:

Ball b = () -> System.out.println("You hit it!");
Ball ba = (boolean miss) -> System.out.println(miss);

b.hit();
b.hit(false);
ba.hit();
ba.hit(false);

The desired result would be:

You hit it!
default false
default hit
false

Consider the following (non-compilable) code (mostly copied from the linked question):

@FunctionalInterface
public interface Ball
{
    void hit();
    void hit(boolean miss);
    default void hit(){
        System.out.println("default hit");
    }
    default void hit(boolean miss){
        System.out.println("default" + miss);
    }

}

I am looking for an alternative to this code that would compile.

Body:
You could wrap the interface in a class and then pass on the method calls to the interfaces internally.

Example code:

public class Test{
    public static void main(String... args) throws Exception{
        Ball b = new Ball(() -> System.out.println("You hit it!"));
        Ball ba = new Ball((boolean miss) -> System.out.println(miss));

        b.hit();
        b.hit(false);
        ba.hit();
        ba.hit(false);
    }

    public static class Ball{
        final Hit a;
        final HitBoolean b;

        public Ball(Hit a){
            this.a = a;
            b = (miss) -> System.out.println("default " + miss);
        }

        public Ball(HitBoolean b){
            this.b = b;
            a = () -> System.out.println("default hit");
        }

        public void hit(){
            a.hit();
        }

        public void hit(boolean miss){
            b.hit(miss);
        }
    }

    public interface Hit{
        void hit();
    }

    public interface HitBoolean{
        void hit(boolean miss);
    }
}

Output of the program:

You hit it!
default false
default hit
false


问:
Why are these two SQL date functions not providing the same answer
I've actually already solved the problem, but I'm trying to understand why the problem occurred because as far as I can see it has no reason to happen.
I have a rather large query that I run to prepare a table with some often used combinations. Generally, it only contains 2 years of data. Occasionally I will reconstruct it. While doing this I tweaked the query to add more information, but suddenly the result no longer matched up to the old query. Comparing the old to the new I noticed several missing orders. Amazingly, even after removing the tweaked parts the results still didn't match up.

I ultimately tracked the problem down to my WHERE clause, which was different from how I did it last time.

The type of the orderdate column I go over has type (datetime, null)

One of the orders that was omitted had this as date:

```<code>2018-12-23 20:58:52.383
</code>```

An order that was included had this as date:

```<code>2019-01-28 15:20:49.107
</code>```

It looks exactly the same to me.

The entire query is the same, except for the WHERE clause. My original where was:

```<code>WHERE DATEPART(yyyy,tbOrder.[OrderDate]) >= DATEPART(yyyy,GETDATE()-2)
</code>```

My new where is now:

```<code>WHERE tborder.[OrderDate] >= DATEADD(yy, DATEDIFF(yy, 0, GETDATE())-2, 0)
</code>```

Any help in understanding why the original where clause drops some lines would be greatly appreciated.

答:
The two expressions return completely different things, so it shouldn't be a surprise the results are different. The first one returns the current year as a number (or the year of the day before yesterday to be precise). The second one returns January 1st two years ago.

You can put both expressions in a SELECT query to see what they return :

```<code>select DATEPART(yyyy,GETDATE()-2),  DATEADD(yy, DATEDIFF(yy, 0, GETDATE()) - 2, 0)
</code>```

The result is :

```<code>2019    2017-01-01 00:00:00.000
</code>```

Both expressions are more complex than they need to be. The first condition will also harm performance because DATEPART(yyyy,tbOrder.[OrderDate]) prevents the server from using any indexes that cover OrderDate.

The question doesn't explain what you actually want to return. If you wanted to return all rows in the current year you can use :

```<code>Where
    OrderDate >=DATEFROMPARTS( YEAR(GETDATE()) ,1,1) and
    OrderDate < DATEFROMPARTS( YEAR(GETDATE()) + 1,1,1)
</code>```

The same can be used to find rows two years in the past :

```<code>Where
    OrderDate >= DATEFROMPARTS( YEAR(GETDATE()) -2 ,1,1) and
    OrderDate < DATEFROMPARTS(YEAR(GETDATE()) - 1,1,1)
</code>```

All rows since January 1st two years ago :

```<code>Where OrderDate >= DATEFROMPARTS( YEAR(GETDATE()) -2 ,1,1)
</code>```

All those queries can take advantage of indexes that cover OrderDate.

Date range queries become a lot easier if you use a Calendar table. A Calendar table is a table that contains eg 50 or 100 years' worth of dates with extra columns for month, month day, week number, day of week, quarter, semester, month and day names, holidays, business reprorint periods, formatted short, long dates etc.

This makes yearly, monthly or weekly queries as easy as joining with the Calendar table and filtering based on the month or period you want.

In this case, retrieving rows two yeas in the past would look like :

```<code>From Orders inner Join Calendar on OrderDate=Calendar.Date
Where Calendar.Year=YEAR(GETDATE())-2
</code>```

That may not looks so impressive but what about Q2 two years ago?

```<code>From Orders inner Join Calendar on OrderDate=Calendar.Date
Where Calendar.Year=YEAR(GETDATE())-2 and Quarter=2
</code>```

Two years ago, same quarter

```<code>From Orders inner Join Calendar on OrderDate=Calendar.Date
Where Calendar.Year=YEAR(GETDATE())-2 and Quarter=DATEPART(q,GETDATE())
</code>```

Retrieving totals for the current quarter for the last two years :

```<code>SELECT Year,Quarter,SUM(Total) QuarterTotal
From Orders inner Join Calendar on OrderDate=Calendar.Date
Where Calendar.Year > YEAR(GETDATE())-2 and Quarter=DATEPART(q,GETDATE())
GROUP BY Calendar.Year
</code>```

Body:
I've actually already solved the problem, but I'm trying to understand why the problem occurred because as far as I can see it has no reason to happen.
I have a rather large query that I run to prepare a table with some often used combinations. Generally, it only contains 2 years of data. Occasionally I will reconstruct it. While doing this I tweaked the query to add more information, but suddenly the result no longer matched up to the old query. Comparing the old to the new I noticed several missing orders. Amazingly, even after removing the tweaked parts the results still didn't match up.

I ultimately tracked the problem down to my WHERE clause, which was different from how I did it last time.

The type of the orderdate column I go over has type (datetime, null)

One of the orders that was omitted had this as date:

2018-12-23 20:58:52.383

An order that was included had this as date:

2019-01-28 15:20:49.107

It looks exactly the same to me.

The entire query is the same, except for the WHERE clause. My original where was:

WHERE DATEPART(yyyy,tbOrder.[OrderDate]) >= DATEPART(yyyy,GETDATE()-2)

My new where is now:

WHERE tborder.[OrderDate] >= DATEADD(yy, DATEDIFF(yy, 0, GETDATE())-2, 0)

Any help in understanding why the original where clause drops some lines would be greatly appreciated.

Body:
The two expressions return completely different things, so it shouldn't be a surprise the results are different. The first one returns the current year as a number (or the year of the day before yesterday to be precise). The second one returns January 1st two years ago.

You can put both expressions in a SELECT query to see what they return :

select DATEPART(yyyy,GETDATE()-2),  DATEADD(yy, DATEDIFF(yy, 0, GETDATE()) - 2, 0)

The result is :

2019    2017-01-01 00:00:00.000

Both expressions are more complex than they need to be. The first condition will also harm performance because DATEPART(yyyy,tbOrder.[OrderDate]) prevents the server from using any indexes that cover OrderDate.

The question doesn't explain what you actually want to return. If you wanted to return all rows in the current year you can use :

Where
    OrderDate >=DATEFROMPARTS( YEAR(GETDATE()) ,1,1) and
    OrderDate < DATEFROMPARTS( YEAR(GETDATE()) + 1,1,1)

The same can be used to find rows two years in the past :

Where
    OrderDate >= DATEFROMPARTS( YEAR(GETDATE()) -2 ,1,1) and
    OrderDate < DATEFROMPARTS(YEAR(GETDATE()) - 1,1,1)

All rows since January 1st two years ago :

Where OrderDate >= DATEFROMPARTS( YEAR(GETDATE()) -2 ,1,1)

All those queries can take advantage of indexes that cover OrderDate.

Date range queries become a lot easier if you use a Calendar table. A Calendar table is a table that contains eg 50 or 100 years' worth of dates with extra columns for month, month day, week number, day of week, quarter, semester, month and day names, holidays, business reprorint periods, formatted short, long dates etc.

This makes yearly, monthly or weekly queries as easy as joining with the Calendar table and filtering based on the month or period you want.

In this case, retrieving rows two yeas in the past would look like :

From Orders inner Join Calendar on OrderDate=Calendar.Date
Where Calendar.Year=YEAR(GETDATE())-2

That may not looks so impressive but what about Q2 two years ago?

From Orders inner Join Calendar on OrderDate=Calendar.Date
Where Calendar.Year=YEAR(GETDATE())-2 and Quarter=2

Two years ago, same quarter

From Orders inner Join Calendar on OrderDate=Calendar.Date
Where Calendar.Year=YEAR(GETDATE())-2 and Quarter=DATEPART(q,GETDATE())

Retrieving totals for the current quarter for the last two years :

SELECT Year,Quarter,SUM(Total) QuarterTotal
From Orders inner Join Calendar on OrderDate=Calendar.Date
Where Calendar.Year > YEAR(GETDATE())-2 and Quarter=DATEPART(q,GETDATE())
GROUP BY Calendar.Year


问:
Updating a field in MondoDB
I am writing a multi-user online dictionary. I want to implement a leadership board, e.i. "score" attribute increases, as soon as a user adds a word. I have a rough idea on how to do it, and tried one solution, however it does not work. Could you please guide me?

Word API route

```<code>const express = require('express');
const router = express.Router();
const Word = require('../../models/Word');
const User = require('../../models/User');

const validateWordInput = require('../../validation/word');
const passport = require('passport');

// @route  POST api/words
// @desc   Add words to profile
// @access Private
router.post(
  '/',
  passport.authenticate('jwt', { session: false }),
  (req, res) => {
    const { errors, isValid } = validateWordInput(req.body);

    // Check validation
    if (!isValid) {
      // Return any errors
      return res.status(400).json(errors);
    }

    Word.find({}).then(word => {
      if (
        word.filter(
          wrd =>
            wrd.ugrWordCyr.toString().toLowerCase() ===
            req.body.ugrWordCyr.toLowerCase()
        ).length !== 0
      ) {
        return res
          .status(404)
          .json({ wordalreadyexists: 'Word already exists' });
      } else {
        const newWord = new Word({
          user: req.user.id,
          ugrWordCyr: req.body.ugrWordCyr,
          rusTranslation: req.body.rusTranslation,
          example: req.body.example,
          exampleTranslation: req.body.exampleTranslation,
          origin: req.body.origin,
          sphere: req.body.sphere,
          lexis: req.body.lexis,
          grammar: req.body.grammar,
          partOfSpeech: req.body.partOfSpeech,
          style: req.body.style
        });

        newWord.save().then(word => res.json(word));
        User.update(
          { _id: '5cf0cb78b3105d1ba8e30331' },
          { $inc: { score: 1 } }
        );
      }
    });
  }
);
</code>```

User model

This is where a score attribute is located

```<code>const mongoose = require('mongoose');
const Schema = mongoose.Schema;

// Create schema
const userSchema = new Schema({
  name: {
    type: String,
    required: true
  },
  email: {
    type: String,
    required: true
  },
  password: {
    type: String,
    required: true
  },
  score: {
    type: Number,
    default: 0
  },
  avatar: {
    type: String
  },
  date: {
    type: Date,
    default: Date.now
  }
});

module.exports = User = mongoose.model('users', userSchema);
</code>```

答:
After successfully saving the word, we should update the user count

To update the respective user's score you can do the following:

```<code>newWord.save().then((word) => {

    //now update user model
    User.findOne({ _id: req.user.id }) <-- or an id you would like
        .then((foundUser) => {
             foundUser.score = foundUser.score + 1

             foundUser.save()
                .then((savedUser) => {
                    res.json({ word, savedUser })
                })
                .catch((err) => {
                    return res.status(400).json({ error: "could not add score"})
                })
        })
        .catch((err) => {
           return res.status(400).json({ error: "could not find user"})
        })

})
</code>```

Title: Updating a field in MondoDB

Body:
I am writing a multi-user online dictionary. I want to implement a leadership board, e.i. "score" attribute increases, as soon as a user adds a word. I have a rough idea on how to do it, and tried one solution, however it does not work. Could you please guide me?

Word API route

const express = require('express');
const router = express.Router();
const Word = require('../../models/Word');
const User = require('../../models/User');

const validateWordInput = require('../../validation/word');
const passport = require('passport');

// @route  POST api/words
// @desc   Add words to profile
// @access Private
router.post(
  '/',
  passport.authenticate('jwt', { session: false }),
  (req, res) => {
    const { errors, isValid } = validateWordInput(req.body);

    // Check validation
    if (!isValid) {
      // Return any errors
      return res.status(400).json(errors);
    }

    Word.find({}).then(word => {
      if (
        word.filter(
          wrd =>
            wrd.ugrWordCyr.toString().toLowerCase() ===
            req.body.ugrWordCyr.toLowerCase()
        ).length !== 0
      ) {
        return res
          .status(404)
          .json({ wordalreadyexists: 'Word already exists' });
      } else {
        const newWord = new Word({
          user: req.user.id,
          ugrWordCyr: req.body.ugrWordCyr,
          rusTranslation: req.body.rusTranslation,
          example: req.body.example,
          exampleTranslation: req.body.exampleTranslation,
          origin: req.body.origin,
          sphere: req.body.sphere,
          lexis: req.body.lexis,
          grammar: req.body.grammar,
          partOfSpeech: req.body.partOfSpeech,
          style: req.body.style
        });

        newWord.save().then(word => res.json(word));
        User.update(
          { _id: '5cf0cb78b3105d1ba8e30331' },
          { $inc: { score: 1 } }
        );
      }
    });
  }
);

User model

This is where a score attribute is located

const mongoose = require('mongoose');
const Schema = mongoose.Schema;

// Create schema
const userSchema = new Schema({
  name: {
    type: String,
    required: true
  },
  email: {
    type: String,
    required: true
  },
  password: {
    type: String,
    required: true
  },
  score: {
    type: Number,
    default: 0
  },
  avatar: {
    type: String
  },
  date: {
    type: Date,
    default: Date.now
  }
});

module.exports = User = mongoose.model('users', userSchema);

Body:
After successfully saving the word, we should update the user count

To update the respective user's score you can do the following:

newWord.save().then((word) => {

    //now update user model
    User.findOne({ _id: req.user.id }) <-- or an id you would like
        .then((foundUser) => {
             foundUser.score = foundUser.score + 1

             foundUser.save()
                .then((savedUser) => {
                    res.json({ word, savedUser })
                })
                .catch((err) => {
                    return res.status(400).json({ error: "could not add score"})
                })
        })
        .catch((err) => {
           return res.status(400).json({ error: "could not find user"})
        })

})


问:
Cant set Triggers to Toggle Button
I can't attach triggers to a toggle button

In the first version, I get an error that the style is already redefined

In the second version with triggers, I get an error that property
Command - The member "Command" is not recognized or is not accessible.

This is Button

<ToggleButton
               Name="ToggleButton_Record"
               IsChecked="False"
               Style="{StaticResource MaterialDesignActionToggleButton}"
               ToolTip="Записать">

               <materialDesign:PackIcon
                    HorizontalAlignment="Center"
                    VerticalAlignment="Center"
                    Foreground="OrangeRed"
                    Kind="Record" />

</ToggleButton>
```

<p>This is 1st variant</p>

<pre class="lang-xml prettyprint-override"><code> <ToggleButton.Style>
                   <Style TargetType="{x:Type ToggleButton}">
                       <Style.Triggers>
                            <Trigger Property="ToggleButton.IsChecked" Value="True">
                                 <Setter Property="Command" Value="{Binding StartRecordCommand}" />
                            </Trigger>
                            <Trigger Property="ToggleButton.IsChecked" Value="False">
                                  <Setter Property="Command" Value="{Binding StopRecordCommand}" />
                            </Trigger>
                        </Style.Triggers>
                   </Style>
 </ToggleButton.Style>
</code>```

2nd variant with triggers

 <ToggleButton.Triggers>
           <Trigger Property="ToggleButton.IsChecked" Value="True">
                <Setter Property="Command" Value="{Binding StartRecordCommand}" />
           </Trigger>
           <Trigger Property="ToggleButton.IsChecked" Value="False">
                <Setter Property="Command" Value="{Binding StopRecordCommand}" />
           </Trigger>
</ToggleButton.Triggers>
```

Yes I know that in 1st variant I just remove style in button and its starting works, but I need this style.

答:
Use the 1st Variant. Remove the Style="{..}". and then, in the Style you defined, add the BasedOn.

```<code><ToggleButton
               Name="ToggleButton_Record"
               IsChecked="False"
               ToolTip="Записать">

              <ToggleButton.Style>
                   <Style TargetType="{x:Type ToggleButton}" BasedOn="{StaticResource MaterialDesignActionToggleButton}">
                       <Style.Triggers>
                            <Trigger Property="ToggleButton.IsChecked" Value="True">
                                 <Setter Property="Command" Value="{Binding StartRecordCommand}" />
                            </Trigger>
                            <Trigger Property="ToggleButton.IsChecked" Value="False">
                                  <Setter Property="Command" Value="{Binding StopRecordCommand}" />
                            </Trigger>
                        </Style.Triggers>
                   </Style>
              </ToggleButton.Style>

               <materialDesign:PackIcon
                    HorizontalAlignment="Center"
                    VerticalAlignment="Center"
                    Foreground="OrangeRed"
                    Kind="Record" />

</ToggleButton>
</code>```

Title: Cant set Triggers to Toggle Button

Body:
I can't attach triggers to a toggle button

In the first version, I get an error that the style is already redefined

In the second version with triggers, I get an error that property
Command - The member "Command" is not recognized or is not accessible.

This is Button

<ToggleButton
               Name="ToggleButton_Record"
               IsChecked="False"
               Style="{StaticResource MaterialDesignActionToggleButton}"
               ToolTip="Записать">

               <materialDesign:PackIcon
                    HorizontalAlignment="Center"
                    VerticalAlignment="Center"
                    Foreground="OrangeRed"
                    Kind="Record" />

</ToggleButton>

This is 1st variant

 <ToggleButton.Style>

                   </Style>
 </ToggleButton.Style>

2nd variant with triggers

 <ToggleButton.Triggers>
           <Trigger Property="ToggleButton.IsChecked" Value="True">
                <Setter Property="Command" Value="{Binding StartRecordCommand}" />
           </Trigger>
           <Trigger Property="ToggleButton.IsChecked" Value="False">
                <Setter Property="Command" Value="{Binding StopRecordCommand}" />
           </Trigger>
</ToggleButton.Triggers>

Yes I know that in 1st variant I just remove style in button and its starting works, but I need this style.

Body:
Use the 1st Variant. Remove the Style="{..}". and then, in the Style you defined, add the BasedOn.

<ToggleButton
               Name="ToggleButton_Record"
               IsChecked="False"
               ToolTip="Записать">

              <ToggleButton.Style>
                   <Style TargetType="{x:Type ToggleButton}" BasedOn="{StaticResource MaterialDesignActionToggleButton}">
                       <Style.Triggers>
                            <Trigger Property="ToggleButton.IsChecked" Value="True">
                                 <Setter Property="Command" Value="{Binding StartRecordCommand}" />
                            </Trigger>
                            <Trigger Property="ToggleButton.IsChecked" Value="False">
                                  <Setter Property="Command" Value="{Binding StopRecordCommand}" />
                            </Trigger>
                        </Style.Triggers>
                   </Style>
              </ToggleButton.Style>

               <materialDesign:PackIcon
                    HorizontalAlignment="Center"
                    VerticalAlignment="Center"
                    Foreground="OrangeRed"
                    Kind="Record" />

</ToggleButton>


问:
How to retrieve substring which is outside of brackets in JS?
I want the text which is outside of brackets, for eg.

Text is - Outside (inside)

and what I expect is - Outside

Can someone please help me to achieve this.

答:
You can use slice & use indexOf to get the first (. This will extract all the characters before first (

let str = 'Outside (inside)'

let substr = str.slice(0, str.indexOf('('));
console.log(substr.trim())```


问:
JS code to have multiple functions be applied to a cell on edit
I am currently trying to write some JS in script editor on a google sheet to not only produce a timestamp in conjunction with a check box being clicked but also set a timer that if the box is check for more than X minutes the cell will start to turn red.

Also when I uncheck the box to make the cell green.  The idea behind this is think of a restaurant hostess paradigm when I click the box that means table is full timestamp gives me the time the box was checked and color shows its not available - IF I uncheck box it gives time stamp it was unchecked while also resetting time counter and changing the cell back to green.  Currently I can get the timestamp portion to work with the code I wrote and it to change color on the first edit but it will not vacillate between colors based on the check box

Below is the code I currently have.  Would a trigger function or another on edit function be used If anyone has any tips or ideas it would be greatly appreciated

For visual each column i'm referencing is a stagnate column 1 which is seat number the check boxes going down the 2nd column and the 3rd column which is populating what time the box is checked and unchecked

function onEdit() {
  var s = SpreadsheetApp.getActiveSheet();
  if (s.getName() == "Sheet1") { //checks that we're on the correct sheet
    var r = s.getActiveCell();
    if (r.getColumn() == 5) { //checks the column
      var nextCell = r.offset(0, 1);
      //if( nextCell.getValue() !== '' ) //is empty?
      nextCell.setValue(new Date().setFontColor('green');
      }
```

答:
The code below should work:

```<code>function onEdit(e) {

  var s = SpreadsheetApp.getActiveSheet(); // the active sheet (no need to check if the sheet == sheet1 as the active sheet will always be the one that's being edited)
  var r = e.range; // the range of the edited cell
  var c = r.getColumn(); // the column of the range
  var timeDelay = 5; // number in seconds
  var checkbox = r.getValue(); // the value of the checkbox after being edited
  var date = new Date(); // the date for the timestamp

  if (c == 5 && checkbox == true) { // if the checkbox has been checked, change the color to red
    var nextCell = r.offset(0,1);
    Utilities.sleep(timeDelay * 1000); // Utilities.sleep takes a number in milliseconds
    nextCell.setValue(date).setBackground("red");
  } else if (c == 5 && checkbox == false) { // if the checkbox has been unchecked, change the color to green
    var nextCell = r.offset(0,1);
    nextCell.setValue(date).setBackground("green");
  }
}
</code>```

I made a few changes to yours, some are simply personal preference of what I think is more readable in the long run if you were to add more to the code (i.e. declaring the date beforehand, setting all your variables up at the start, etc.).

However, this is definitely superfluous as active sheet will return the right thing anyway:

```<code> if (s.getName() == "Sheet1")
</code>```

I also changed setFontColor() to setBackground() as it sounded like this is what you wanted from your description and thought you might not know of the function, although you can of course change it back to setFontColor() without any issues.

I also added in the time delay which you asked about, although I'm not sure why you'd need it in this context. If this isn't what you were talking about, feel free to remove these two lines and the rest of the code will still work fine:

```<code>var timeDelay = 5; // number in seconds
</code>```

and

```<code>   Utilities.sleep(timeDelay * 1000);
</code>```

Body:
The code below should work:

function onEdit(e) {

  var s = SpreadsheetApp.getActiveSheet(); // the active sheet (no need to check if the sheet == sheet1 as the active sheet will always be the one that's being edited)
  var r = e.range; // the range of the edited cell
  var c = r.getColumn(); // the column of the range
  var timeDelay = 5; // number in seconds
  var checkbox = r.getValue(); // the value of the checkbox after being edited
  var date = new Date(); // the date for the timestamp

  if (c == 5 && checkbox == true) { // if the checkbox has been checked, change the color to red
    var nextCell = r.offset(0,1);
    Utilities.sleep(timeDelay * 1000); // Utilities.sleep takes a number in milliseconds
    nextCell.setValue(date).setBackground("red");
  } else if (c == 5 && checkbox == false) { // if the checkbox has been unchecked, change the color to green
    var nextCell = r.offset(0,1);
    nextCell.setValue(date).setBackground("green");
  }
}

I made a few changes to yours, some are simply personal preference of what I think is more readable in the long run if you were to add more to the code (i.e. declaring the date beforehand, setting all your variables up at the start, etc.).

However, this is definitely superfluous as active sheet will return the right thing anyway:

 if (s.getName() == "Sheet1")

I also changed setFontColor() to setBackground() as it sounded like this is what you wanted from your description and thought you might not know of the function, although you can of course change it back to setFontColor() without any issues.

I also added in the time delay which you asked about, although I'm not sure why you'd need it in this context. If this isn't what you were talking about, feel free to remove these two lines and the rest of the code will still work fine:

var timeDelay = 5; // number in seconds

and

   Utilities.sleep(timeDelay * 1000);


问:
SyntaxError: await is only valid in async function with argon2
I'm implementing argon2 in my application for password.

```<code>try {
  if (await argon2.verify("<big long hash>", "password")) {
    // password match
  } else {
    // password did not match
  }
} catch (err) {
  // internal failure
}
</code>```

But getting an error SyntaxError: await is only valid in async function.
How can i use async funtion?

答:
You have to declare an async function with async keyword:

```<code>const myAsyncFunc = async (hashKey, password) => { //<-- declare as an async function
  try {
    if (await argon2.verify(hashKey, password)) {
      // password match
    } else {
      // password did not match
    }
  } catch (err) {
    // internal failure
  }
}

myAsyncFunc("<big long hash>", "password");
</code>```

Updated answer to make it more verbose

Body:
I'm implementing argon2 in my application for password.

try {
  if (await argon2.verify("<big long hash>", "password")) {
    // password match
  } else {
    // password did not match
  }
} catch (err) {
  // internal failure
}

But getting an error SyntaxError: await is only valid in async function.
How can i use async funtion?

Body:
You have to declare an async function with async keyword:

const myAsyncFunc = async (hashKey, password) => { //<-- declare as an async function
  try {
    if (await argon2.verify(hashKey, password)) {
      // password match
    } else {
      // password did not match
    }
  } catch (err) {
    // internal failure
  }
}

myAsyncFunc("<big long hash>", "password");

Updated answer to make it more verbose


问:
Expression tree for groupby with where clause and than select
From UI dynamic column are coming as parameter in API and based on the parameter I have to fetch data from database.
Example : In the below code, based on the column if condition linq query is being executed. Now I want to make it generic so that it serve if new column condition come in future.

```<code>public List<string> GetFilteredTypeAhead(string searchText,string searchForRole,int fiscalyear,int fiscalPeriod)
        {
 if (searchForRole == "column1")
            {
                var accounts = (from a in _context.Account
                                where a.column1.StartsWith(searchText) && a.FiscalPeriod == fiscalPeriod && a.FiscalYear ==fiscalyear
                                group a.column1 by a.column2 into g
                                select g.Key).ToList();
                return accounts;
            }
            else if(searchForRole == "column2")
            {
                var accounts = (from a in _context.Account
                                where a.column2.StartsWith(searchText) && a.FiscalPeriod == fiscalPeriod && a.FiscalYear == fiscalyear
                                group a.column2 by a.column2 into g
                                select g.Key).ToList();
                return accounts;
            }
            else if (searchForRole == "column3")
            {
                var accounts = (from a in _context.Account
                                where a.column3.StartsWith(searchText) && a.FiscalPeriod == fiscalPeriod && a.FiscalYear == fiscalyear
                                group a.column3 by a.column3 into g
                                select g.Key).ToList();
                return accounts;
            }
            else if (searchForRole == "column4")
            {
                var accounts = (from a in _context.Account
                                where a.column4.StartsWith(searchText) && a.FiscalPeriod.Equals(fiscalPeriod) && a.FiscalYear.Equals(fiscalyear)
                                group a.column4 by a.column4 into g
                                select g.Key).ToList();
                return accounts;
            }
            else
            {
                return new List<string>();
            }
        }
</code>```

To convert it to generic. I created a expression tree.

```<code>static IQueryable<T> ConvertToExpression<T>(IQueryable<T> query, string propertyValue, PropertyInfo propertyInfo, int fiscalyear, int fiscalPeriod)
        {
            ParameterExpression e = Expression.Parameter(typeof(T), "e");
            MemberExpression m = Expression.MakeMemberAccess(e, propertyInfo);
            ConstantExpression c = Expression.Constant(propertyValue, typeof(string));
            MethodInfo mi = typeof(string).GetMethod("StartsWith", new Type[] { typeof(string) });
            Expression call = Expression.Call(m, mi, c);

            PropertyInfo propertyInfoFiscalPeriod = typeof(T).GetProperty("FiscalPeriod");
            MemberExpression memberPropertyFiscalPeriod = Expression.Property(e, propertyInfoFiscalPeriod);
            ConstantExpression right = Expression.Constant(fiscalPeriod);
            Expression equalsFiscalPeriod = Expression.Equal(memberPropertyFiscalPeriod, Expression.Convert(right, typeof(Int16)));

            PropertyInfo propertyInfoFiscalYear = typeof(T).GetProperty("FiscalYear");
            MemberExpression memberPropertyFiscalYear = Expression.Property(e, propertyInfoFiscalYear);
            right = Expression.Constant(fiscalyear);
            Expression equalsFiscalYear = Expression.Equal(memberPropertyFiscalYear, Expression.Convert(right, typeof(Int16)));

            Expression combineExpression = Expression.And(equalsFiscalPeriod, equalsFiscalYear);

            Expression predicateBody = Expression.And(call, combineExpression);

            Expression<Func<T, bool>> lambda = Expression.Lambda<Func<T, bool>>(predicateBody, e);
            return query.Where(lambda);
        }

</code>```

And To call it I used code like below
"searchForRole" comes as parameter in as "column1","column2" etc

```<code>
 PropertyInfo propertyInfo = typeof(Account).GetProperty(searchForRole);

            IQueryable<Account> query = _context.Account;

            query = ConvertToExpression(query, searchText, propertyInfo,fiscalyear,fiscalPeriod);

            var list = query.ToList();

</code>```

Now this is working fine but the result having duplicate records. I wanted to have some distinct or group by on passed parameter column. In Simple words I wanted to remove if condition and make my search method generic. Please help.

答:
It's possible, but IMHO it's better to keep the dynamic parts at minimum and use the C# compile time safety as much as possible.

The sample query in question

```<code>var accounts = (from a in _context.Account
                where a.column1.StartsWith(searchText) && a.FiscalPeriod == fiscalPeriod && a.FiscalYear ==fiscalyear
                group a.column1 by a.column1 into g
                select g.Key).ToList();
</code>```

can be rewritten as follows

```<code>var accounts = _context.Account
    .Where(a => a.FiscalPeriod == fiscalPeriod && a.FiscalYear == fiscalyear)
    .Select(a => a.column1)
    .Where(c => c.StartsWith(searchText))
    .Distinct()
    .ToList();
</code>```

As you can see, the only dynamic part is a => a.column1 of type Expression<Func<Account, string>>. So all you need is a method like this:

```<code>static Expression<Func<T, M>> MemberSelector<T>(string name)
{
    var parameter = Expression.Parameter(typeof(T), "e");
    var body = Expression.PropertyOrField(name);
    return Expression.Lambda<Func<T, M>>(body, parameter);
}
</code>```

and to replace

```<code>.Select(a => a.column1)
</code>```

with

```<code>.Select(MemberSelector<Account, string>(searchForRole))
</code>```

Body:
From UI dynamic column are coming as parameter in API and based on the parameter I have to fetch data from database.
Example : In the below code, based on the column if condition linq query is being executed. Now I want to make it generic so that it serve if new column condition come in future.

public List<string> GetFilteredTypeAhead(string searchText,string searchForRole,int fiscalyear,int fiscalPeriod)
        {
 if (searchForRole == "column1")
            {
                var accounts = (from a in _context.Account
                                where a.column1.StartsWith(searchText) && a.FiscalPeriod == fiscalPeriod && a.FiscalYear ==fiscalyear
                                group a.column1 by a.column2 into g
                                select g.Key).ToList();
                return accounts;
            }
            else if(searchForRole == "column2")
            {
                var accounts = (from a in _context.Account
                                where a.column2.StartsWith(searchText) && a.FiscalPeriod == fiscalPeriod && a.FiscalYear == fiscalyear
                                group a.column2 by a.column2 into g
                                select g.Key).ToList();
                return accounts;
            }
            else if (searchForRole == "column3")
            {
                var accounts = (from a in _context.Account
                                where a.column3.StartsWith(searchText) && a.FiscalPeriod == fiscalPeriod && a.FiscalYear == fiscalyear
                                group a.column3 by a.column3 into g
                                select g.Key).ToList();
                return accounts;
            }
            else if (searchForRole == "column4")
            {
                var accounts = (from a in _context.Account
                                where a.column4.StartsWith(searchText) && a.FiscalPeriod.Equals(fiscalPeriod) && a.FiscalYear.Equals(fiscalyear)
                                group a.column4 by a.column4 into g
                                select g.Key).ToList();
                return accounts;
            }
            else
            {
                return new List<string>();
            }
        }

To convert it to generic. I created a expression tree.

static IQueryable<T> ConvertToExpression<T>(IQueryable<T> query, string propertyValue, PropertyInfo propertyInfo, int fiscalyear, int fiscalPeriod)
        {
            ParameterExpression e = Expression.Parameter(typeof(T), "e");
            MemberExpression m = Expression.MakeMemberAccess(e, propertyInfo);
            ConstantExpression c = Expression.Constant(propertyValue, typeof(string));
            MethodInfo mi = typeof(string).GetMethod("StartsWith", new Type[] { typeof(string) });
            Expression call = Expression.Call(m, mi, c);

            PropertyInfo propertyInfoFiscalPeriod = typeof(T).GetProperty("FiscalPeriod");
            MemberExpression memberPropertyFiscalPeriod = Expression.Property(e, propertyInfoFiscalPeriod);
            ConstantExpression right = Expression.Constant(fiscalPeriod);
            Expression equalsFiscalPeriod = Expression.Equal(memberPropertyFiscalPeriod, Expression.Convert(right, typeof(Int16)));

            PropertyInfo propertyInfoFiscalYear = typeof(T).GetProperty("FiscalYear");
            MemberExpression memberPropertyFiscalYear = Expression.Property(e, propertyInfoFiscalYear);
            right = Expression.Constant(fiscalyear);
            Expression equalsFiscalYear = Expression.Equal(memberPropertyFiscalYear, Expression.Convert(right, typeof(Int16)));

            Expression combineExpression = Expression.And(equalsFiscalPeriod, equalsFiscalYear);

            Expression predicateBody = Expression.And(call, combineExpression);

            Expression<Func<T, bool>> lambda = Expression.Lambda<Func<T, bool>>(predicateBody, e);
            return query.Where(lambda);
        }

And To call it I used code like below
"searchForRole" comes as parameter in as "column1","column2" etc

 PropertyInfo propertyInfo = typeof(Account).GetProperty(searchForRole);

            IQueryable<Account> query = _context.Account;

            query = ConvertToExpression(query, searchText, propertyInfo,fiscalyear,fiscalPeriod);

            var list = query.ToList();

Now this is working fine but the result having duplicate records. I wanted to have some distinct or group by on passed parameter column. In Simple words I wanted to remove if condition and make my search method generic. Please help.

Body:
It's possible, but IMHO it's better to keep the dynamic parts at minimum and use the C# compile time safety as much as possible.

The sample query in question

var accounts = (from a in _context.Account
                where a.column1.StartsWith(searchText) && a.FiscalPeriod == fiscalPeriod && a.FiscalYear ==fiscalyear
                group a.column1 by a.column1 into g
                select g.Key).ToList();

can be rewritten as follows

var accounts = _context.Account
    .Where(a => a.FiscalPeriod == fiscalPeriod && a.FiscalYear == fiscalyear)
    .Select(a => a.column1)
    .Where(c => c.StartsWith(searchText))
    .Distinct()
    .ToList();

As you can see, the only dynamic part is a => a.column1 of type Expression<Func<Account, string>>. So all you need is a method like this:

static Expression<Func<T, M>> MemberSelector<T>(string name)
{
    var parameter = Expression.Parameter(typeof(T), "e");
    var body = Expression.PropertyOrField(name);
    return Expression.Lambda<Func<T, M>>(body, parameter);
}

and to replace

.Select(a => a.column1)

with

.Select(MemberSelector<Account, string>(searchForRole))


问:
How to Programatically open NgbPopOver from code without actually clicking on a button
Requirement is to show an information message as to why save button is disabled. For the save button to enabled, some mandatory filters have to be chosen. So for the user to be aware of it, im trying to display a popover on the disabled button which shows the necessary information. I would want to display the popover to display on top of the button as soon as it is disabled. As of now my present code tries to achieve most of the requirement, except that i have to physically hover or click on the button to display the popup. I want to show the popup as soon as the button is disabled due to some logic in the code behind.

```<code><button id="btnCancel" title="Cancel" aria-label="Cancel Filter dialog" class="btn btn-cancel"
            style="margin-right: 5px;" (click)="close();" (keydown)="trapFocus('cancel',$event)">CANCEL</button>
          <button id="btnApply" title="Apply" class="btn btn-primary"
          [disabled]="!(checkIfAnyFiltersAreSelected() && checkIfMandatoryFiltersAreSelected())"
          (click)="onApply()" (keydown)="trapFocus('apply',$event)">
            <span triggers="hover" *ngIf="!checkIfMandatoryFiltersAreSelected(); else elseTemplate" [ngbPopover]="popContent"
              popoverTitle="Mandatory Filters">
              APPLY
            </span>
            <ng-template #elseTemplate>
              APPLY
            </ng-template>
          </button>
          <ng-template #popContent>Necessary Information to be shown here</ng-template>
</code>```

Tried to follow the solution in this question, but the answer is not clear and is not solving the issue

ngbPopover will not close and will open on load

答:
You can accomplish this by defining a manual trigger for the popover and passing the popover into the function that determines whether the button is disabled, so that if the button is disabled the popover can be opened programatically.

HTML Template

If you define the button as follows:

```<code><button type="button" class="btn btn-outline-secondary mr-2"
    placement="top" ngbPopover="Displayed when button is disabled"
    triggers="manual" #p="ngbPopover" [disabled]="isDisabled(p)">
      Apply
</button>
</code>```

triggers="manual" means it won't be triggered automatically by hovering over the button

#p="ngbPopover" is the reference to the NgbPopover object

[disabled]="isDisabled(p)" is a function that returns a boolean indicating whether the button should be disabled or not. Passing in p (the NgbPopover) allows it to be opened programatically in the isDisabled function.

TypeScript

The isDisabled function looks like this:

```<code>isDisabled(popover) {
  if (this.disabled) {
    popover.open();
  }
  return this.disabled;
}
</code>```

This checks the value of the disabled property (this is just a boolean I've defined in the TypeScript file), and will open the popover if it is true. It then returns the value so that the HTML template can enable/disable the button accordingly.

Please see this StackBlitz for a demo. If you toggle the checkbox (which is bound to the disabled TypeScript property, you will see that the popover is displayed when the button is disabled.

Body:
Requirement is to show an information message as to why save button is disabled. For the save button to enabled, some mandatory filters have to be chosen. So for the user to be aware of it, im trying to display a popover on the disabled button which shows the necessary information. I would want to display the popover to display on top of the button as soon as it is disabled. As of now my present code tries to achieve most of the requirement, except that i have to physically hover or click on the button to display the popup. I want to show the popup as soon as the button is disabled due to some logic in the code behind.

<button id="btnCancel" title="Cancel" aria-label="Cancel Filter dialog" class="btn btn-cancel"
            style="margin-right: 5px;" (click)="close();" (keydown)="trapFocus('cancel',$event)">CANCEL</button>
          <button id="btnApply" title="Apply" class="btn btn-primary"
          [disabled]="!(checkIfAnyFiltersAreSelected() && checkIfMandatoryFiltersAreSelected())"
          (click)="onApply()" (keydown)="trapFocus('apply',$event)">

              APPLY

            <ng-template #elseTemplate>
              APPLY
            </ng-template>
          </button>
          <ng-template #popContent>Necessary Information to be shown here</ng-template>

Tried to follow the solution in this question, but the answer is not clear and is not solving the issue

ngbPopover will not close and will open on load

Body:
You can accomplish this by defining a manual trigger for the popover and passing the popover into the function that determines whether the button is disabled, so that if the button is disabled the popover can be opened programatically.

HTML Template

If you define the button as follows:

<button type="button" class="btn btn-outline-secondary mr-2"
    placement="top" ngbPopover="Displayed when button is disabled"
    triggers="manual" #p="ngbPopover" [disabled]="isDisabled(p)">
      Apply
</button>

triggers="manual" means it won't be triggered automatically by hovering over the button

#p="ngbPopover" is the reference to the NgbPopover object

[disabled]="isDisabled(p)" is a function that returns a boolean indicating whether the button should be disabled or not. Passing in p (the NgbPopover) allows it to be opened programatically in the isDisabled function.

TypeScript

The isDisabled function looks like this:

isDisabled(popover) {
  if (this.disabled) {
    popover.open();
  }
  return this.disabled;
}

This checks the value of the disabled property (this is just a boolean I've defined in the TypeScript file), and will open the popover if it is true. It then returns the value so that the HTML template can enable/disable the button accordingly.

Please see this StackBlitz for a demo. If you toggle the checkbox (which is bound to the disabled TypeScript property, you will see that the popover is displayed when the button is disabled.


问:
Modify a svg file using jQuery
I have a svg file with some shape and some text. I'd like to modify the svg at runtime, so that some shape can change color, and some text can change its content.

Let's suppose that I have only two elements in an external svg file:

circle1: a blue filled circle witdh that id

text1: a text containing "--" with that id

Now I can view the file in my html with

```<code><object data="Sample.svg" type="image/svg+xml" width="200" height="200" id="svg1"></object>
</code>```

From a button near the image, using jQuery, I can catch the onClick event: I'd like to fill the cicle with red and change the text to "hello word".

How can I do that? Is there a jQuery based solution?

I have found the jquery.svg plugin, but it seem that you can only modify a runtime created document.

Thanks.

答:
Well, there's a FANTASTIC library that you can use with jQuery or any other javascript:

Raphael JS: http://raphaeljs.com/

Check out the samples, you can do just about anything.

Title: Modify a svg file using jQuery

Body:
I have a svg file with some shape and some text. I'd like to modify the svg at runtime, so that some shape can change color, and some text can change its content.

Let's suppose that I have only two elements in an external svg file:

circle1: a blue filled circle witdh that id

text1: a text containing "--" with that id

Now I can view the file in my html with

<object data="Sample.svg" type="image/svg+xml" width="200" height="200" id="svg1"></object>

From a button near the image, using jQuery, I can catch the onClick event: I'd like to fill the cicle with red and change the text to "hello word".

How can I do that? Is there a jQuery based solution?

I have found the jquery.svg plugin, but it seem that you can only modify a runtime created document.

Thanks.