问:
Uncaught TypeError: Cannot read properties of null (reading 'style')
I, trying to make a div clickable so it will be redirected to a different document or site but got that error.
However, it works with the old way of using the onclick as an attribute inside the element.

```<code>var examscol = document.getElementById("exam-col1");
function examCol() {
  return window.location.assign("https://www.w3schools.com")
}

examscol.addEventListener("click", examCol);

</code>```

Any suggestions on why it isn't working with this way ?

答:
1. Problem

The problem is that the id of the  element is not exam-col1. When I change the id of the  element to exam-col I get the following error [1]:

```<code>Error
{
  "message": "Uncaught TypeError: Cannot read properties of null (reading 'addEventListener')",
}
</code>```

2. Hint

The frame cannot be displayed when the URL's X-Frame-Options field is set to SAMEORIGIN. The X-Frame-Options HTTP response header can be used to indicate whether or not a browser should be allowed to render a page in a <frame>, , <embed> or <object> [2]. That's why I changed the targeted URL.

/* If there is no item with an id of "exam-col1" on the page, you will get a "null" error. */
var examscol = document.getElementById("exam-col1");

function examCol() {
 return window.location.assign("https://www.wikipedia.com")
}

examscol.addEventListener("click", examCol);```
<pre class="snippet-code-css lang-css prettyprint-override"><code>.clickable {
  display: inline;
  cursor: pointer;
  padding: 5px;
  border: 1px solid red;
}</code>```

Open
```

1 - JavaScript TypeError: Cannot read property 'style' of null

2 - X-Frame-Options

Body:
I, trying to make a div clickable so it will be redirected to a different document or site but got that error.
However, it works with the old way of using the onclick as an attribute inside the element.

var examscol = document.getElementById("exam-col1");
function examCol() {
  return window.location.assign("https://www.w3schools.com")
}

examscol.addEventListener("click", examCol);

Any suggestions on why it isn't working with this way ?

Body:
1. Problem

The problem is that the id of the  element is not exam-col1. When I change the id of the  element to exam-col I get the following error [1]:

Error
{
  "message": "Uncaught TypeError: Cannot read properties of null (reading 'addEventListener')",
}

2. Hint

The frame cannot be displayed when the URL's X-Frame-Options field is set to SAMEORIGIN. The X-Frame-Options HTTP response header can be used to indicate whether or not a browser should be allowed to render a page in a <frame>, <iframe>, <embed> or <object> [2]. That's why I changed the targeted URL.

/* If there is no item with an id of "exam-col1" on the page, you will get a "null" error. */
var examscol = document.getElementById("exam-col1");

function examCol() {
 return window.location.assign("https://www.wikipedia.com")
}

examscol.addEventListener("click", examCol);

.clickable {
  display: inline;
  cursor: pointer;
  padding: 5px;
  border: 1px solid red;
}

<!-- Note that the id of the item is "exam-col1". -->
<div id="exam-col1" class="clickable">Open</div>

1 - JavaScript TypeError: Cannot read property 'style' of null

2 - X-Frame-Options


来源: stackexchange

问:
Overlay element at top-left corner of centered image
I have an image which is currently centered on the screen using flexbox:

```<code>.center-flex {
    display: flex;
    justify-content: center;
}

<div class="center-flex">
    <img id="revealImage">
</div>
</code>```

I am attempting to dynamically create a div that needs to be placed at the upper-left hand corner.  I have tried the following to get the computed left on the image but it does not work as it returns auto due to the flex layout.

```<code>const revealImage = document.getElementById('revealImage');

const left = window.getComputedStyle(revealImage,null).getPropertyValue('left');

let square = document.createElement('div');
square.style.height = '100px';
square.style.width = '100px';
square.style.zIndex = '2';
square.style.position = 'absolute';
square.style.backgroundColor = 'red';
square.style.top = 0;
square.style.left = left;

console.log('left: ' + left);
</code>```

This results in a properly overlayed red box but it is centered and not set left.

答:
I would suggest a different approach in the html, by using the picture element in order to wrap the red square.

For example,

html:

```<code><div class="center-flex">
    <picture>
        <img id="revealImage">
    </picture>
</div>
</code>```

css:

```<code>picture {
    position: relative;
}
</code>```

js:

```<code>const picture = document.querySelector('picture');

const square = document.createElement('div');

square.style.height = '100px';
square.style.width = '100px';
square.style.zIndex = '2';
square.style.position = 'absolute';
square.style.backgroundColor = 'red';
square.style.top = 0;
picture.appendChild(square)
</code>```

https://jsfiddle.net/kongallis/ju16rdfL/9/

ContentLicense: CC BY-SA 4.0

Body:
I have an image which is currently centered on the screen using flexbox:

.center-flex {
    display: flex;
    justify-content: center;
}

I am attempting to dynamically create a div that needs to be placed at the upper-left hand corner.  I have tried the following to get the computed left on the image but it does not work as it returns auto due to the flex layout.

const revealImage = document.getElementById('revealImage');

const left = window.getComputedStyle(revealImage,null).getPropertyValue('left');

let square = document.createElement('div');
square.style.height = '100px';
square.style.width = '100px';
square.style.zIndex = '2';
square.style.position = 'absolute';
square.style.backgroundColor = 'red';
square.style.top = 0;
square.style.left = left;

console.log('left: ' + left);

This results in a properly overlayed red box but it is centered and not set left.

Body:
I would suggest a different approach in the html, by using the picture element in order to wrap the red square.

For example,

html:

<div class="center-flex">
    <picture>
        <img id="revealImage">
    </picture>
</div>

css:

picture {
    position: relative;
}

js:

const picture = document.querySelector('picture');

const square = document.createElement('div');

square.style.height = '100px';
square.style.width = '100px';
square.style.zIndex = '2';
square.style.position = 'absolute';
square.style.backgroundColor = 'red';
square.style.top = 0;
picture.appendChild(square)

https://jsfiddle.net/kongallis/ju16rdfL/9/


问:
White to Transparent Layer in matplotlib figure (SVG)
I would like to add a layer with a gradient (from white to transparent) on top of my matplotlib image and be able to save the result as an SVG eventually (I have some more shapes on my actual image than sketched below).

It is unclear to me, if this is possible with matplotlib + svg. Does anybody know or has a solution for this?

Here is some example code:

```<code>plt.figure(figsize=[6, 6])
x = np.arange(0, 100, 0.00001)
y = np.sin(0.1* np.pi * x)
plt.plot(y)
plt.axis('off')
plt.gca().set_position([0, 0, 1, 1])
# TODO: Add white -> transparent layer
plt.savefig("temp.svg", bbox_inches=0)
</code>```

The result should look like this:

Before:

After:

答:
To achieve transition effect, You can plot one layer on top of Your existing figure with bicubic interpolation and custom color map.

First You have to create colormap having just two colors.

White color with alpha channel = 0 and other white with alpha channel = 1.

Then we add another figure filled with new color map from top to the bottom.

Here is code that does it:

```<code>import matplotlib.colors as mcolors
import matplotlib.pyplot as plt
import numpy as np

fig = plt.figure(figsize=[6, 6])
x = np.arange(0, 100, 0.00001)
y = np.sin(0.1 * np.pi * x)
plt.plot(y)
plt.axis('off')
plt.gca().set_position([0, 0, 1, 1])

# Add new subplot on top of what is there already
ax = fig.add_subplot()
ax.axis('off')
ax.set_position([0, 0, 1, 1])

# Create colormap of two white colors, one with alpha=0 and other one with alpha=1
colors = [(1, 1, 1, 0), (1, 1, 1, 1)]
# Create new colormap from our two colors
cmap = mcolors.LinearSegmentedColormap.from_list('mycmap', colors)
# Use imshow with bicubic interpolation to create transition from top to bottom
ax.imshow([[0., 0.], [1., 1.]],
          cmap=cmap, interpolation='bicubic', aspect='auto'
          )
# Save as .svg file
plt.savefig("temp.svg", bbox_inches=0)
</code>```

Body:
I would like to add a layer with a gradient (from white to transparent) on top of my matplotlib image and be able to save the result as an SVG eventually (I have some more shapes on my actual image than sketched below).

It is unclear to me, if this is possible with matplotlib + svg. Does anybody know or has a solution for this?

Here is some example code:

plt.figure(figsize=[6, 6])
x = np.arange(0, 100, 0.00001)
y = np.sin(0.1* np.pi * x)
plt.plot(y)
plt.axis('off')
plt.gca().set_position([0, 0, 1, 1])
# TODO: Add white -> transparent layer
plt.savefig("temp.svg", bbox_inches=0)

The result should look like this:

Before:

After:

Body:
To achieve transition effect, You can plot one layer on top of Your existing figure with bicubic interpolation and custom color map.

First You have to create colormap having just two colors.

White color with alpha channel = 0 and other white with alpha channel = 1.

Then we add another figure filled with new color map from top to the bottom.

Here is code that does it:

import matplotlib.colors as mcolors
import matplotlib.pyplot as plt
import numpy as np

fig = plt.figure(figsize=[6, 6])
x = np.arange(0, 100, 0.00001)
y = np.sin(0.1 * np.pi * x)
plt.plot(y)
plt.axis('off')
plt.gca().set_position([0, 0, 1, 1])

# Add new subplot on top of what is there already
ax = fig.add_subplot()
ax.axis('off')
ax.set_position([0, 0, 1, 1])

# Create colormap of two white colors, one with alpha=0 and other one with alpha=1
colors = [(1, 1, 1, 0), (1, 1, 1, 1)]
# Create new colormap from our two colors
cmap = mcolors.LinearSegmentedColormap.from_list('mycmap', colors)
# Use imshow with bicubic interpolation to create transition from top to bottom
ax.imshow([[0., 0.], [1., 1.]],
          cmap=cmap, interpolation='bicubic', aspect='auto'
          )
# Save as .svg file
plt.savefig("temp.svg", bbox_inches=0)


问:
GitHub Actions get from API to create pull request
Is there a way to tell GitHub to automatically create a pull request from an API providing JSON content and merge it into my project?

I want to:

Edit files on a platform (I control the platform) using my own production editors/tools.

Have GitHub request it (REST), then create a PR or a commit, so people can collaborate on it with forks/GitHub project management.

Push from GitHub back to the platform for publishing.

3 is no problem, but 2 I can't find documentation for if it's even possible.

答:
```<code>name: Manual workflow
on:
  workflow_dispatch:
jobs:
  makefiles:
    # The type of runner that the job will run on
    runs-on: ubuntu-latest

    # Steps represent a sequence of tasks that will be executed as part of the job
    steps:
    - uses: actions/checkout@v2
    - name: Getting
      uses: fjogeleit/http-request-action@master
      id: myRequest
      with:
        url: 'https://domain/api/file'
        method: 'GET'
    - name: Show File
      run: echo ${{ steps.myRequest.outputs.response }}
    - name: Create A File
      uses: 1arp/create-a-file-action@0.2
      with:
        path: 'src'
        file: 'foo.bar'
        content: ${{steps.myRequest.outputs.response}}
    - name: final commit
      uses: zwaldowski/git-commit-action@v1
      id: git_commit
    - name: show
      run: echo "${{ steps.git_commit.outputs.sha }}"
</code>```


问:
How do I deploy the AWS EFS CSI Driver Helm chart from https://kubernetes-sigs.github.io/aws-efs-csi-driver/ using Pulimi
I would like to be able to deploy the AWS EFS CSI Driver Helm chart hosted at AWS EFS SIG Repo using Pulumi. With Source from AWS EFS CSI Driver Github Source.  I would like to avoid having almost everything managed with Pulumi except this one part of my infrastructure.

Below is the TypeScript class I created to manage interacting with the k8s.helm.v3.Release class:

import * as k8s from '@pulumi/kubernetes';
import * as eks from '@pulumi/eks';

export default class AwsEfsCsiDriverHelmRepo extends k8s.helm.v3.Release {
  constructor(cluster: eks.Cluster) {
    super(`aws-efs-csi-driver`, {
      chart: `aws-efs-csi-driver`,
      version: `1.3.6`,
      repositoryOpts: {
        repo: `https://kubernetes-sigs.github.io/aws-efs-csi-driver/`,
      },
      namespace: `kube-system`,
    }, { provider: cluster.provider });
  }
}
```
<p>I've tried several variations on the above code, chopping of the <code>-driver</code> in the name, removing <code>aws-cfs-csi-driver</code> from the <code>repo</code> property, changing to <code>latest</code> for the version.</p>
<p>When I do a <code>pulumi up</code> I get: <code>failed to pull chart: chart "aws-efs-csi-driver" version "1.3.6" not found in https://kubernetes-sigs.github.io/aws-efs-csi-driver/ repository</code></p>
<pre class="lang-sh prettyprint-override"><code>$ helm version
version.BuildInfo{Version:"v3.7.0", GitCommit:"eeac83883cb4014fe60267ec6373570374ce770b", GitTreeState:"clean", GoVersion:"go1.16.8"}
</code>```

$ pulumi version
v3.24.1
```

答:
You're using the wrong version in your chart invocation.

The version you're selecting is the application version, ie the release version of the underlying application. You need to set the Chart version, see here which is defined here

the following works:

const csiDrive = new kubernetes.helm.v3.Release("csi", {
  chart: `aws-efs-csi-driver`,
  version: `2.2.3`,
  repositoryOpts: {
    repo: `https://kubernetes-sigs.github.io/aws-efs-csi-driver/`,
  },
  namespace: `kube-system`,
});
```
<p>If you want to use the existing code you have, try this:</p>
<pre class="lang-js prettyprint-override"><code>import * as k8s from '@pulumi/kubernetes';
import * as eks from '@pulumi/eks';

export default class AwsEfsCsiDriverHelmRepo extends k8s.helm.v3.Release {
  constructor(cluster: eks.Cluster) {
    super(`aws-efs-csi-driver`, {
      chart: `aws-efs-csi-driver`,
      version: `2.2.3`,
      repositoryOpts: {
        repo: `https://kubernetes-sigs.github.io/aws-efs-csi-driver/`,
      },
      namespace: `kube-system`,
    }, { provider: cluster.provider });
  }
}
</code>```

Body:
I would like to be able to deploy the AWS EFS CSI Driver Helm chart hosted at AWS EFS SIG Repo using Pulumi. With Source from AWS EFS CSI Driver Github Source.  I would like to avoid having almost everything managed with Pulumi except this one part of my infrastructure.

Below is the TypeScript class I created to manage interacting with the k8s.helm.v3.Release class:

import * as k8s from '@pulumi/kubernetes';
import * as eks from '@pulumi/eks';

export default class AwsEfsCsiDriverHelmRepo extends k8s.helm.v3.Release {
  constructor(cluster: eks.Cluster) {
    super(`aws-efs-csi-driver`, {
      chart: `aws-efs-csi-driver`,
      version: `1.3.6`,
      repositoryOpts: {
        repo: `https://kubernetes-sigs.github.io/aws-efs-csi-driver/`,
      },
      namespace: `kube-system`,
    }, { provider: cluster.provider });
  }
}

I've tried several variations on the above code, chopping of the -driver in the name, removing aws-cfs-csi-driver from the repo property, changing to latest for the version.

When I do a pulumi up I get: failed to pull chart: chart "aws-efs-csi-driver" version "1.3.6" not found in https://kubernetes-sigs.github.io/aws-efs-csi-driver/ repository

$ helm version
version.BuildInfo{Version:"v3.7.0", GitCommit:"eeac83883cb4014fe60267ec6373570374ce770b", GitTreeState:"clean", GoVersion:"go1.16.8"}

$ pulumi version
v3.24.1

Body:
You're using the wrong version in your chart invocation.

The version you're selecting is the application version, ie the release version of the underlying application. You need to set the Chart version, see here which is defined here

the following works:

const csiDrive = new kubernetes.helm.v3.Release("csi", {
  chart: `aws-efs-csi-driver`,
  version: `2.2.3`,
  repositoryOpts: {
    repo: `https://kubernetes-sigs.github.io/aws-efs-csi-driver/`,
  },
  namespace: `kube-system`,
});

If you want to use the existing code you have, try this:

import * as k8s from '@pulumi/kubernetes';
import * as eks from '@pulumi/eks';

export default class AwsEfsCsiDriverHelmRepo extends k8s.helm.v3.Release {
  constructor(cluster: eks.Cluster) {
    super(`aws-efs-csi-driver`, {
      chart: `aws-efs-csi-driver`,
      version: `2.2.3`,
      repositoryOpts: {
        repo: `https://kubernetes-sigs.github.io/aws-efs-csi-driver/`,
      },
      namespace: `kube-system`,
    }, { provider: cluster.provider });
  }
}


问:
Altair mark_text position based on condition

I have this chart with mark_text to denote the value of each bar. There is a slider to go back/forth in time.
I would like to change the positioning of the text (the numbers in the bars) depending on the Y value: if it is larger than a certain value, it will go just below the top of the bar (baseline='line-top), otherwise just above (baseline='line-bottom').
This way, as I slide through time the text will appear below/above the top of the bar depending on Y.

I think I have to use some condition or expression, but I cannot figure out how.

```<code>import numpy as np
import pandas as pd
import altair as alt

np.random.seed(0)

################################################################################

model_keys = ['M1', 'M2']
scene_keys = ['S1', 'S2']
layer_keys = ['L1', 'L2']
time_keys = [1, 2, 3]

ys = []
models = []
dataset = []
layers = []
scenes = []
times = []

for sc in scene_keys:
    for m in model_keys:
        for l in layer_keys:
            for s in range(10):
                y = np.random.rand(10) / 10
                if m == 'M1':
                    y *= 10
                if l == 'L1':
                    y *= 5
                for t in time_keys:
                    y += 1

                    ys += list(y)
                    scenes += [sc] * len(y)
                    models += [m] * len(y)
                    layers += [l] * len(y)
                    times += [t] * len(y)

# ------------------------------------------------------------------------------

df = pd.DataFrame({'Y': ys,
                   'Model': models,
                   'Layer': layers,
                   'Scenes': scenes,
                   'Time': times})

bars = alt.Chart(df, width=100, height=90).mark_bar().encode(
    x=alt.X('Scenes:N',
        title=None,
        axis=alt.Axis(
            grid=False,
            title=None,
            labels=False,
        ),
    ),
    y=alt.Y('Y:Q',
        aggregate='mean',
        axis=alt.Axis(
            grid=True,
            title='Y',
            titleFontWeight='normal',
        ),
    ),
)

text = alt.Chart(df).mark_text(align='center',
    baseline='line-top',
    color='black',
    dy=5,
    fontSize=13,
).encode(
    x=alt.X('Scenes:N'),
    y=alt.Y('mean(Y):Q'),
    text=alt.Text('mean(Y):Q',
        format='.1f'
    ),
)

bars = bars + text

bars = bars.facet(
    row=alt.Row('Model:N',
        title=None,
    ),
    column=alt.Column('Layer:N',
        title=None,
    ),
    spacing={"row": 10, "column": 10},
)

slider = alt.binding_range(
    min=1,
    max=3,
    step=1,
    name='Time',
)
selector = alt.selection_single(
    name='Selector',
    fields=['Time'],
    bind=slider,
    init={'Time': 3},
)
bars = bars.add_selection(
    selector
).transform_filter(
    selector
)

bars.save('test.html')
</code>```

答:
Unfortunately, you can only use conditions with encodings, not (yet) with  mark properties, so there is no way to dynamically change the text baseline. However, you could add a second text mark that is above the bars and then set the opacity encoding of both text marks to depend on the value of y, so that it is either the text above or below the bar that is visible.

I believe you need to do the calculation of the average y value in a separate transform, so that you can access the column name in the conditional expression. I also believe that the charts need to build on each other to filter correctly when the Time value changes, but I am not 100% on either of these two points.

Taking the above into consideration, something like this would work:

```<code>bars = alt.Chart(df, width=100, height=90).mark_bar().transform_aggregate(
    y_mean = 'mean(Y)',
    groupby=['Scenes']
).encode(
    x=alt.X(
        'Scenes:N',
        title=None,
        axis=alt.Axis(
            grid=False,
            title=None,
            labels=False,
        ),
    ),
    y=alt.Y(
        'y_mean:Q',
        axis=alt.Axis(
            grid=True,
            title='Y',
            titleFontWeight='normal',
        ),
    ),
)

text = bars.mark_text(
    align='center',
    baseline='line-top',
    color='black',
    dy=5,
    fontSize=13,
).encode(
    text=alt.Text( 'y_mean:Q', format='.1f'),
    opacity=alt.condition( 'datum.y_mean < 3', alt.value(1), alt.value(0))
)

text2 = text.mark_text(
    align='center',
    baseline='line-bottom',
    fontSize=13,
).encode(
    opacity=alt.condition( 'datum.y_mean >= 3', alt.value(1), alt.value(0))
)

bars = bars + text + text2

bars = bars.facet(
    row=alt.Row('Model:N', title=None),
    column=alt.Column('Layer:N', title=None),
    spacing={"row": 10, "column": 10},
)

slider = alt.binding_range(
    min=1,
    max=3,
    step=1,
    name='Time',
)
selector = alt.selection_single(
    name='Selector',
    fields=['Time'],
    bind=slider,
    init={'Time': 2},
)
bars = bars.add_selection(
    selector
).transform_filter(
    selector
)
bars
</code>```

Body:
I have this chart with mark_text to denote the value of each bar. There is a slider to go back/forth in time.
I would like to change the positioning of the text (the numbers in the bars) depending on the Y value: if it is larger than a certain value, it will go just below the top of the bar (baseline='line-top), otherwise just above (baseline='line-bottom').
This way, as I slide through time the text will appear below/above the top of the bar depending on Y.

I think I have to use some condition or expression, but I cannot figure out how.

import numpy as np
import pandas as pd
import altair as alt

np.random.seed(0)

################################################################################

model_keys = ['M1', 'M2']
scene_keys = ['S1', 'S2']
layer_keys = ['L1', 'L2']
time_keys = [1, 2, 3]

ys = []
models = []
dataset = []
layers = []
scenes = []
times = []

for sc in scene_keys:
    for m in model_keys:
        for l in layer_keys:
            for s in range(10):
                y = np.random.rand(10) / 10
                if m == 'M1':
                    y *= 10
                if l == 'L1':
                    y *= 5
                for t in time_keys:
                    y += 1

                    ys += list(y)
                    scenes += [sc] * len(y)
                    models += [m] * len(y)
                    layers += [l] * len(y)
                    times += [t] * len(y)

# ------------------------------------------------------------------------------

df = pd.DataFrame({'Y': ys,
                   'Model': models,
                   'Layer': layers,
                   'Scenes': scenes,
                   'Time': times})

bars = alt.Chart(df, width=100, height=90).mark_bar().encode(
    x=alt.X('Scenes:N',
        title=None,
        axis=alt.Axis(
            grid=False,
            title=None,
            labels=False,
        ),
    ),
    y=alt.Y('Y:Q',
        aggregate='mean',
        axis=alt.Axis(
            grid=True,
            title='Y',
            titleFontWeight='normal',
        ),
    ),
)

text = alt.Chart(df).mark_text(align='center',
    baseline='line-top',
    color='black',
    dy=5,
    fontSize=13,
).encode(
    x=alt.X('Scenes:N'),
    y=alt.Y('mean(Y):Q'),
    text=alt.Text('mean(Y):Q',
        format='.1f'
    ),
)

bars = bars + text

bars = bars.facet(
    row=alt.Row('Model:N',
        title=None,
    ),
    column=alt.Column('Layer:N',
        title=None,
    ),
    spacing={"row": 10, "column": 10},
)

slider = alt.binding_range(
    min=1,
    max=3,
    step=1,
    name='Time',
)
selector = alt.selection_single(
    name='Selector',
    fields=['Time'],
    bind=slider,
    init={'Time': 3},
)
bars = bars.add_selection(
    selector
).transform_filter(
    selector
)

bars.save('test.html')

Body:
Unfortunately, you can only use conditions with encodings, not (yet) with  mark properties, so there is no way to dynamically change the text baseline. However, you could add a second text mark that is above the bars and then set the opacity encoding of both text marks to depend on the value of y, so that it is either the text above or below the bar that is visible.

I believe you need to do the calculation of the average y value in a separate transform, so that you can access the column name in the conditional expression. I also believe that the charts need to build on each other to filter correctly when the Time value changes, but I am not 100% on either of these two points.

Taking the above into consideration, something like this would work:

bars = alt.Chart(df, width=100, height=90).mark_bar().transform_aggregate(
    y_mean = 'mean(Y)',
    groupby=['Scenes']
).encode(
    x=alt.X(
        'Scenes:N',
        title=None,
        axis=alt.Axis(
            grid=False,
            title=None,
            labels=False,
        ),
    ),
    y=alt.Y(
        'y_mean:Q',
        axis=alt.Axis(
            grid=True,
            title='Y',
            titleFontWeight='normal',
        ),
    ),
)

text = bars.mark_text(
    align='center',
    baseline='line-top',
    color='black',
    dy=5,
    fontSize=13,
).encode(
    text=alt.Text( 'y_mean:Q', format='.1f'),
    opacity=alt.condition( 'datum.y_mean < 3', alt.value(1), alt.value(0))
)

text2 = text.mark_text(
    align='center',
    baseline='line-bottom',
    fontSize=13,
).encode(
    opacity=alt.condition( 'datum.y_mean >= 3', alt.value(1), alt.value(0))
)

bars = bars + text + text2

bars = bars.facet(
    row=alt.Row('Model:N', title=None),
    column=alt.Column('Layer:N', title=None),
    spacing={"row": 10, "column": 10},
)

slider = alt.binding_range(
    min=1,
    max=3,
    step=1,
    name='Time',
)
selector = alt.selection_single(
    name='Selector',
    fields=['Time'],
    bind=slider,
    init={'Time': 2},
)
bars = bars.add_selection(
    selector
).transform_filter(
    selector
)
bars


问:
What is wrong with this sorting of dictionary?
I am trying to sort the dictionary here:

```<code>car =   {
  "brand": ["Ford","Honda","Toyota","Tesla","Ford"],
  "model": ["Mustang","CRV","RAV4","X","Transit"],
  "year": [1964,2010,2015,2022,1964],
  "color": ["Red","Yellow","Green","Blue","Black"]
}

sortedbyval1={k: v for k, v in sorted(car.items(),key=lambda v:v[1])}
</code>```

I keep getting error message like below. There is no < in the code!!!

```<code>TypeError: '<' not supported between instances of 'int' and 'str'
</code>```

I am trying to sort the car dictionary by model, year, color etc.

If possible, by color AND year.

答:
This is not directly what you asked for but since you are learning python, one might mention the clean and simple way of using classes and object oriented programming in this case:

class car():

    def __init__(self, brand, model, year, color):
        self.brand = brand
        self.model = model
        self.year = year
        self.color = color

cars = [car("Ford", "Mustang", 1964, "Red"),
        car("Honda", "CRV", 2010, "Yellow"),
        car("Toyota", "RAV4", 2015, "Green"),
        car("Tesla", "X", 2022, "Blue"),
        car("Ford", "Transit", 1964, "Black")]

cars.sort(key=lambda c: c.year)

for c in cars:
    print(c.year, c.model, c.brand)
```

Body:
I am trying to sort the dictionary here:

car =   {
  "brand": ["Ford","Honda","Toyota","Tesla","Ford"],
  "model": ["Mustang","CRV","RAV4","X","Transit"],
  "year": [1964,2010,2015,2022,1964],
  "color": ["Red","Yellow","Green","Blue","Black"]
}

sortedbyval1={k: v for k, v in sorted(car.items(),key=lambda v:v[1])}

I keep getting error message like below. There is no < in the code!!!

TypeError: '<' not supported between instances of 'int' and 'str'

I am trying to sort the car dictionary by model, year, color etc.

If possible, by color AND year.


问:
Group rows based on contiguous column data
I have a dataset table in PowerBi with this structure:

It's pretty straight forward; the column "Duration (s)" is the difference in seconds between "DateTime End" and "DateTime Start.

I need to create a visualization (a table/matrix) which would give me this result:

Basically it's a sort of group by of columns "Product" and "Machine" based on contiguous values of the column "Event Code" where i keep the first row "DateTime Start" and the last row "DateTime End", sum the rows "Duration (s)" values (or calculate it ex-novo, since it's always a time diff) and count the contiguous rows with the same "Event Code" in the column "Rows Count".

Since the dataset is fairly large (5m+ rows) i'd prefer a solution based on Dax rather than an M-based one, but any will suffice.

答:
With M code, starting with your initial table, where I presume you've added a custom column for Duration (s):

Group by the Product, Machine and Event code columns

Add your various aggregations for

min start

max end

sum duration

row count

Then, open the Advanced Editor and add the optional final argument for the Table.Group function:  GroupKind.Local  This is what that argument is for

```<code>let

//orginal table
    Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("hZLBCsMgDIZfZeRcqInald1s77t0t+Jp9AXKxl5/rqcm0QVR+CAfJr+uKyzPfftABw8sRyqb+rIc0WW4oRMcIXeGEjmT08qkSjijraDgYCuBs680llQJZ6+VWZUwDuIW0oqT41eUZCQWbUW+y2gro5iNDuX+fv0EryNufJc/gmgKr1KYVUEtq7bQSOokWDkNkPMX", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type nullable text) meta [Serialized.Text = true]) in type table [Product = _t, Machine = _t, #"Event Code" = _t, #"DateTime Start" = _t, #"DateTime End" = _t]),
    #"Changed Type" = Table.TransformColumnTypes(Source,{
        {"Product", type text}, {"Machine", type text}, {"Event Code", type text},
        {"DateTime Start", type datetime}, {"DateTime End", type datetime}}),
    #"Added Custom" = Table.AddColumn(#"Changed Type", "Duration (s)", each Duration.TotalSeconds([DateTime End]-[DateTime Start])),

//added code to group by contiguous event code groups
    #"Grouped Rows" = Table.Group(#"Added Custom", {"Product", "Machine", "Event Code"}, {
        {"DateTime Start", each List.Min([DateTime Start]), type nullable datetime},
        {"DateTime End", each List.Max([DateTime End]), type nullable datetime},
        {"Duration (s)", each List.Sum([#"Duration (s)"]), type number},
        {"Rows Count", each Table.RowCount(_), Int64.Type}},
        GroupKind.Local)
    //    ^^^^^
in
    #"Grouped Rows"
</code>```

Body:
With M code, starting with your initial table, where I presume you've added a custom column for Duration (s):

Group by the Product, Machine and Event code columns

Add your various aggregations for

min start

max end

sum duration

row count

Then, open the Advanced Editor and add the optional final argument for the Table.Group function:  GroupKind.Local  This is what that argument is for

let

//orginal table
    Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("hZLBCsMgDIZfZeRcqInald1s77t0t+Jp9AXKxl5/rqcm0QVR+CAfJr+uKyzPfftABw8sRyqb+rIc0WW4oRMcIXeGEjmT08qkSjijraDgYCuBs680llQJZ6+VWZUwDuIW0oqT41eUZCQWbUW+y2gro5iNDuX+fv0EryNufJc/gmgKr1KYVUEtq7bQSOokWDkNkPMX", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type nullable text) meta [Serialized.Text = true]) in type table [Product = _t, Machine = _t, #"Event Code" = _t, #"DateTime Start" = _t, #"DateTime End" = _t]),
    #"Changed Type" = Table.TransformColumnTypes(Source,{
        {"Product", type text}, {"Machine", type text}, {"Event Code", type text},
        {"DateTime Start", type datetime}, {"DateTime End", type datetime}}),
    #"Added Custom" = Table.AddColumn(#"Changed Type", "Duration (s)", each Duration.TotalSeconds([DateTime End]-[DateTime Start])),

//added code to group by contiguous event code groups
    #"Grouped Rows" = Table.Group(#"Added Custom", {"Product", "Machine", "Event Code"}, {
        {"DateTime Start", each List.Min([DateTime Start]), type nullable datetime},
        {"DateTime End", each List.Max([DateTime End]), type nullable datetime},
        {"Duration (s)", each List.Sum([#"Duration (s)"]), type number},
        {"Rows Count", each Table.RowCount(_), Int64.Type}},
        GroupKind.Local)
    //    ^^^^^
in
    #"Grouped Rows"


问:
ffmpeg put multiple pictures into different frames
my array in Python looks like this [['0.3251', '6.5712', '12.8174', '13.3979', '13.9784', '14.5357', '14.9537', '15.1394', '15.5109', '16.3236', '16.5094', '16.6951', '17.2524', '17.6704', '18.0419']] and I need to put put one image on that exact same second like in that array with ffmpeg. How can I do that?
For an example I want a video with a song
on first 0.3251s of the video i want to put img1 second 6.5712s of the video i want to put img2 and so on.

答:
Unfortunately I do not know much about Python but here is an example of a Windows batch file how you can create a video with images and sound by using FFmpeg.

This example uses mp3 file with sound, three jpg files with images and two of your starting points: 0.3251 and 6.5712. First image will be displayed since start of the output video to 0.3251, second image will be displayed from 0.3251 to 6.5712, third image will be displayed from 6.5712 to the end of the sound. You can easily add more input images and starting points by following the same pattern (I included one example at the end of this post).

```<code>ffmpeg.exe -i input.mp3 -loop 1 -i input1.jpg -loop 1 -i input2.jpg -loop 1 -i input3.jpg -filter_complex ^
 ^"[1:v]trim=duration=0.3251[a]; ^
   [2:v]trim=start=0.3251:end=6.5712,setpts=PTS-STARTPTS[b]; ^
   [a][b]concat[c]; ^
   [3:v]trim=start=6.5712,setpts=PTS-STARTPTS[d]; ^
   [c][d]concat[video]^" ^
  -map [video]:v -map 0:a -c:v libx264 -crf 18 -c:a copy -shortest output.mp4
</code>```

-i tells FFmpeg to use the following input as the source of stream(s) for the next operations.

input.mp3 is the input file with a sound.

inputX.jpg are the input files with an images.

-loop tells FFmpeg to loop the next input image.

-filter_complex tells FFmpeg to use the following filters.

trim is the type of filter to set the duration of specific image, it can be used with duration option or with start and end options (this is where you need to paste values of your starting points).

concat is the type of filter to merge two previous parts of video into one part that can be used for the next concat operation.

-map tells FFmpeg what streams (video and audio) should be used to create the output file.

-c tells FFmpeg what codecs should be used to encode video and audio to create the output file.

-shortest tells the FFmpeg to use the shortest input stream as the duration of the output (in this case it is the input file with a sound as all images are in infinite loops).

^ is Windows batch specific character used to be able to split one long command to a several lines of code. You can delete all ^ and use one long command instead:

```<code>ffmpeg.exe -i input.mp3 -loop 1 -i input1.jpg -loop 1 -i input2.jpg -loop 1 -i input3.jpg -filter_complex "[1:v]trim=duration=0.3251[a]; [2:v]trim=start=0.3251:end=6.5712,setpts=PTS-STARTPTS[b]; [a][b]concat[c]; [3:v]trim=start=6.5712,setpts=PTS-STARTPTS[d]; [c][d]concat[video]" -map [video]:v -map 0:a -c:v libx264 -crf 18 -c:a copy -shortest output.mp4
</code>```

How to add the next image?

You need to add one more image as the input and change last few lines in the current set of filters:

```<code>   [a][b]concat[c]; ^
   [3:v]trim=start=6.5712,setpts=PTS-STARTPTS[d]; ^
   [c][d]concat[video]^" ^
</code>```

with:

```<code>   [a][b]concat[c]; ^
   [3:v]trim=start=6.5712:end=12.8174,setpts=PTS-STARTPTS[d]; ^
   [c][d]concat[e]; ^
   [4:v]trim=start=12.8174,setpts=PTS-STARTPTS[f]; ^
   [e][f]concat[video]^" ^
</code>```

The letters [a], [b], [c] are the names of the variables - you can use any combination of letters here, not just one letter. For example: [aa][ab]concat[ac] would also work and [video] is a also a variable name used in this command.

Body:
Unfortunately I do not know much about Python but here is an example of a Windows batch file how you can create a video with images and sound by using FFmpeg.

This example uses mp3 file with sound, three jpg files with images and two of your starting points: 0.3251 and 6.5712. First image will be displayed since start of the output video to 0.3251, second image will be displayed from 0.3251 to 6.5712, third image will be displayed from 6.5712 to the end of the sound. You can easily add more input images and starting points by following the same pattern (I included one example at the end of this post).

ffmpeg.exe -i input.mp3 -loop 1 -i input1.jpg -loop 1 -i input2.jpg -loop 1 -i input3.jpg -filter_complex ^
 ^"[1:v]trim=duration=0.3251[a]; ^
   [2:v]trim=start=0.3251:end=6.5712,setpts=PTS-STARTPTS[b]; ^
   [a][b]concat[c]; ^
   [3:v]trim=start=6.5712,setpts=PTS-STARTPTS[d]; ^
   [c][d]concat[video]^" ^
  -map [video]:v -map 0:a -c:v libx264 -crf 18 -c:a copy -shortest output.mp4

-i tells FFmpeg to use the following input as the source of stream(s) for the next operations.

input.mp3 is the input file with a sound.

inputX.jpg are the input files with an images.

-loop tells FFmpeg to loop the next input image.

-filter_complex tells FFmpeg to use the following filters.

trim is the type of filter to set the duration of specific image, it can be used with duration option or with start and end options (this is where you need to paste values of your starting points).

concat is the type of filter to merge two previous parts of video into one part that can be used for the next concat operation.

-map tells FFmpeg what streams (video and audio) should be used to create the output file.

-c tells FFmpeg what codecs should be used to encode video and audio to create the output file.

-shortest tells the FFmpeg to use the shortest input stream as the duration of the output (in this case it is the input file with a sound as all images are in infinite loops).

^ is Windows batch specific character used to be able to split one long command to a several lines of code. You can delete all ^ and use one long command instead:

ffmpeg.exe -i input.mp3 -loop 1 -i input1.jpg -loop 1 -i input2.jpg -loop 1 -i input3.jpg -filter_complex "[1:v]trim=duration=0.3251[a]; [2:v]trim=start=0.3251:end=6.5712,setpts=PTS-STARTPTS[b]; [a][b]concat[c]; [3:v]trim=start=6.5712,setpts=PTS-STARTPTS[d]; [c][d]concat[video]" -map [video]:v -map 0:a -c:v libx264 -crf 18 -c:a copy -shortest output.mp4

How to add the next image?

You need to add one more image as the input and change last few lines in the current set of filters:

   [a][b]concat[c]; ^
   [3:v]trim=start=6.5712,setpts=PTS-STARTPTS[d]; ^
   [c][d]concat[video]^" ^

with:

   [a][b]concat[c]; ^
   [3:v]trim=start=6.5712:end=12.8174,setpts=PTS-STARTPTS[d]; ^
   [c][d]concat[e]; ^
   [4:v]trim=start=12.8174,setpts=PTS-STARTPTS[f]; ^
   [e][f]concat[video]^" ^

The letters [a], [b], [c] are the names of the variables - you can use any combination of letters here, not just one letter. For example: [aa][ab]concat[ac] would also work and [video] is a also a variable name used in this command.


问:
just declaring useStyles in a Mui-React wrapper component, produces strange behaviors
I'm using mui makeStyles in all my components.

But when I try to use it in a wrapper component, I get undesired behavior

The code that I'm using is this:

```<code>import Box from '@mui/material/Box';
import React from 'react';
import NavBar from './NavBar';
import SwipeableLeftDrawer from './SwipeableLeftDrawer';
import { makeStyles } from '@mui/styles';

const useStyles = makeStyles((theme) => ({
    text: {
        marginTop: 0
    }
}));

const WrapperComponent = ({ render }) => {
    // const classes = useStyles(); // If I uncomment this line, I start to have problems
    const [ drawerOpen, setDrawerOpen ] = React.useState(false);

    return (
        <Box>
            <SwipeableLeftDrawer
                open={drawerOpen}
                setDrawerOpen={setDrawerOpen}
                drawerWith={'10em'}
                //
            />
            <Box
                sx={{
                    display: 'flex',
                    flexDirection: 'column',
                    justifyContent: 'space-between',
                    width: '100vw',
                    height: '100vh'
                }}
            >
                <NavBar setOpenDrawer={setDrawerOpen} /> // <=== HERE, SOME STYLINGS CEASE TO WORK
                <Box>{render()}</Box> // here, I render the wrapped component
                ...
                ...
</code>```

This is what I have now,

If I just declare the constant classes = useStyles, even without using it, I get this:

Can somebody tell me what am I missing here?

Thanks in advance

Rafael

答: don't use makeStyle in mui v5 style by using sx props</p>

Body:
I'm using mui makeStyles in all my components.

But when I try to use it in a wrapper component, I get undesired behavior

The code that I'm using is this:

import Box from '@mui/material/Box';
import React from 'react';
import NavBar from './NavBar';
import SwipeableLeftDrawer from './SwipeableLeftDrawer';
import { makeStyles } from '@mui/styles';

const useStyles = makeStyles((theme) => ({
    text: {
        marginTop: 0
    }
}));

const WrapperComponent = ({ render }) => {
    // const classes = useStyles(); // If I uncomment this line, I start to have problems
    const [ drawerOpen, setDrawerOpen ] = React.useState(false);

    return (
        <Box>
            <SwipeableLeftDrawer
                open={drawerOpen}
                setDrawerOpen={setDrawerOpen}
                drawerWith={'10em'}
                //
            />
            <Box
                sx={{
                    display: 'flex',
                    flexDirection: 'column',
                    justifyContent: 'space-between',
                    width: '100vw',
                    height: '100vh'
                }}
            >
                <NavBar setOpenDrawer={setDrawerOpen} /> // <=== HERE, SOME STYLINGS CEASE TO WORK
                <Box>{render()}</Box> // here, I render the wrapped component
                ...
                ...

This is what I have now,

If I just declare the constant classes = useStyles, even without using it, I get this:

Can somebody tell me what am I missing here?

Thanks in advance

Rafael


问:
Discord.py bot sends messages from a different command when another command is input
This is my code for a chatbot:

if 'Hello' or 'hello' in message.content:
    await message.reply((random.choice(hello)))

if 'How are you' or 'how are you' in message.content:
    mention = ' Thanks for asking, ' + message.author.mention + '!'
    await message.channel.send((random.choice(howareyou)) + mention)
```

However, whenever I type 'hello' or 'how are you' into the chat separately, it sends both messages. How do I fix this?

答:
I think it's because of two reasons:

The operator precedence make the interpreter check the in operator before the or operator.

For strings, anything that is not an empty string is considered as having the value True if a boolean is asked. You can have more details in the official documentation about what is considered True or False.

To your interpreter, your code looks like:

if True or ('hello' in message.content):
    await message.reply((random.choice(hello)))

if True or ('how are you' in message.content):
    mention = ' Thanks for asking, ' + message.author.mention + '!'
    await message.channel.send((random.choice(howareyou)) + mention)

```
<p>So:</p>
<ol>
<li><code>'hello' in message.content</code> and <code>'how are you' in message.content</code> becomes <code>True</code> of <code>False</code> depending on the situation</li>
<li><code>'Hello' or True</code> becomes <code>True or True</code> which will become <code>True</code>. The same is true for <code>'Hello' or False</code>. The same is true for <code>'How are you'</code></li>
<li>So your two <code>if</code> will always see that the condition is <code>True</code>and will always execute</li>
</ol>
<p>To correct your situation simply:</p>
<pre class="lang-py prettyprint-override"><code>if 'Hello' in message.content or 'hello' in message.content:
    await message.reply((random.choice(hello)))

if 'How are you' in message.content or 'how are you' in message.content:
    mention = ' Thanks for asking, ' + message.author.mention + '!'
    await message.channel.send((random.choice(howareyou)) + mention)
</code>```

Body:
This is my code for a chatbot:

if 'Hello' or 'hello' in message.content:
    await message.reply((random.choice(hello)))

if 'How are you' or 'how are you' in message.content:
    mention = ' Thanks for asking, ' + message.author.mention + '!'
    await message.channel.send((random.choice(howareyou)) + mention)

However, whenever I type 'hello' or 'how are you' into the chat separately, it sends both messages. How do I fix this?

Body:
I think it's because of two reasons:

The operator precedence make the interpreter check the in operator before the or operator.

For strings, anything that is not an empty string is considered as having the value True if a boolean is asked. You can have more details in the official documentation about what is considered True or False.

To your interpreter, your code looks like:

if True or ('hello' in message.content):
    await message.reply((random.choice(hello)))

if True or ('how are you' in message.content):
    mention = ' Thanks for asking, ' + message.author.mention + '!'
    await message.channel.send((random.choice(howareyou)) + mention)

So:

'hello' in message.content and 'how are you' in message.content becomes True of False depending on the situation

'Hello' or True becomes True or True which will become True. The same is true for 'Hello' or False. The same is true for 'How are you'

So your two if will always see that the condition is Trueand will always execute

To correct your situation simply:

if 'Hello' in message.content or 'hello' in message.content:
    await message.reply((random.choice(hello)))

if 'How are you' in message.content or 'how are you' in message.content:
    mention = ' Thanks for asking, ' + message.author.mention + '!'
    await message.channel.send((random.choice(howareyou)) + mention)


问:
TKinter button over transparent background
I am trying to understand how to apply a button to a transparent background while keeping its shape. When I generate the code below, there is a gray background around the border that appears, and it also looks like it loses its shape.

Colors Used

Sidebar: #2E3A4B at 53%

Button: #2C2F33 at 100%

```<code>from tkinter import *

def btn_clicked():
    """ Prints to console a message every time the button is clicked """
    print("Button Clicked")

root = Tk()

# Configures the frame, and sets up the canvas
root.geometry("1440x1024")
root.configure(bg="#ffffff")
canvas = Canvas(root, bg="#ffffff", height=1024, width=1440, bd=0, highlightthickness=0, relief="ridge")
canvas.place(x=0, y=0)

background_img = PhotoImage(file=f"background.png")
background = canvas.create_image(719.5, 512.5, image=background_img)

img0 = PhotoImage(file=f"img0.png")
alarm_button = Button(image=img0, borderwidth=0, highlightthickness=0, command=btn_clicked, relief="flat")

alarm_button.place(x=9, y=119, width=90, height=90)

root.resizable(False, False)
root.mainloop()
</code>```

Required Images

How it looks:

How it should look:

答:
Good news! I was able to get that answer to a related question you found to work. To make it easier to reuse I've converted it into a formal class and added a couple of methods. In addition I made it flash the image off and back on when it's clicked to give the user some visual feedback like "real" tkinter Buttons do.

Note that it responds to mouse button <ButtonRelease-1> events. That's a better choice in most cases than the <Button-1> event because if the user accidentally presses the button, they can move the mouse off the widget image to avoid setting off the event.

Turns out that using the PIL module was unnecessary. Here's the code:

```<code>import tkinter as tk  # PEP 8 recommends avoiding `import *`.

class CanvasButton:
    """ Create leftmost mouse button clickable canvas image object.

    The x, y coordinates are relative to the top-left corner of the canvas.
    """
    flash_delay = 100  # Milliseconds.

    def __init__(self, canvas, x, y, image_path, command, state=tk.NORMAL):
        self.canvas = canvas
        self.btn_image = tk.PhotoImage(file=image_path)
        self.canvas_btn_img_obj = canvas.create_image(x, y, anchor='nw', state=state,
                                                      image=self.btn_image)
        canvas.tag_bind(self.canvas_btn_img_obj, "<ButtonRelease-1>",
                        lambda event: (self.flash(), command()))
    def flash(self):
        self.set_state(tk.HIDDEN)
        self.canvas.after(self.flash_delay, self.set_state, tk.NORMAL)

    def set_state(self, state):
        """ Change canvas button image's state.

        Normally, image objects are created in state tk.NORMAL. Use value
        tk.DISABLED to make it unresponsive to the mouse, or use tk.HIDDEN to
        make it invisible.
        """
        self.canvas.itemconfigure(self.canvas_btn_img_obj, state=state)

BGR_IMG_PATH = "sunset_background.png"
BUTTON_IMG_PATH = "alarm_button.png"

def btn_clicked():
    """ Prints to console a message every time the button is clicked """
    print("Button Clicked")

root = tk.Tk()

background_img = tk.PhotoImage(file=BGR_IMG_PATH)
bgr_width, bgr_height = background_img.width(), background_img.height()

root.geometry(f'{bgr_width}x{bgr_height}')
root.title("TKinter button over transparent background")
root.configure(bg="white")

canvas = tk.Canvas(root, bg="white", height=bgr_height, width=bgr_width, bd=0,
                   highlightthickness=0, relief="ridge")
canvas.place(x=0, y=0)

background = canvas.create_image(0, 0, anchor='nw', image=background_img)

canvas_btn1 = CanvasButton(canvas, 0, 128, BUTTON_IMG_PATH, btn_clicked)
canvas_btn2 = CanvasButton(canvas, 0, 256, BUTTON_IMG_PATH, btn_clicked)

root.resizable(False, False)
root.mainloop()
</code>```

Screenshot of the result:

Close up:

Body:
I am trying to understand how to apply a button to a transparent background while keeping its shape. When I generate the code below, there is a gray background around the border that appears, and it also looks like it loses its shape.

Colors Used

Sidebar: #2E3A4B at 53%

Button: #2C2F33 at 100%

from tkinter import *

def btn_clicked():
    """ Prints to console a message every time the button is clicked """
    print("Button Clicked")

root = Tk()

# Configures the frame, and sets up the canvas
root.geometry("1440x1024")
root.configure(bg="#ffffff")
canvas = Canvas(root, bg="#ffffff", height=1024, width=1440, bd=0, highlightthickness=0, relief="ridge")
canvas.place(x=0, y=0)

background_img = PhotoImage(file=f"background.png")
background = canvas.create_image(719.5, 512.5, image=background_img)

img0 = PhotoImage(file=f"img0.png")
alarm_button = Button(image=img0, borderwidth=0, highlightthickness=0, command=btn_clicked, relief="flat")

alarm_button.place(x=9, y=119, width=90, height=90)

root.resizable(False, False)
root.mainloop()

Required Images

How it looks:

How it should look:

Body:
Good news! I was able to get that answer to a related question you found to work. To make it easier to reuse I've converted it into a formal class and added a couple of methods. In addition I made it flash the image off and back on when it's clicked to give the user some visual feedback like "real" tkinter Buttons do.

Note that it responds to mouse button <ButtonRelease-1> events. That's a better choice in most cases than the <Button-1> event because if the user accidentally presses the button, they can move the mouse off the widget image to avoid setting off the event.

Turns out that using the PIL module was unnecessary. Here's the code:

import tkinter as tk  # PEP 8 recommends avoiding `import *`.

class CanvasButton:
    """ Create leftmost mouse button clickable canvas image object.

    The x, y coordinates are relative to the top-left corner of the canvas.
    """
    flash_delay = 100  # Milliseconds.

    def __init__(self, canvas, x, y, image_path, command, state=tk.NORMAL):
        self.canvas = canvas
        self.btn_image = tk.PhotoImage(file=image_path)
        self.canvas_btn_img_obj = canvas.create_image(x, y, anchor='nw', state=state,
                                                      image=self.btn_image)
        canvas.tag_bind(self.canvas_btn_img_obj, "<ButtonRelease-1>",
                        lambda event: (self.flash(), command()))
    def flash(self):
        self.set_state(tk.HIDDEN)
        self.canvas.after(self.flash_delay, self.set_state, tk.NORMAL)

    def set_state(self, state):
        """ Change canvas button image's state.

        Normally, image objects are created in state tk.NORMAL. Use value
        tk.DISABLED to make it unresponsive to the mouse, or use tk.HIDDEN to
        make it invisible.
        """
        self.canvas.itemconfigure(self.canvas_btn_img_obj, state=state)

BGR_IMG_PATH = "sunset_background.png"
BUTTON_IMG_PATH = "alarm_button.png"

def btn_clicked():
    """ Prints to console a message every time the button is clicked """
    print("Button Clicked")

root = tk.Tk()

background_img = tk.PhotoImage(file=BGR_IMG_PATH)
bgr_width, bgr_height = background_img.width(), background_img.height()

root.geometry(f'{bgr_width}x{bgr_height}')
root.title("TKinter button over transparent background")
root.configure(bg="white")

canvas = tk.Canvas(root, bg="white", height=bgr_height, width=bgr_width, bd=0,
                   highlightthickness=0, relief="ridge")
canvas.place(x=0, y=0)

background = canvas.create_image(0, 0, anchor='nw', image=background_img)

canvas_btn1 = CanvasButton(canvas, 0, 128, BUTTON_IMG_PATH, btn_clicked)
canvas_btn2 = CanvasButton(canvas, 0, 256, BUTTON_IMG_PATH, btn_clicked)

root.resizable(False, False)
root.mainloop()

Screenshot of the result:

Close up:


问:
Trying to retrieve data from SQL Server DB using PHP and only get 1 for rowcount when there are 10000 rows
So, I'm trying to retrieve data from a data base on my own www.ionos.com server, which is dedicated and running SQL Server 2019.

I'm using PHP to retrieve the data. But, even though there are over 10K rows, I only ever see 1 row!

When I retrieve the data, I get 100 rows (restricting the select to TOP(100)) but all the data is coming back as NULL which is absolutely not true.

Here is my PHP code:

```<code><?php

// require_once('../../PtcDebug.php');
// $_GET['debug'] = true;        // turn on the debug
// $_GET['debug_off'] = true;    // turn off debug
// PtcDebug::load();
// COMMENT when through testing....
// $error_reporting = error_reporting(E_ALL);
// $ini_set = ini_set('display_errors', 'on');

$return_arr = array();

$parameters = array();

$host = "tcp:12.345.67.890,1433";
$uid = "sa";
$pwd = "**********";
$db = "someDBName";
$query = "SELECT TOP(100)
       [Product_Key]
      ,[Legacy_Product_Key]
      ,[Product_Code]
      ,[Date_Added]
      ,[Title]
      ,[Weight]
      ,[MSRP]
      ,[Wholesale]
      ,[Available_for_Web_Sale]
      ,[Detailed_Description]
      ,[Product_Type]
      ,[Manufacturer]
      ,[Artist_Magician]
      ,[Maintain_MSRP]
      ,[All_Star_Product]
      ,[On_Sale]
      ,[SkillLevels]
      ,[Image_URL]
      ,[Thumbnail_URL]
      ,[Alternate_Images]
      ,[Videos]
      ,[Christmas_Themed]
      ,[Halloween_Themed]
      ,[Card_Magic_and_Trick_Decks]
      ,[Decks_Custom_Standard]
      ,[Lectures_and_Conventions]
      ,[Magazines]
      ,[Money_Magic]
      ,[Posters_Gifts_and_Collectables]
      ,[Refills]
      ,[Silk_and_Silk_Magic]
      ,[Special_Effects_Fire_Smoke_Sound]
      ,[Sponge_and_Sponge_Magic]
      ,[Tables_and_Cases]
      ,[Theory_History_and_Business]
      ,[Toy_Magic_Toy_Kits_Puzzles]
      ,[Utility]
      ,[Close_Up_Performer]
      ,[Comedy_Performer]
      ,[Escape_Performer]
      ,[Gambling_Performer]
      ,[Illusionist]
      ,[Juggling_Performer]
      ,[Kids_Show_and_Balloon_Performer]
      ,[Mentalism_Bizarre_and_Psychokinesis_Perf]
      ,[Stage_Parlor_Performer]
      ,[Religious_and_Gospel_Performer]
      ,[Street_Performer]
      ,[Walk_Around_Performer]
      ,[Black_Label]
      ,[Limited_Edition] FROM murphys_product_list_new";

$querycnt = "SELECT COUNT(*) FROM a_database_table";
$dbconn = new PDO("sqlsrv:Server=12.345.67.890,1433;Database=" . $db . "", $uid, $pwd);
$dbconn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

if ($dbconn === false) {
    printf("There was an error opening the connection");
    die("Error opening connection: " . PDO::ERRMODE_EXCEPTION);
} else {

    /* Connect using SQL Server Authentication. */
    try {
        printf("Inside TRY<br>");

        $stmtcnt = $dbconn->prepare($querycnt);
        // $stmtcnt->execute();
        print_r($stmtcnt->execute() . "<br>");

        $stmtproducts = $dbconn->prepare($query);
        $stmtproducts->execute();

        // if ($row = $stmtproducts->fetch(PDO::FETCH_ASSOC)) {
        //     printf("Inside IF for rows - " . $row . "<br>");
        //     foreach ($row as $item) {
        //         $products_arr = array(
        //             "status" => true,
        //             "id" => $item['Product_Key'],
        //             "productcd" => $item['Product_Code']
        //         );
        //     }
        // } else {
        //     $products_arr = array(
        //         "status" => false,
        //         "message" => "Invalid Username and Password!",
        //     );
        // }
        print_r(json_encode($stmtproducts) . "<br>");

    } catch (Exception $e) {
        printf("Inside CATCH<br>");
        $e->getMessage();
        printf("ERROR CONNECTION: %s\n", $e);
        die('Error connecting to SQL Server: ' . $e . '.');
    }
}

if (!empty($stmtproducts)) {
str_replace('T', ' ', $endtime) . "<p></p><ul>";
    foreach ($stmtproducts as $item) {
        $id = $item->Product_Key;
        $legacyid = $item->Legacy_Product_Key;
        $productcd = $item->Product_Code;
        $dateAdded = $item->Date_Added;
        $title = $item->Title;
        $weight = $item->Weight;
        $msrp = $item->MSRP;
        $wholesale = $item->Wholesale;
        $qty = $item->Available_for_Web_Sale;
        $detailed_description = $item->Detailed_Description;
        $productType = $item->Product_Type;
        $manufacturer = $item->Manufacturer;
        $artist_or_magician = $item->Artist_Magician;
        $allstar_product = $item->All_Star_Product;
        $onsale = $item->On_Sale;
        $skill_levels = $item->SkillLevels;
        $imageURL = $item->Image_URL;
        $thumbnailURL = $item->Thumbnail_URL;
        $alt_images = $item->Alternate_Images;
        $videos = $item->Videos;
        $christmas_Themed = $item->Christmas_Themed;
        $halloween_Themed = $item->Halloween_Themed;
        $card_magic_and_trick_decks = $item->Card_Magic_Trick_Decks;
        $decks_custom_standard = $item->Decks_Custom_Standard;
        $lectures_and_conventions = $item->Lectures_and_Conventions;
        $magazines = $item->Magazines;
        $money_magic = $item->Money_Magic;
        $posters_gifts_and_collectables = $item->Posters_Gifts_and_Collectables;
        $refills = $item->Refills;
        $silk_and_silk_magic = $item->Silk_and_Silk_Magic;
        $special_effects_fire_smoke_sound = $item->Special_Effects_Fire_Smoke_Sound;
        $sponge_and_Sponge_magic = $item->Sponge_and_Sponge_Magic;
        $tables_and_cases = $item->Tables_and_Cases;
        $theory_history_and_business = $item->Theory_History_and_Business;
        $toy_magic_toy_kits_puzzles = $item->Toy_Magic_Toy_Kits_Puzzles;
        $utility = $item->Utility;
        $close_up_performer = $item->Close_Up_Performer;
        $comedy_performer = $item->Comedy_Performer;
        $escape_performer = $item->Escape_Performer;
        $gambling_performer = $item->Gambling_Performer;
        $illusionist = $item->Illusionist;
        $juggling_performer = $item->Juggling_Performer;
        $kids_show_and_balloon_performer = $item->Kids_Show_and_Balloon_Performer;
        $mentalism_performer = $item->Mentalism_Bizarre_and_Psychokinesis_Perf;
        $stage_parlor_performer = $item->Stage_Parlor_Performer;
        $religious_performer = $item->Religious_and_Gospel_Performer;
        $street_performer = $item->Street_Performer;
        $walk_around_performer = $item->Walk_Around_Performer;
        $black_label = $item->Black_Label;
        $limited_edition = $item->Limited_Edition;

        // get rid of \\" and then \\""

        $title = str_replace('5\\"x8\\"', '5x8', $title);
        $title = str_replace('\\\\""Six\\\\""', 'Six', $title);
        $title = str_replace('3\\\\"X5\\\\"', '3x5', $title);

        stripslashes($title);

        $return_arr[] = array(
            "id" => $id,
            "legacyid" => $legacyid,
            "product_cd" => $productcd,
            "dateadded" => $dateAdded,
            "title" => $title,
            "weight" => $weight,
            "price" => $msrp,
            "wholesale" => $wholesale,
            "qty" => $qty,
            "htmldesc" => $detailed_description,
            "producttype" => $productType,
            "manufacturer" => $manufacturer,
            "artist_magician" => $artist_or_magician,
            "allstarproduct" => $allstar_product,
            "onsale" => $onsale,
            "skill_level" => $skill_levels,
            "imgfilename" => $imageURL,
            "imgthumbname" => $thumbnailURL,
            "altimages" => $alt_images,
            "videos" => $videos,
            "xmas" => $christmas_Themed,
            "halloween" => $halloween_Themed,
            "carddeckstricks" => $card_magic_and_trick_decks,
            "customstandarddecks" => $decks_custom_standard,
            "lecturesconventions" => $lectures_and_conventions,
            "magazines" => $magazines,
            "money" => $money_magic,
            "refills" => $refills,
            "silks" => $silk_and_silk_magic,
            "spfx" => $special_effects_fire_smoke_sound,
            "sponges" => $sponge_and_Sponge_magic,
            "tablescases" => $tables_and_cases,
            "theoryhistory" => $theory_history_and_business,
            "toyskitspuzzles" => $toy_magic_toy_kits_puzzles,
            "utility" => $utility,
            "closeup" => $close_up_performer,
            "comedy" => $comedy_performer,
            "escape" => $escape_performer,
            "gambling" => $gambling_performer,
            "illusionist" => $illusionist,
            "juggling" => $juggling_performer,
            "kidsballoons" => $kids_show_and_balloon_performer,
            "mentalism" => $mentalism_performer,
            "stageparlor" => $stage_parlor_performer,
            "religious" => $religious_performer,
            "street" => $street_performer,
            "walkaround" => $walk_around_performer,
            "blacklabel" => $black_label,
            "ltdedition" => $limited_edition

        );
    }

    $obj = (object) [
        "status" => 200,
        "statusText" => "Success",
        "data" => $return_arr
    ];

    // Save data to sessionStorage
    // sessionStorage . setItem('allmagictopresent', json_encode($obj, JSON_PRETTY_PRINT));

    echo json_encode($obj, JSON_PRETTY_PRINT);
} else {
    echo "No items found";
}

</code>```

What I get back from this is the following for this URL:
http://magicdjs.com/webservices/vendor/murphs/murphs-services-mssql.php

```<code>Inside TRY
1
{"queryString":"SELECT TOP(100) \n [Product_Key]\n ,[Legacy_Product_Key]\n ,[Product_Code]\n ,[Date_Added]\n ,[Title]\n ,[Weight]\n ,[MSRP]\n ,[Wholesale]\n ,[Available_for_Web_Sale]\n ,[Detailed_Description]\n ,[Product_Type]\n ,[Manufacturer]\n ,[Artist_Magician]\n ,[Maintain_MSRP]\n ,[All_Star_Product]\n ,[On_Sale]\n ,[SkillLevels]\n ,[Image_URL]\n ,[Thumbnail_URL]\n ,[Alternate_Images]\n ,[Videos]\n ,[Christmas_Themed]\n ,[Halloween_Themed]\n ,[Card_Magic_and_Trick_Decks]\n ,[Decks_Custom_Standard]\n ,[Lectures_and_Conventions]\n ,[Magazines]\n ,[Money_Magic]\n ,[Posters_Gifts_and_Collectables]\n ,[Refills]\n ,[Silk_and_Silk_Magic]\n ,[Special_Effects_Fire_Smoke_Sound]\n ,[Sponge_and_Sponge_Magic]\n ,[Tables_and_Cases]\n ,[Theory_History_and_Business]\n ,[Toy_Magic_Toy_Kits_Puzzles]\n ,[Utility]\n ,[Close_Up_Performer]\n ,[Comedy_Performer]\n ,[Escape_Performer]\n ,[Gambling_Performer]\n ,[Illusionist]\n ,[Juggling_Performer]\n ,[Kids_Show_and_Balloon_Performer]\n ,[Mentalism_Bizarre_and_Psychokinesis_Perf]\n ,[Stage_Parlor_Performer]\n ,[Religious_and_Gospel_Performer]\n ,[Street_Performer]\n ,[Walk_Around_Performer]\n ,[Black_Label]\n ,[Limited_Edition] FROM murphys_product_list_new"}
{ "status": 200, "statusText": "Success", "data": [ { "id": null, "legacyid": null, "product_cd": null, "dateadded": null, "title": "", "weight": null, "price": null, "wholesale": null, "qty": null, "htmldesc": null, "producttype": null, "manufacturer": null, "artist_magician": null, "allstarproduct": null, "onsale": null, "skill_level": null, "imgfilename": null, "imgthumbname": null, "altimages": null, "videos": null, "xmas": null, "halloween": null, "carddeckstricks": null, "customstandarddecks": null, "lecturesconventions": null, "magazines": null, "money": null, "refills": null, "silks": null, "spfx": null, "sponges": null, "tablescases": null, "theoryhistory": null, "toyskitspuzzles": null, "utility": null, "closeup": null, "comedy": null, "escape": null, "gambling": null, "illusionist": null, "juggling": null, "kidsballoons": null, "mentalism": null, "stageparlor": null, "religious": null, "street": null, "walkaround": null, "blacklabel": null, "ltdedition": null },.... and so on
</code>```

Question: Why are all NULLS coming back when in SQL Server Mgmt Studio, I see this...

UPDATE BECAUSE OF DALE

```<code>        if ($stmtproducts->fetch(PDO::FETCH_ASSOC)) {
            printf("Inside IF for rows - " . $row . "<br>");
            while ($row = $stmtproducts->fetch(PDO::FETCH_ASSOC)) {
                $products_arr = array(
                    "status" => true,
                    "id" => $row['Product_Key'],
                    "productcd" => $row['Product_Code'],
                    "title" => $row['Title']
                );
                print_r(json_encode($products_arr) . "<br>");

            }
            $obj = (object) [
                "status" => 200,
                "statusText" => "Success",
                "data" => $products_arr
            ];
            echo json_encode($obj, JSON_PRETTY_PRINT);
        } else {
            $products_arr = array(
                "status" => false,
                "message" => "Invalid Username and Password!",
            );
        }
</code>```

Re-run this to see the different results:

http://magicdjs.com/webservices/vendor/murphs/murphs-services-mssql.php

Now I need to put ALL those records BACK into the

```<code>            $obj = (object) [
                "status" => 200,
                "statusText" => "Success",
                "data" => $products_arr
            ];
</code>```

But I'm only putting "1" object vice 100.  I'm close Dale. Thank you!  A wee bit more help please, sir and make it a solution and I'll vote for you.

UPDATE FOR ROWCOUNT:

This works in MSSQL Server Mgmt Studio but not my code

```<code>SELECT COUNT(*) FROM murphys_product_list_new
</code>```

答:
You're creating $products_arr multiple times in a loop but you are only ever ending up with one element in the array.

Instead of $products_array = array(...) (which will replace the contents of $products_array every time with one single element), you need to use $products_array[] = array(...), which will push an element to the end of the $products_array:

This should give you an array of elements:

```<code>   if ($stmtproducts->fetch(PDO::FETCH_ASSOC)) {
        printf("Inside IF for rows - " . $row . "<br>");
        while ($row = $stmtproducts->fetch(PDO::FETCH_ASSOC)) {
            $products_arr[] = array(
                "status" => true,
                "id" => $row['Product_Key'],
                "productcd" => $row['Product_Code'],
                "title" => $row['Title']
            );
            print_r(json_encode($products_arr) . "<br>");

        }
        $obj = (object) [
            "status" => 200,
            "statusText" => "Success",
            "data" => $products_arr
        ];
        echo json_encode($obj, JSON_PRETTY_PRINT);
    } else {
        $products_arr = array(
            "status" => false,
            "message" => "Invalid Username and Password!",
        );
    }
</code>```

Body:
So, I'm trying to retrieve data from a data base on my own www.ionos.com server, which is dedicated and running SQL Server 2019.

I'm using PHP to retrieve the data. But, even though there are over 10K rows, I only ever see 1 row!

When I retrieve the data, I get 100 rows (restricting the select to TOP(100)) but all the data is coming back as NULL which is absolutely not true.

Here is my PHP code:

<?php

// require_once('../../PtcDebug.php');
// $_GET['debug'] = true;        // turn on the debug
// $_GET['debug_off'] = true;    // turn off debug
// PtcDebug::load();
// COMMENT when through testing....
// $error_reporting = error_reporting(E_ALL);
// $ini_set = ini_set('display_errors', 'on');

$return_arr = array();

$parameters = array();

$host = "tcp:12.345.67.890,1433";
$uid = "sa";
$pwd = "**********";
$db = "someDBName";
$query = "SELECT TOP(100)
       [Product_Key]
      ,[Legacy_Product_Key]
      ,[Product_Code]
      ,[Date_Added]
      ,[Title]
      ,[Weight]
      ,[MSRP]
      ,[Wholesale]
      ,[Available_for_Web_Sale]
      ,[Detailed_Description]
      ,[Product_Type]
      ,[Manufacturer]
      ,[Artist_Magician]
      ,[Maintain_MSRP]
      ,[All_Star_Product]
      ,[On_Sale]
      ,[SkillLevels]
      ,[Image_URL]
      ,[Thumbnail_URL]
      ,[Alternate_Images]
      ,[Videos]
      ,[Christmas_Themed]
      ,[Halloween_Themed]
      ,[Card_Magic_and_Trick_Decks]
      ,[Decks_Custom_Standard]
      ,[Lectures_and_Conventions]
      ,[Magazines]
      ,[Money_Magic]
      ,[Posters_Gifts_and_Collectables]
      ,[Refills]
      ,[Silk_and_Silk_Magic]
      ,[Special_Effects_Fire_Smoke_Sound]
      ,[Sponge_and_Sponge_Magic]
      ,[Tables_and_Cases]
      ,[Theory_History_and_Business]
      ,[Toy_Magic_Toy_Kits_Puzzles]
      ,[Utility]
      ,[Close_Up_Performer]
      ,[Comedy_Performer]
      ,[Escape_Performer]
      ,[Gambling_Performer]
      ,[Illusionist]
      ,[Juggling_Performer]
      ,[Kids_Show_and_Balloon_Performer]
      ,[Mentalism_Bizarre_and_Psychokinesis_Perf]
      ,[Stage_Parlor_Performer]
      ,[Religious_and_Gospel_Performer]
      ,[Street_Performer]
      ,[Walk_Around_Performer]
      ,[Black_Label]
      ,[Limited_Edition] FROM murphys_product_list_new";

$querycnt = "SELECT COUNT(*) FROM a_database_table";
$dbconn = new PDO("sqlsrv:Server=12.345.67.890,1433;Database=" . $db . "", $uid, $pwd);
$dbconn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

if ($dbconn === false) {
    printf("There was an error opening the connection");
    die("Error opening connection: " . PDO::ERRMODE_EXCEPTION);
} else {

    /* Connect using SQL Server Authentication. */
    try {
        printf("Inside TRY
");

        $stmtcnt = $dbconn->prepare($querycnt);
        // $stmtcnt->execute();
        print_r($stmtcnt->execute() . "
");

        $stmtproducts = $dbconn->prepare($query);
        $stmtproducts->execute();

        // if ($row = $stmtproducts->fetch(PDO::FETCH_ASSOC)) {
        //     printf("Inside IF for rows - " . $row . "
");
        //     foreach ($row as $item) {
        //         $products_arr = array(
        //             "status" => true,
        //             "id" => $item['Product_Key'],
        //             "productcd" => $item['Product_Code']
        //         );
        //     }
        // } else {
        //     $products_arr = array(
        //         "status" => false,
        //         "message" => "Invalid Username and Password!",
        //     );
        // }
        print_r(json_encode($stmtproducts) . "
");

    } catch (Exception $e) {
        printf("Inside CATCH
");
        $e->getMessage();
        printf("ERROR CONNECTION: %s\n", $e);
        die('Error connecting to SQL Server: ' . $e . '.');
    }
}

if (!empty($stmtproducts)) {
str_replace('T', ' ', $endtime) . "

";
    foreach ($stmtproducts as $item) {
        $id = $item->Product_Key;
        $legacyid = $item->Legacy_Product_Key;
        $productcd = $item->Product_Code;
        $dateAdded = $item->Date_Added;
        $title = $item->Title;
        $weight = $item->Weight;
        $msrp = $item->MSRP;
        $wholesale = $item->Wholesale;
        $qty = $item->Available_for_Web_Sale;
        $detailed_description = $item->Detailed_Description;
        $productType = $item->Product_Type;
        $manufacturer = $item->Manufacturer;
        $artist_or_magician = $item->Artist_Magician;
        $allstar_product = $item->All_Star_Product;
        $onsale = $item->On_Sale;
        $skill_levels = $item->SkillLevels;
        $imageURL = $item->Image_URL;
        $thumbnailURL = $item->Thumbnail_URL;
        $alt_images = $item->Alternate_Images;
        $videos = $item->Videos;
        $christmas_Themed = $item->Christmas_Themed;
        $halloween_Themed = $item->Halloween_Themed;
        $card_magic_and_trick_decks = $item->Card_Magic_Trick_Decks;
        $decks_custom_standard = $item->Decks_Custom_Standard;
        $lectures_and_conventions = $item->Lectures_and_Conventions;
        $magazines = $item->Magazines;
        $money_magic = $item->Money_Magic;
        $posters_gifts_and_collectables = $item->Posters_Gifts_and_Collectables;
        $refills = $item->Refills;
        $silk_and_silk_magic = $item->Silk_and_Silk_Magic;
        $special_effects_fire_smoke_sound = $item->Special_Effects_Fire_Smoke_Sound;
        $sponge_and_Sponge_magic = $item->Sponge_and_Sponge_Magic;
        $tables_and_cases = $item->Tables_and_Cases;
        $theory_history_and_business = $item->Theory_History_and_Business;
        $toy_magic_toy_kits_puzzles = $item->Toy_Magic_Toy_Kits_Puzzles;
        $utility = $item->Utility;
        $close_up_performer = $item->Close_Up_Performer;
        $comedy_performer = $item->Comedy_Performer;
        $escape_performer = $item->Escape_Performer;
        $gambling_performer = $item->Gambling_Performer;
        $illusionist = $item->Illusionist;
        $juggling_performer = $item->Juggling_Performer;
        $kids_show_and_balloon_performer = $item->Kids_Show_and_Balloon_Performer;
        $mentalism_performer = $item->Mentalism_Bizarre_and_Psychokinesis_Perf;
        $stage_parlor_performer = $item->Stage_Parlor_Performer;
        $religious_performer = $item->Religious_and_Gospel_Performer;
        $street_performer = $item->Street_Performer;
        $walk_around_performer = $item->Walk_Around_Performer;
        $black_label = $item->Black_Label;
        $limited_edition = $item->Limited_Edition;

        // get rid of \\" and then \\""

        $title = str_replace('5\\"x8\\"', '5x8', $title);
        $title = str_replace('\\\\""Six\\\\""', 'Six', $title);
        $title = str_replace('3\\\\"X5\\\\"', '3x5', $title);

        stripslashes($title);

        $return_arr[] = array(
            "id" => $id,
            "legacyid" => $legacyid,
            "product_cd" => $productcd,
            "dateadded" => $dateAdded,
            "title" => $title,
            "weight" => $weight,
            "price" => $msrp,
            "wholesale" => $wholesale,
            "qty" => $qty,
            "htmldesc" => $detailed_description,
            "producttype" => $productType,
            "manufacturer" => $manufacturer,
            "artist_magician" => $artist_or_magician,
            "allstarproduct" => $allstar_product,
            "onsale" => $onsale,
            "skill_level" => $skill_levels,
            "imgfilename" => $imageURL,
            "imgthumbname" => $thumbnailURL,
            "altimages" => $alt_images,
            "videos" => $videos,
            "xmas" => $christmas_Themed,
            "halloween" => $halloween_Themed,
            "carddeckstricks" => $card_magic_and_trick_decks,
            "customstandarddecks" => $decks_custom_standard,
            "lecturesconventions" => $lectures_and_conventions,
            "magazines" => $magazines,
            "money" => $money_magic,
            "refills" => $refills,
            "silks" => $silk_and_silk_magic,
            "spfx" => $special_effects_fire_smoke_sound,
            "sponges" => $sponge_and_Sponge_magic,
            "tablescases" => $tables_and_cases,
            "theoryhistory" => $theory_history_and_business,
            "toyskitspuzzles" => $toy_magic_toy_kits_puzzles,
            "utility" => $utility,
            "closeup" => $close_up_performer,
            "comedy" => $comedy_performer,
            "escape" => $escape_performer,
            "gambling" => $gambling_performer,
            "illusionist" => $illusionist,
            "juggling" => $juggling_performer,
            "kidsballoons" => $kids_show_and_balloon_performer,
            "mentalism" => $mentalism_performer,
            "stageparlor" => $stage_parlor_performer,
            "religious" => $religious_performer,
            "street" => $street_performer,
            "walkaround" => $walk_around_performer,
            "blacklabel" => $black_label,
            "ltdedition" => $limited_edition

        );
    }

    $obj = (object) [
        "status" => 200,
        "statusText" => "Success",
        "data" => $return_arr
    ];

    // Save data to sessionStorage
    // sessionStorage . setItem('allmagictopresent', json_encode($obj, JSON_PRETTY_PRINT));

    echo json_encode($obj, JSON_PRETTY_PRINT);
} else {
    echo "No items found";
}

What I get back from this is the following for this URL:
http://magicdjs.com/webservices/vendor/murphs/murphs-services-mssql.php

Inside TRY
1
{"queryString":"SELECT TOP(100) \n [Product_Key]\n ,[Legacy_Product_Key]\n ,[Product_Code]\n ,[Date_Added]\n ,[Title]\n ,[Weight]\n ,[MSRP]\n ,[Wholesale]\n ,[Available_for_Web_Sale]\n ,[Detailed_Description]\n ,[Product_Type]\n ,[Manufacturer]\n ,[Artist_Magician]\n ,[Maintain_MSRP]\n ,[All_Star_Product]\n ,[On_Sale]\n ,[SkillLevels]\n ,[Image_URL]\n ,[Thumbnail_URL]\n ,[Alternate_Images]\n ,[Videos]\n ,[Christmas_Themed]\n ,[Halloween_Themed]\n ,[Card_Magic_and_Trick_Decks]\n ,[Decks_Custom_Standard]\n ,[Lectures_and_Conventions]\n ,[Magazines]\n ,[Money_Magic]\n ,[Posters_Gifts_and_Collectables]\n ,[Refills]\n ,[Silk_and_Silk_Magic]\n ,[Special_Effects_Fire_Smoke_Sound]\n ,[Sponge_and_Sponge_Magic]\n ,[Tables_and_Cases]\n ,[Theory_History_and_Business]\n ,[Toy_Magic_Toy_Kits_Puzzles]\n ,[Utility]\n ,[Close_Up_Performer]\n ,[Comedy_Performer]\n ,[Escape_Performer]\n ,[Gambling_Performer]\n ,[Illusionist]\n ,[Juggling_Performer]\n ,[Kids_Show_and_Balloon_Performer]\n ,[Mentalism_Bizarre_and_Psychokinesis_Perf]\n ,[Stage_Parlor_Performer]\n ,[Religious_and_Gospel_Performer]\n ,[Street_Performer]\n ,[Walk_Around_Performer]\n ,[Black_Label]\n ,[Limited_Edition] FROM murphys_product_list_new"}
{ "status": 200, "statusText": "Success", "data": [ { "id": null, "legacyid": null, "product_cd": null, "dateadded": null, "title": "", "weight": null, "price": null, "wholesale": null, "qty": null, "htmldesc": null, "producttype": null, "manufacturer": null, "artist_magician": null, "allstarproduct": null, "onsale": null, "skill_level": null, "imgfilename": null, "imgthumbname": null, "altimages": null, "videos": null, "xmas": null, "halloween": null, "carddeckstricks": null, "customstandarddecks": null, "lecturesconventions": null, "magazines": null, "money": null, "refills": null, "silks": null, "spfx": null, "sponges": null, "tablescases": null, "theoryhistory": null, "toyskitspuzzles": null, "utility": null, "closeup": null, "comedy": null, "escape": null, "gambling": null, "illusionist": null, "juggling": null, "kidsballoons": null, "mentalism": null, "stageparlor": null, "religious": null, "street": null, "walkaround": null, "blacklabel": null, "ltdedition": null },.... and so on

Question: Why are all NULLS coming back when in SQL Server Mgmt Studio, I see this...

UPDATE BECAUSE OF DALE

        if ($stmtproducts->fetch(PDO::FETCH_ASSOC)) {
            printf("Inside IF for rows - " . $row . "
");
            while ($row = $stmtproducts->fetch(PDO::FETCH_ASSOC)) {
                $products_arr = array(
                    "status" => true,
                    "id" => $row['Product_Key'],
                    "productcd" => $row['Product_Code'],
                    "title" => $row['Title']
                );
                print_r(json_encode($products_arr) . "
");

            }
            $obj = (object) [
                "status" => 200,
                "statusText" => "Success",
                "data" => $products_arr
            ];
            echo json_encode($obj, JSON_PRETTY_PRINT);
        } else {
            $products_arr = array(
                "status" => false,
                "message" => "Invalid Username and Password!",
            );
        }

Re-run this to see the different results:

http://magicdjs.com/webservices/vendor/murphs/murphs-services-mssql.php

Now I need to put ALL those records BACK into the

            $obj = (object) [
                "status" => 200,
                "statusText" => "Success",
                "data" => $products_arr
            ];

But I'm only putting "1" object vice 100.  I'm close Dale. Thank you!  A wee bit more help please, sir and make it a solution and I'll vote for you.

UPDATE FOR ROWCOUNT:

This works in MSSQL Server Mgmt Studio but not my code

SELECT COUNT(*) FROM murphys_product_list_new

Body:
You're creating $products_arr multiple times in a loop but you are only ever ending up with one element in the array.

Instead of $products_array = array(...) (which will replace the contents of $products_array every time with one single element), you need to use $products_array[] = array(...), which will push an element to the end of the $products_array:

This should give you an array of elements:

   if ($stmtproducts->fetch(PDO::FETCH_ASSOC)) {
        printf("Inside IF for rows - " . $row . "<br>");
        while ($row = $stmtproducts->fetch(PDO::FETCH_ASSOC)) {
            $products_arr[] = array(
                "status" => true,
                "id" => $row['Product_Key'],
                "productcd" => $row['Product_Code'],
                "title" => $row['Title']
            );
            print_r(json_encode($products_arr) . "<br>");

        }
        $obj = (object) [
            "status" => 200,
            "statusText" => "Success",
            "data" => $products_arr
        ];
        echo json_encode($obj, JSON_PRETTY_PRINT);
    } else {
        $products_arr = array(
            "status" => false,
            "message" => "Invalid Username and Password!",
        );
    }


问:
Copying to Clipboard in a content Script
Can someone explain how I can write to clipboard please? I've seen a lot of ways but I cant seem to understand how. Currently using manifest v3 and no background.js script.

popup.js (action: download) -> contentscript.js (see below)

```<code>function listener(info) {

    chrome.runtime.onMessage.addListener(
        function (request, sender, sendResponse) {

            if (!request.action) return sendResponse({
                err: 'Error: No Request Action'
            });

            switch (request.action) {
                case "copy":

                    var textCopy = info.links.join(', ').replace(/"/g, '') // Text to Copy (String)

                    navigator.clipboard.writeText(textCopy).then(() => {
                        sendResponse('success')
                    }, () => {
                        sendResponse('failed')
                    });

                    break;

                // Other Requests

            }

        }
    );
}
</code>```

答:
thanks to @cactus12 for the help here's the code that worked for me!</p>
```<code>var textCopy = '' // Text to Copy
var copyFrom = document.createElement("textarea");

copyFrom.textContent = `${textCopy}`;
document.body.appendChild(copyFrom);

copyFrom.select();
document.execCommand(`copy`);

copyFrom.blur();
document.body.removeChild(copyFrom);
</code>```

Body:
Can someone explain how I can write to clipboard please? I've seen a lot of ways but I cant seem to understand how. Currently using manifest v3 and no background.js script.

popup.js (action: download) -> contentscript.js (see below)

function listener(info) {

    chrome.runtime.onMessage.addListener(
        function (request, sender, sendResponse) {

            if (!request.action) return sendResponse({
                err: 'Error: No Request Action'
            });

            switch (request.action) {
                case "copy":

                    var textCopy = info.links.join(', ').replace(/"/g, '') // Text to Copy (String)

                    navigator.clipboard.writeText(textCopy).then(() => {
                        sendResponse('success')
                    }, () => {
                        sendResponse('failed')
                    });

                    break;

                // Other Requests

            }

        }
    );
}

Body:
thanks to @cactus12 for the help here's the code that worked for me!

var textCopy = '' // Text to Copy
var copyFrom = document.createElement("textarea");

copyFrom.textContent = `${textCopy}`;
document.body.appendChild(copyFrom);

copyFrom.select();
document.execCommand(`copy`);

copyFrom.blur();
document.body.removeChild(copyFrom);


答: I thinks nothing wrong in this code it something else referring to some style error .you can check your html if its ok and also show you code to insure whats the problem. Its would be pleasure</p>

Title: Uncaught TypeError: Cannot read properties of null (reading 'style')

Body:
I, trying to make a div clickable so it will be redirected to a different document or site but got that error.
However, it works with the old way of using the onclick as an attribute inside the element.

var examscol = document.getElementById("exam-col1");
function examCol() {
  return window.location.assign("https://www.w3schools.com")
}

examscol.addEventListener("click", examCol);

Any suggestions on why it isn't working with this way ?


问:
AWS LAMBDA function "Cannot read property 's3' of undefined"
I am using lambda AWS to convert mp4 to HLS and when I put my hostname: I am getting an error of the following:

{

"errorType": "TypeError",
  "errorMessage": "Cannot read property 's3' of undefined",
  "trace": [
    "TypeError: Cannot read property 's3' of undefined",
    "    at Runtime.exports.handler (/var/task/index.js:14:35)",
    "    at Runtime.handleOnce (/var/runtime/Runtime.js:66:25)"
  ]
}
```

line 14 inputBucket = eventRecord.s3.bucket.name,

My output is set in Lambda to which bucker I want to post to.

Any idea?

答:
It looks like the event your Lambda function is not a valid S3 event.

At a guess, you are manually triggering your Lambda function with a test event from the AWS console and you have supplied an non-conformant JSON structure.

Here is a minimal example of what you need in the test event:

```<code>{
  "Records": [
    {
      "s3": {
        "bucket": {
          "name": "my-s3-bucket"
        },
        "object": {
          "key": "HappyFace.jpg"
        }
      }
    }
  ]
}
</code>```

Body:
I am using lambda AWS to convert mp4 to HLS and when I put my hostname: I am getting an error of the following:

{

"errorType": "TypeError",
  "errorMessage": "Cannot read property 's3' of undefined",
  "trace": [
    "TypeError: Cannot read property 's3' of undefined",
    "    at Runtime.exports.handler (/var/task/index.js:14:35)",
    "    at Runtime.handleOnce (/var/runtime/Runtime.js:66:25)"
  ]
}

line 14 inputBucket = eventRecord.s3.bucket.name,

My output is set in Lambda to which bucker I want to post to.

Any idea?

Body:
It looks like the event your Lambda function is not a valid S3 event.

At a guess, you are manually triggering your Lambda function with a test event from the AWS console and you have supplied an non-conformant JSON structure.

Here is a minimal example of what you need in the test event:

{
  "Records": [
    {
      "s3": {
        "bucket": {
          "name": "my-s3-bucket"
        },
        "object": {
          "key": "HappyFace.jpg"
        }
      }
    }
  ]
}


问:
JQ: Extract value of a particular Key using pattern

In the following json:

mediainfo --Output=JSON 'Brazil.mp4' | jq '.media.track[]'
```
<pre class="lang-json prettyprint-override"><code>{
  "@type": "General",
  "VideoCount": "1",
  "AudioCount": "1",
  "FileExtension": "mp4",
  "Format": "MPEG-4",
  "Format_Profile": "Base Media",
  "CodecID": "isom",
  "CodecID_Compatible": "isom/iso2/avc1/mp41",
  "FileSize": "620542062",
  "Duration": "1531.263",
  "OverallBitRate_Mode": "VBR",
  "OverallBitRate": "3241988",
  "FrameRate": "30.000",
  "FrameCount": "45934",
  "StreamSize": "1454348",
  "HeaderSize": "40",
  "DataSize": "619584223",
  "FooterSize": "957799",
  "IsStreamable": "No",
  "File_Modified_Date": "UTC 2022-02-06 19:28:26",
  "File_Modified_Date_Local": "2022-02-06 20:28:26"
}
{
  "@type": "Video",
  "StreamOrder": "0",
  "ID": "1",
  "Format": "AVC",
  "Format_Profile": "High",
  "Format_Level": "4",
  "Format_Settings_CABAC": "Yes",
  "Format_Settings_RefFrames": "4",
  "CodecID": "avc1",
  "Duration": "1531.238",
  "Source_Duration": "1531.538",
  "BitRate": "3019356",
  "Width": "1912",
  "Width_Original": "1920",
  "Height": "1088",
  "Height_Original": "1080",
  "Stored_Height": "1088",
  "Sampled_Width": "1920",
  "Sampled_Height": "1080",
  "PixelAspectRatio": "1.000",
  "DisplayAspectRatio": "1.778",
  "Rotation": "0.000",
  "FrameRate_Mode": "VFR",
  "FrameRate": "30.000",
  "FrameRate_Minimum": "6.000",
  "FrameRate_Maximum": "120.000",
  "FrameCount": "45934",
  "ColorSpace": "YUV",
  "ChromaSubsampling": "4:2:0",
  "BitDepth": "8",
  "ScanType": "Progressive",
  "StreamSize": "577879629",
  "Source_StreamSize": "577914508",
  "Encoded_Library": "x264 - core 159",
  "Encoded_Library_Name": "x264",
  "Encoded_Library_Version": "core 159",
  "Encoded_Library_Settings": "cabac=1 / ref=3 / deblock=1:0:0 / analyse=0x3:0x113 / me=hex / subme=7 / psy=1 / psy_rd=1.00:0.00 / mixed_ref=1 / me_range=16 / chroma_me=1 / trellis=1 / 8x8dct=1 / cqm=0 / deadzone=21,11 / fast_pskip=1 / chroma_qp_offset=-2 / threads=12 / lookahead_threads=2 / sliced_threads=0 / nr=0 / decimate=1 / interlaced=0 / bluray_compat=0 / constrained_intra=0 / bframes=3 / b_pyramid=2 / b_adapt=1 / b_bias=0 / direct=1 / weightb=1 / open_gop=0 / weightp=2 / keyint=90 / keyint_min=46 / scenecut=0 / intra_refresh=0 / rc_lookahead=40 / rc=crf / mbtree=1 / crf=23.0 / qcomp=0.60 / qpmin=0 / qpmax=69 / qpstep=4 / vbv_maxrate=4000 / vbv_bufsize=133 / crf_max=27.0 / nal_hrd=none / filler=0 / ip_ratio=1.40 / aq=1:1.00",
  "extra": {
    "Source_Delay": "-67",
    "Source_Delay_Source": "Container",
    "mdhd_Duration": "1531238",
    "CodecConfigurationBox": "avcC"
  }
}
{
  "@type": "Audio",
  "StreamOrder": "1",
  "ID": "2",
  "Format": "AAC",
  "Format_AdditionalFeatures": "LC",
  "CodecID": "mp4a-40-2",
  "Duration": "1531.263",
  "BitRate_Mode": "VBR",
  "BitRate": "215289",
  "BitRate_Maximum": "427563",
  "Channels": "2",
  "ChannelPositions": "Front: L R",
  "ChannelLayout": "L R",
  "SamplesPerFrame": "1024",
  "SamplingRate": "44100",
  "SamplingCount": "67528698",
  "FrameRate": "43.066",
  "FrameCount": "65946",
  "Compression_Mode": "Lossy",
  "StreamSize": "41208085",
  "StreamSize_Proportion": "0.06641"
}
</code>```

I want to extract the duration from the json object with key @type=General. So, I did:

mediainfo --Output=JSON 'Brazil.mp4' | jq '.media.track[] | select(@type==General) | .Duration'
```
<ul>
<li>But this leads to error</li>
</ul>
<pre class="lang-sh prettyprint-override"><code>jq: error: General/0 is not defined at <top-level>, line 1:
.media.track[] | select(@type==General) | .Duration
jq: 1 compile error
</code>```

I am suspecting it is because the key begins with @. Any suggestions?

答:
You need to put quotes around both the field name (as it contains the @ character), and around the query string (as it is a string):

jq '.media.track[] | select(."@type" == "General") | .Duration'
```
```"1531.263"
```

Demo

Note: If you want to get the output as text 1531.263 rather than a JSON string "1531.263" (in quotes), then add the --raw-output or -r flag when calling jq. (Demo)

Body:
In the following json:

mediainfo --Output=JSON 'Brazil.mp4' | jq '.media.track[]'

{
  "@type": "General",
  "VideoCount": "1",
  "AudioCount": "1",
  "FileExtension": "mp4",
  "Format": "MPEG-4",
  "Format_Profile": "Base Media",
  "CodecID": "isom",
  "CodecID_Compatible": "isom/iso2/avc1/mp41",
  "FileSize": "620542062",
  "Duration": "1531.263",
  "OverallBitRate_Mode": "VBR",
  "OverallBitRate": "3241988",
  "FrameRate": "30.000",
  "FrameCount": "45934",
  "StreamSize": "1454348",
  "HeaderSize": "40",
  "DataSize": "619584223",
  "FooterSize": "957799",
  "IsStreamable": "No",
  "File_Modified_Date": "UTC 2022-02-06 19:28:26",
  "File_Modified_Date_Local": "2022-02-06 20:28:26"
}
{
  "@type": "Video",
  "StreamOrder": "0",
  "ID": "1",
  "Format": "AVC",
  "Format_Profile": "High",
  "Format_Level": "4",
  "Format_Settings_CABAC": "Yes",
  "Format_Settings_RefFrames": "4",
  "CodecID": "avc1",
  "Duration": "1531.238",
  "Source_Duration": "1531.538",
  "BitRate": "3019356",
  "Width": "1912",
  "Width_Original": "1920",
  "Height": "1088",
  "Height_Original": "1080",
  "Stored_Height": "1088",
  "Sampled_Width": "1920",
  "Sampled_Height": "1080",
  "PixelAspectRatio": "1.000",
  "DisplayAspectRatio": "1.778",
  "Rotation": "0.000",
  "FrameRate_Mode": "VFR",
  "FrameRate": "30.000",
  "FrameRate_Minimum": "6.000",
  "FrameRate_Maximum": "120.000",
  "FrameCount": "45934",
  "ColorSpace": "YUV",
  "ChromaSubsampling": "4:2:0",
  "BitDepth": "8",
  "ScanType": "Progressive",
  "StreamSize": "577879629",
  "Source_StreamSize": "577914508",
  "Encoded_Library": "x264 - core 159",
  "Encoded_Library_Name": "x264",
  "Encoded_Library_Version": "core 159",
  "Encoded_Library_Settings": "cabac=1 / ref=3 / deblock=1:0:0 / analyse=0x3:0x113 / me=hex / subme=7 / psy=1 / psy_rd=1.00:0.00 / mixed_ref=1 / me_range=16 / chroma_me=1 / trellis=1 / 8x8dct=1 / cqm=0 / deadzone=21,11 / fast_pskip=1 / chroma_qp_offset=-2 / threads=12 / lookahead_threads=2 / sliced_threads=0 / nr=0 / decimate=1 / interlaced=0 / bluray_compat=0 / constrained_intra=0 / bframes=3 / b_pyramid=2 / b_adapt=1 / b_bias=0 / direct=1 / weightb=1 / open_gop=0 / weightp=2 / keyint=90 / keyint_min=46 / scenecut=0 / intra_refresh=0 / rc_lookahead=40 / rc=crf / mbtree=1 / crf=23.0 / qcomp=0.60 / qpmin=0 / qpmax=69 / qpstep=4 / vbv_maxrate=4000 / vbv_bufsize=133 / crf_max=27.0 / nal_hrd=none / filler=0 / ip_ratio=1.40 / aq=1:1.00",
  "extra": {
    "Source_Delay": "-67",
    "Source_Delay_Source": "Container",
    "mdhd_Duration": "1531238",
    "CodecConfigurationBox": "avcC"
  }
}
{
  "@type": "Audio",
  "StreamOrder": "1",
  "ID": "2",
  "Format": "AAC",
  "Format_AdditionalFeatures": "LC",
  "CodecID": "mp4a-40-2",
  "Duration": "1531.263",
  "BitRate_Mode": "VBR",
  "BitRate": "215289",
  "BitRate_Maximum": "427563",
  "Channels": "2",
  "ChannelPositions": "Front: L R",
  "ChannelLayout": "L R",
  "SamplesPerFrame": "1024",
  "SamplingRate": "44100",
  "SamplingCount": "67528698",
  "FrameRate": "43.066",
  "FrameCount": "65946",
  "Compression_Mode": "Lossy",
  "StreamSize": "41208085",
  "StreamSize_Proportion": "0.06641"
}

I want to extract the duration from the json object with key @type=General. So, I did:

mediainfo --Output=JSON 'Brazil.mp4' | jq '.media.track[] | select(@type==General) | .Duration'

But this leads to error

jq: error: General/0 is not defined at <top-level>, line 1:
.media.track[] | select(@type==General) | .Duration
jq: 1 compile error

I am suspecting it is because the key begins with @. Any suggestions?

Body:
You need to put quotes around both the field name (as it contains the @ character), and around the query string (as it is a string):

jq '.media.track[] | select(."@type" == "General") | .Duration'

"1531.263"

Demo

Note: If you want to get the output as text 1531.263 rather than a JSON string "1531.263" (in quotes), then add the --raw-output or -r flag when calling jq. (Demo)