问:
Check if a form is valid from a parent component using Angular 4
I am trying to check the validity of a form placed on a child component from a parent component. The best scenario would be to disable a button on the parent component if the form is invalid or in the worse scenario to trigger an alert from the parent button if form is invalid.

I could achieve to check if the form has 'ng-invalid' class from the parent using a @ViewChild decorator to call a function on the child component as follows:

Parent Component:

```<code>export class CandidateVerificationComponent implements OnChanges, OnInit {

@ViewChild(RightPanelComponent) rightPanelPointer: RightPanelComponent;

saveAndFinish() {

    if (this.rightPanelPointer.checkFormValidity())
    {
        alert('No Valid');
        return;
    }

    this.rightPanelPointer.onSubmit();

  }
}
</code>```

Child Component:

```<code>export class RightPanelComponent implements OnChanges , OnInit{

@ViewChild("candiateForm", { read: ElementRef }) tref: ElementRef;

   checkFormValidity():boolean {
    return (this.tref.nativeElement.className.indexOf('ng-invalid') !== -1);
   }
}
</code>```

It works for the worst scenario, but I do not like the idea to link the component to the DOM, I would rather a smarter idea.

I would like to use a template reference variable (#candiateForm), for example the one that allows to check validity in the submit button (see below) from the form (child) in order to check validity from the parent. Is it possible to have access to that template variable from the parent?

```<code> <form (ngSubmit)="onSubmit()" #candiateForm="ngForm" name="candiateForm" (change)="formChanged()">
    <div class="form-group">
      <label class="control-label" for="firstName">First name:</label>
      <input type="text" class="form-control" id="firstName" pattern="^[^0-9]+$" required [(ngModel)]='candidate.firstName' name="firstName" #firstName="ngModel">
   </div>
<button type="submit" class="btn btn-default" [disabled]="!candiateForm.form.valid">Submit</button>
</form>
</code>```

答:
Since Angular applies ngForm to all form elements implicitly and you can reference any component/directive in the component template by component/directive class reference, you don't have to read ElementRef and don't need the template reference #candiateForm, you can access the form directly by the directive class reference ngForm:

```<code>export class RightPanelComponent implements OnChanges , OnInit{
    @ViewChild(NgForm) form;

    checkFormValidity():boolean {
        return this.form.valid;
    }
</code>```

And also you can access the form directly from the parent component:

```<code>export class CandidateVerificationComponent implements OnChanges, OnInit {
    @ViewChild(RightPanelComponent) rightPanelPointer: RightPanelComponent;

    saveAndFinish() {
        if (this.rightPanelPointer.form.valid)
</code>```

Body:
I am trying to check the validity of a form placed on a child component from a parent component. The best scenario would be to disable a button on the parent component if the form is invalid or in the worse scenario to trigger an alert from the parent button if form is invalid.

I could achieve to check if the form has 'ng-invalid' class from the parent using a @ViewChild decorator to call a function on the child component as follows:

Parent Component:

export class CandidateVerificationComponent implements OnChanges, OnInit {

@ViewChild(RightPanelComponent) rightPanelPointer: RightPanelComponent;

saveAndFinish() {

    if (this.rightPanelPointer.checkFormValidity())
    {
        alert('No Valid');
        return;
    }

    this.rightPanelPointer.onSubmit();

  }
}

Child Component:

export class RightPanelComponent implements OnChanges , OnInit{

@ViewChild("candiateForm", { read: ElementRef }) tref: ElementRef;

   checkFormValidity():boolean {
    return (this.tref.nativeElement.className.indexOf('ng-invalid') !== -1);
   }
}

It works for the worst scenario, but I do not like the idea to link the component to the DOM, I would rather a smarter idea.

I would like to use a template reference variable (#candiateForm), for example the one that allows to check validity in the submit button (see below) from the form (child) in order to check validity from the parent. Is it possible to have access to that template variable from the parent?

 <form (ngSubmit)="onSubmit()" #candiateForm="ngForm" name="candiateForm" (change)="formChanged()">

      First name:
      <input type="text" class="form-control" id="firstName" pattern="^[^0-9]+$" required [(ngModel)]='candidate.firstName' name="firstName" #firstName="ngModel">

<button type="submit" class="btn btn-default" [disabled]="!candiateForm.form.valid">Submit</button>
</form>

Body:
Since Angular applies ngForm to all form elements implicitly and you can reference any component/directive in the component template by component/directive class reference, you don't have to read ElementRef and don't need the template reference #candiateForm, you can access the form directly by the directive class reference ngForm:

export class RightPanelComponent implements OnChanges , OnInit{
    @ViewChild(NgForm) form;

    checkFormValidity():boolean {
        return this.form.valid;
    }

And also you can access the form directly from the parent component:

export class CandidateVerificationComponent implements OnChanges, OnInit {
    @ViewChild(RightPanelComponent) rightPanelPointer: RightPanelComponent;

    saveAndFinish() {
        if (this.rightPanelPointer.form.valid)


来源: stackexchange

问:
Run tests on multiple browsers (Sequentially)
I'm currently testing with Chrome(driver) only. I want to test it with Firefox and Safari too. One after the other, it cannot be in parallel.

Here's my gulp task to start the tests:

```<code>gulp.task('test', function() {
  return gulp.src('*test/features/*').pipe(cucumber({
    'steps': '*test/features/steps/*.js'
  }));
});
</code>```

A simple feature file:

```<code>Feature: UI
    Testing UI

    Scenario: Check the title of the page
        When I open the homepage
        Then I should see "Test - IntApp" in the title
</code>```

And the step file:

```<code>const chrome = require('selenium-webdriver/chrome');
const webdriver = require('selenium-webdriver');
const assert = require('assert');

module.exports = function () {
    let options = new chrome.Options();
    options.addArguments('start-maximized');

    var driver = new webdriver.Builder()
    .forBrowser('chrome')
    .setChromeOptions(options)
    .build();

    this.When('I open the homepage', function (done) {
        driver.get('http://intapp.dev/').then(done);
    });

    this.Then('I should see "Test - IntApp" in the title', function (done) {
        driver.getTitle().then(function(title) {
          assert.equal(title, "Test - IntApp");
        }).then(done);
    });

    this.registerHandler('AfterFeatures', function (features) {
        return driver.quit();
    });
};
</code>```

I was thinking that maybe I could pass the browser's name as parameter somehow from the gulp task, but it doesn't seem to be possible.

答:
Write a bash or batch script and create a setup file.

In the setup file, you can set a variable that can be changed with the script (by editing the line), and hand this over to where you declare which driver you'll be using.

This script will run them one after the other, but they will be different suites (creating different reports if you use the JSON or HTML output).

It's how I've been doing cross browser automation for a while now.

Preference would be to use bash over batch, as bash can be run on Mac, UNIX and Windows 10, but batch is primarily Windows (from memory I think it's Windows only).

If you need guidance on where to start, on request I'll give you an outline, but I should have given you enough information to research how to do it.

ContentLicense: CC BY-SA 3.0

Body:
I'm currently testing with Chrome(driver) only. I want to test it with Firefox and Safari too. One after the other, it cannot be in parallel.

Here's my gulp task to start the tests:

gulp.task('test', function() {
  return gulp.src('*test/features/*').pipe(cucumber({
    'steps': '*test/features/steps/*.js'
  }));
});

A simple feature file:

Feature: UI
    Testing UI

    Scenario: Check the title of the page
        When I open the homepage
        Then I should see "Test - IntApp" in the title

And the step file:

const chrome = require('selenium-webdriver/chrome');
const webdriver = require('selenium-webdriver');
const assert = require('assert');

module.exports = function () {
    let options = new chrome.Options();
    options.addArguments('start-maximized');

    var driver = new webdriver.Builder()
    .forBrowser('chrome')
    .setChromeOptions(options)
    .build();

    this.When('I open the homepage', function (done) {
        driver.get('http://intapp.dev/').then(done);
    });

    this.Then('I should see "Test - IntApp" in the title', function (done) {
        driver.getTitle().then(function(title) {
          assert.equal(title, "Test - IntApp");
        }).then(done);
    });

    this.registerHandler('AfterFeatures', function (features) {
        return driver.quit();
    });
};

I was thinking that maybe I could pass the browser's name as parameter somehow from the gulp task, but it doesn't seem to be possible.


问:
Python checking if string in list to list
I am having a hard time trying to understand how the "for" function works.

I want to make a script that only outputs the strings in list2 that are not inside list1. For example:

```<code>list1 = ["link1.com", "link2.com", "link3.com"]
list2 = ["link2.com", "link123.com"]

for list2 in list1:
    print(list2)
</code>```

{My intention was that the code printed:

link123.com

But instead it printed the strings from list1}

I can't get it to work. Help would be much appreciated. I am using python 3 by the way.

答:
The semantic, that python will check if these items are in list1 is NOT part of the for-each-loop.

The 'set' - solution is maybe too advanced for you.

So straightforward you would:

```<code>for item in list2:
    if item not in list1:
        print(item)
</code>```

Body:
I am having a hard time trying to understand how the "for" function works.

I want to make a script that only outputs the strings in list2 that are not inside list1. For example:

list1 = ["link1.com", "link2.com", "link3.com"]
list2 = ["link2.com", "link123.com"]

for list2 in list1:
    print(list2)

{My intention was that the code printed:

link123.com

But instead it printed the strings from list1}

I can't get it to work. Help would be much appreciated. I am using python 3 by the way.

Body:
The semantic, that python will check if these items are in list1 is NOT part of the for-each-loop.

The 'set' - solution is maybe too advanced for you.

So straightforward you would:

for item in list2:
    if item not in list1:
        print(item)


问:
TYPO3 individual query filter by another table
I have TYPO3 version 7.6.18, and  want get data with filtering by field on another relation table.

```<code>class PhotoRepository extends \TYPO3\CMS\Extbase\Persistence\Repository
{
    public function getFiltered($offset = 0, $limit = 5){
        $query = $this->createQuery();
        $query->matching($query->in('cruserId.gender', 3));
        return $query->execute();
    }
}
</code>```

Model:

```<code>class Photo extends \TYPO3\CMS\Extbase\DomainObject\AbstractEntity
{

    /**
     * CruserId
     *
     * @var \Fhk\Feusersplus\Domain\Model\User>
     */
    protected $cruserId;

    /**
     * Returns the cruserId
     *
     * @return \Fhk\Feusersplus\Domain\Model\User> $cruserId
     */
    public function getCruserId()
    {
        return $this->cruserId;
    }

    /**
     * Sets the cruserId
     *
     * @return void
     */
    public function setCruserId($cruserId)
    {
        $this->cruserId = $cruserId;
    }
}
</code>```

And my TCA:

```<code>'cruser_id' => [
    'exclude' => 1,
    'label' => 'LLL:EXT:fefiles/Resources/Private/Language/locallang_db.xlf:tx_fefiles_domain_model_photo.cruser_id',
    'config' => [
        'type' => 'group',
        'internal_type' => 'db',
        'allowed' => 'fe_users',
        'size' => 1,
        'minitems' => 0,
        'maxitems' => 1,
    ]
],
</code>```

That not works. I get error. I don't know what is this error because it not put in error log. I think may be I should write relation in ext_typoscript_setup.txt or somewhere? I think I should make reference somewhere, but I don't know

答:
Problem was in wrong TCA. The right TCA is :</p>

```<code>'cruser_id' => [
    'exclude' => 1,
    'label' => 'LLL:EXT:fefiles/Resources/Private/Language/locallang_db.xlf:tx_fefiles_domain_model_photo.cruser_id',
    'config' => [
        'type' => 'group',
        'foreign_table' => 'fe_users',
        'minitems' => 0,
        'maxitems' => 1,
        'appearance' => [
            'collapseAll' => 0,
            'levelLinksPosition' => 'top',
            'showSynchronizationLink' => 1,
            'showPossibleLocalizationRecords' => 1,
            'showAllLocalizationLink' => 1
        ],
    ]
],
</code>```

Body:
I have TYPO3 version 7.6.18, and  want get data with filtering by field on another relation table.

class PhotoRepository extends \TYPO3\CMS\Extbase\Persistence\Repository
{
    public function getFiltered($offset = 0, $limit = 5){
        $query = $this->createQuery();
        $query->matching($query->in('cruserId.gender', 3));
        return $query->execute();
    }
}

Model:

class Photo extends \TYPO3\CMS\Extbase\DomainObject\AbstractEntity
{

    /**
     * CruserId
     *
     * @var \Fhk\Feusersplus\Domain\Model\User>
     */
    protected $cruserId;

    /**
     * Returns the cruserId
     *
     * @return \Fhk\Feusersplus\Domain\Model\User> $cruserId
     */
    public function getCruserId()
    {
        return $this->cruserId;
    }

    /**
     * Sets the cruserId
     *
     * @return void
     */
    public function setCruserId($cruserId)
    {
        $this->cruserId = $cruserId;
    }
}

And my TCA:

'cruser_id' => [
    'exclude' => 1,
    'label' => 'LLL:EXT:fefiles/Resources/Private/Language/locallang_db.xlf:tx_fefiles_domain_model_photo.cruser_id',
    'config' => [
        'type' => 'group',
        'internal_type' => 'db',
        'allowed' => 'fe_users',
        'size' => 1,
        'minitems' => 0,
        'maxitems' => 1,
    ]
],

That not works. I get error. I don't know what is this error because it not put in error log. I think may be I should write relation in ext_typoscript_setup.txt or somewhere? I think I should make reference somewhere, but I don't know

Body:
Problem was in wrong TCA. The right TCA is :

'cruser_id' => [
    'exclude' => 1,
    'label' => 'LLL:EXT:fefiles/Resources/Private/Language/locallang_db.xlf:tx_fefiles_domain_model_photo.cruser_id',
    'config' => [
        'type' => 'group',
        'foreign_table' => 'fe_users',
        'minitems' => 0,
        'maxitems' => 1,
        'appearance' => [
            'collapseAll' => 0,
            'levelLinksPosition' => 'top',
            'showSynchronizationLink' => 1,
            'showPossibleLocalizationRecords' => 1,
            'showAllLocalizationLink' => 1
        ],
    ]
],


问:
MustacheJS not rendering in IE8
I have a dynamic template which I append on a div when the page loads, it is working on Chrome and some other browsers, however it doesnt work in IE8.

Any idea why it doesn't work in IE8 ?

Heres the code

```<code>var notificationDetails = {
    dangerMessage: "",
    seats: data.seatRemaining,
    class:"product-notification-danger"
};

var templates = '<div class="panel {{class}}"><button type="button" class="close" data-target="#product-notification" data-dismiss="alert"><span aria-hidden="true" style=" border: 4px solid #fff; border-radius: 50%; display: block; color: #FFFFFF; background-color: rgba(0,0,0.6); font-size: 25; width: 32px; margin-right: 5px; margin-top: 5px; ">×</span><span class="sr-only">Close</span> </button> <div class="notication"> <div class="notification-section"><img src="/media/13583871/ms-device.png" width="126" class="mCS_img_loaded"></div><div class="notification-section"><div class="panel-heading"> <span class="product-notification-title">Protect <span id="remaining-seats">{{seats}}</span> more devices.</span></div><div class="panel-body"> <p>{{dangerMessage}}</p><p><a href="#" style="color:#fff; font-size: 14px; text-transform: uppercase; font-weight: 700;">Learn More <span class="glyphicon glyphicon-circle-arrow-right"> </span></a></p></div></div></div></div>'

$('#product-notification').append(Mustache.to_html(templates, notificationDetails));
</code>```

答:
It just let the script run in my IE8.

I'd say it's simply not supported (anymore). And I also think that you don't need to support IE8. Or is there any reason to do so?

Title: MustacheJS not rendering in IE8

Body:
I have a dynamic template which I append on a div when the page loads, it is working on Chrome and some other browsers, however it doesnt work in IE8.

Any idea why it doesn't work in IE8 ?

Heres the code

var notificationDetails = {
    dangerMessage: "",
    seats: data.seatRemaining,
    class:"product-notification-danger"
};

var templates = '
<button type="button" class="close" data-target="#product-notification" data-dismiss="alert">×Close </button>

 Protect {{seats}} more devices.

{{dangerMessage}}

Learn More

'

$('#product-notification').append(Mustache.to_html(templates, notificationDetails));


问:
Can simple Java synchronized block throws Exception?
Let's say that I have this block of code inside a method:

```<code>...
synchronized (this) {
    this.var = value;
}
...
</code>```

Could there be any scenario that makes that synchronized block throws an exception (assuming this, var, and value having non null values)?

Thanks!

答:
According to the Java Language Specification about the synchronized statement :

The executing thread locks the monitor associated with V. Then the Block is executed [...]

And the Java virtual Machine Specification on Synchronization, that explains how the mentioned monitors are to be used, only talks about exceptions being thrown from within the synchronized block. So the synchronized statement itself isn't permitted to throw an exceptions.

So there can't be any scenario in your case where an exception gets thrown.

Body:
Let's say that I have this block of code inside a method:

...
synchronized (this) {
    this.var = value;
}
...

Could there be any scenario that makes that synchronized block throws an exception (assuming this, var, and value having non null values)?

Thanks!


问:
Android Tabbed Activity Searchview not opening in Toolbar
the problem

I've used the Setting Up The Search interface doc from the official Android documentation but I'm not getting far for some strange reason as the SearchView refuses to open in the Toolbar
cfr. Android docs

the code

I've added the menu item as such:

<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    tools:context="...">

    <item
        android:id="@+id/action_search"
        android:title="@string/action_search"
        android:icon="@android:drawable/ic_menu_search"
        app:showAsAction="collapseActionView|ifRoom"
        android:actionViewClass="android.widget.SearchView"/>
</menu>
```

<p>(Sidenote, I've also tried the v7 <code>SearchView</code> view class, but result is no different)
<br /><br /><br />
This is how the toolbar is laid out</p>

<pre class="lang-xml prettyprint-override"><code><android.support.design.widget.AppBarLayout
    android:id="@+id/appbar"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:paddingTop="@dimen/appbar_padding_top"
    android:theme="@style/AppTheme.AppBarOverlay">

    <android.support.v7.widget.Toolbar
        app:theme="@style/AppTheme.Toolbar"
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="?attr/colorPrimary"
        app:layout_scrollFlags="scroll|enterAlways"
        app:popupTheme="@style/AppTheme.PopupOverlay">
    </android.support.v7.widget.Toolbar>

</android.support.design.widget.AppBarLayout>
</code>```

I have also added the SEARCH intent in the manifest and the menu gets properly inflated in the onCreateOptionsMenu method.

edit, manifest.xml and searchable.xml
Added these by request although I don't believe they are relevant to the issue.

<activity
    android:name=".HomeActivity"
    android:label="@string/app_name"
    android:theme="@style/AppTheme.NoActionBar">
    <meta-data
        android:name="android.app.searchable"
        android:resource="@xml/searchable" />
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <action android:name="android.intent.action.VIEW" />
        <action android:name="android.intent.action.SEND" />
        <action android:name="android.intent.action.SEARCH" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>
```

<p>Searchable.xml
</p>

```<?xml version="1.0" encoding="utf-8"?>
<searchable xmlns:android="http://schemas.android.com/apk/res/android"
    android:label="@string/app_name"
    android:hint="" />
```

Now according to the Android doc the SearchView is supposed to show up but when I press the search icon in the Toolbar nothing happens.

Any ideas what could be wrong?

答:
Use menu item as such "android.support.v7.widget.SearchView"</p>

```<code><item
    android:id="@+id/action_search"
    android:icon="@drawable/ic_search"
    android:title="@string/lbl_search"
    app:actionViewClass="android.support.v7.widget.SearchView"
    app:showAsAction="ifRoom" />
</code>```

Body:
the problem

I've used the Setting Up The Search interface doc from the official Android documentation but I'm not getting far for some strange reason as the SearchView refuses to open in the Toolbar
cfr. Android docs

the code

I've added the menu item as such:

<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    tools:context="...">

    <item
        android:id="@+id/action_search"
        android:title="@string/action_search"
        android:icon="@android:drawable/ic_menu_search"
        app:showAsAction="collapseActionView|ifRoom"
        android:actionViewClass="android.widget.SearchView"/>
</menu>

(Sidenote, I've also tried the v7 SearchView view class, but result is no different)

This is how the toolbar is laid out

<android.support.design.widget.AppBarLayout
    android:id="@+id/appbar"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:paddingTop="@dimen/appbar_padding_top"
    android:theme="@style/AppTheme.AppBarOverlay">

    <android.support.v7.widget.Toolbar
        app:theme="@style/AppTheme.Toolbar"
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="?attr/colorPrimary"
        app:layout_scrollFlags="scroll|enterAlways"
        app:popupTheme="@style/AppTheme.PopupOverlay">
    </android.support.v7.widget.Toolbar>

</android.support.design.widget.AppBarLayout>

I have also added the SEARCH intent in the manifest and the menu gets properly inflated in the onCreateOptionsMenu method.

edit, manifest.xml and searchable.xml
Added these by request although I don't believe they are relevant to the issue.

<activity
    android:name=".HomeActivity"
    android:label="@string/app_name"
    android:theme="@style/AppTheme.NoActionBar">
    <meta-data
        android:name="android.app.searchable"
        android:resource="@xml/searchable" />
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <action android:name="android.intent.action.VIEW" />
        <action android:name="android.intent.action.SEND" />
        <action android:name="android.intent.action.SEARCH" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>

Searchable.xml

<?xml version="1.0" encoding="utf-8"?>
<searchable xmlns:android="http://schemas.android.com/apk/res/android"
    android:label="@string/app_name"
    android:hint="" />

Now according to the Android doc the SearchView is supposed to show up but when I press the search icon in the Toolbar nothing happens.

Any ideas what could be wrong?

Body:
Use menu item as such "android.support.v7.widget.SearchView"

<item
    android:id="@+id/action_search"
    android:icon="@drawable/ic_search"
    android:title="@string/lbl_search"
    app:actionViewClass="android.support.v7.widget.SearchView"
    app:showAsAction="ifRoom" />


问:
$env:homedrive is lost occasionally
I use $env:homedrive in my scripts in Azure's CustomScriptExtension.
Strangely sometimes I got blank from this variable but sometimes OK.

Is this environment variable not reliable?

答:
It's difficult to say without looking at the script. But you can put a $null condition check before proceeding.

```<code>if($env:HOMEDRIVE -eq $null){
  $env:HOMEDRIVE = "H:" # Whatever you want
}
else{
  Do-WhatYouWant
}
</code>```

Alternative you can set $env:HOMEDRIVE directly to your desired location at the beginning of the script or function. But still, I would prefer to put the $null check condition always.
@Dave Wu

Title: $env:homedrive is lost occasionally

Body:
It's difficult to say without looking at the script. But you can put a $null condition check before proceeding.

if($env:HOMEDRIVE -eq $null){
  $env:HOMEDRIVE = "H:" # Whatever you want
}
else{
  Do-WhatYouWant
}

Alternative you can set $env:HOMEDRIVE directly to your desired location at the beginning of the script or function. But still, I would prefer to put the $null check condition always.
@Dave Wu


问:
Is it possible to use React.js in React-Native?
Using React-Native, I'll make Native app. But I don't know anything about it.
So, I am going to buy some books about React-Native.
If It is possible to use React.js in React-Native, then I will buy the book about React.js .

Is it possible?

ps. Do you know some links or website about React-Native? Please Share!

答:
React-Native uses the same syntax as React.js. You have to use React in order to use RN, but the functions, methods and components are not the same. (There is no , no documentElement or anything else).

You should take a look at the Fabebook documentation for React & RN:

https://facebook.github.io/react-native/

https://facebook.github.io/react/


问:
HTML5 canvas with freehand line drawing
I am a new learner of canvas in HTML5, and currently trying to make a simple draw line project for kids. I inserted background images into canvas, and try to come up with a freehand line drawing method but up  to no result. Can someone help me fix my below code? Thank you all before. </p>

```<code><!DOCTYPE HTML>
<html>
    <script type="text/javascript">
    var canvas, ctx, flag = false,
        prevX = 0,
        currX = 0,
        prevY = 0,
        currY = 0,
        dot_flag = false;

    var x = "black",
        y = 2;

    function init() {
        canvas = document.getElementById('can');
        ctx = canvas.getContext("2d");
        w = canvas.width;
        h = canvas.height;

        canvas.addEventListener("mousemove", function (e) {
            findxy('move', e)
        }, false);
        canvas.addEventListener("mousedown", function (e) {
            findxy('down', e)
        }, false);
        canvas.addEventListener("mouseup", function (e) {
            findxy('up', e)
        }, false);
        canvas.addEventListener("mouseout", function (e) {
            findxy('out', e)
        }, false);
    }

    function color(obj) {
        switch (obj.id) {
            case "green":
                x = "green";
                break;
            case "blue":
                x = "blue";
                break;
            case "red":
                x = "red";
                break;
            case "yellow":
                x = "yellow";
                break;
            case "orange":
                x = "orange";
                break;
            case "black":
                x = "black";
                break;
            case "white":
                x = "white";
                break;
        }
        if (x == "white") y = 14;
        else y = 2;

    }

    function draw() {
        ctx.beginPath();
        ctx.moveTo(prevX, prevY);
        ctx.lineTo(currX, currY);
        ctx.strokeStyle = x;
        ctx.lineWidth = y;
        ctx.stroke();
        ctx.closePath();
    }

    function erase() {
        var m = confirm("Want to clear");
        if (m) {
            ctx.clearRect(0, 0, w, h);
            document.getElementById("canvasimg").style.display = "none";
        }
    }

    function save() {
        document.getElementById("canvasimg").style.border = "2px solid";
        var dataURL = canvas.toDataURL();
        document.getElementById("canvasimg").src = dataURL;
        document.getElementById("canvasimg").style.display = "inline";
    }

    function findxy(res, e) {
        if (res == 'down') {
            prevX = currX;
            prevY = currY;
            currX = e.clientX - canvas.offsetLeft;
            currY = e.clientY - canvas.offsetTop;

            flag = true;
            dot_flag = true;
            if (dot_flag) {
                ctx.beginPath();
                ctx.fillStyle = x;
                ctx.fillRect(currX, currY, 2, 2);
                ctx.closePath();
                dot_flag = false;
            }
        }
        if (res == 'up' || res == "out") {
            flag = false;
        }
        if (res == 'move') {
            if (flag) {
                prevX = currX;
                prevY = currY;
                currX = e.clientX - canvas.offsetLeft;
                currY = e.clientY - canvas.offsetTop;
                draw();
            }
        }
    }
    </script>
    <body onload="init()" style="background-image: src=c:/WebProgram/Pictures/test1.png;">
        <canvas id="can" width="520" height="700" style="position:absolute;top:10%;left:10%;border:2px solid;"></canvas>
        <div style="position:absolute;top:12%;left:43%;">Choose Color</div>
        <div style="position:absolute;top:15%;left:45%;width:10px;height:10px;background:green;" id="green" onclick="color(this)"></div>
        <div style="position:absolute;top:15%;left:46%;width:10px;height:10px;background:blue;" id="blue" onclick="color(this)"></div>
        <div style="position:absolute;top:15%;left:47%;width:10px;height:10px;background:red;" id="red" onclick="color(this)"></div>
        <div style="position:absolute;top:17%;left:45%;width:10px;height:10px;background:yellow;" id="yellow" onclick="color(this)"></div>
        <div style="position:absolute;top:17%;left:46%;width:10px;height:10px;background:orange;" id="orange" onclick="color(this)"></div>
        <div style="position:absolute;top:17%;left:47%;width:10px;height:10px;background:black;" id="black" onclick="color(this)"></div>
        <div style="position:absolute;top:20%;left:43%;">Eraser</div>
        <div style="position:absolute;top:22%;left:45%;width:15px;height:15px;background:white;border:2px solid;" id="white" onclick="color(this)"></div>
        <img id="canvasimg" style="position:absolute;top:10%;left:52%;" style="display:none;">
        <input type="button" value="save" id="btn" size="30" onclick="save()" style="position:absolute;top:5%;left:10%;">
        <input type="button" value="clear" id="clr" size="23" onclick="erase()" style="position:absolute;top:5%;left:15%;">
    </body>
</html>
</code>```

答:
Creating a canvas based drawing app.

There is not that much to a drawing app. Listen to the mouse, when the button is down draw at the mouse position.

If you want to have a responsive canvas and also include undos and more then you need to start at a slightly more complex level.

Drawing and display.

First you should separate the drawing from the display. This is done by creating an offscreen canvas that holds the drawing. Its size is constant and can be panned and zoomed (even rotated) by the user.

Having an offscreen canvas to hold the drawing also lets you draw over the drawing if you are creating lines or boxes.

Some functions to aid in creating a canvas

```<code>function createCanvas(width, height) {
  const c = document.createElement("canvas");
  c.width = width;
  c.height = height;
  c.ctx = c.getContext("2d");
  return c;
}
const drawing = createCanvas(512,512);
</code>```

You can draw that canvas to the display canvas with

```<code>ctx.drawImage(drawing,0,0);
</code>```

The snippet draws the drawing in the center of the canvas with a shadow and border to look nice.

The mouse handler

It is important that you do the mouse interface correctly. Listening to the mouse events from the canvas has some problems. When the user drags off of the canvas you no longer get any mouse events. This means that when the mouse leaves the canvas you need to stop drawing as you don't know if the mouse is still down when it returns.

To solve this problem you listen to the document's mouse events. This will capture the mouse when a button is down, allowing the user to move the mouse anywhere on the screen while you still get the events. If the mouse goes up while off the canvas you still get that event.

NOTE the stack overflow snippet window prevents mouse capture ATM (a recent change) so the above mouse behaviour is restricted to the iFrame containing the snippet.

You should also never do any rendering from mouse events. Some rendering operations can be slow, much slower than the update speed of the mouse. If you render from the mouse events you will lose mouse events. Always do the minimum possible code inside mouse event listeners.

In the snippet the mouse event only records the current mouse state and if the mouse is down and drawing it will record the path the mouse creates. A separate loop that is synced to the display refresh rate via the function call requestAnimationFrame is responsible for rendering content. It runs at about 60fps. To stop it from drawing when nothing is happening a flag is used to indicate that the display needs updating updateDisplay When there are changes you set that to true updateDisplay=true; and the next time the display hardware is ready to display a frame it will draw all the updated content.

Drawing a line

A line is just a set of connected points. In the snippet I create a line object. It holds the points that make up the line and the line width and color.

When the mouse is down I create a new line object and start adding points to it. I flag that the display needs updating and in the display loop I draw the line on the display canvas via its draw method.

When the mouse moves up, then I draw the line on the drawing canvas. Doing it this way lets you apply some smarts to the line (snippet is simple and does nothing to the line), for example making it fade out along its length. You will only know its length when the mouse is up.

In the snippet I discard the line when the mouse is up, but if you wanted to have undos you would save each line drawn in an array. To undo you just clear the drawing and redraw all the lines except for the undone line.

The line object and associated code.

```<code>// a point object creates point from x,y coords or object that has x,y
const point = (x, y = x.y + ((x = x.x) * 0)) => ({ x, y });

// function to add a point to the line
function addPoint(x, y) { this.points.push(point(x, y)); }

// draw a line on context ctx and adds offset.x, offset.y
function drawLine(ctx, offset) {
  ctx.strokeStyle = this.color;
  ctx.lineWidth = this.width;
  ctx.lineJoin = "round";
  ctx.lineCap = "round";
  ctx.beginPath();
  var i = 0;
  while (i < this.points.length) {
    const p = this.points[i++];
    ctx.lineTo(p.x + offset.x, p.y + offset.y);
  }
  ctx.stroke();
}
// creates a new line object
function createLine(color, width) {
  return {
    points: [], // the points making up the line
    color,      // colour of the line
    width,      // width of the line
    add: addPoint,  // function to add a point
    draw: drawLine,  // function to draw the whole line
  };
}
</code>```

Example snippet

The snippet turned out a little longer than I wanted. I have added comments for relevant code but if you have any question please do ask in the comments and I will update the answer with more information.

// size of drawing and its starting background colour
const drawingInfo = {
  width: 384 ,
  height: 160,
  bgColor: "white",
}
const brushSizes = [1, 2, 3, 4, 5, 6, 7, 8];
const colors = "red,orange,yellow,green,cyan,blue,purple,white,gray,black".split(",");
var currentColor = "blue";
var currentWidth = 2;
var currentSelectBrush;
var currentSelectColor;
const colorSel = document.getElementById("colorSel");
colors.forEach((color, i) => {
  var swatch = document.createElement("span");
  swatch.className = "swatch";
  swatch.style.backgroundColor = color;
  if (currentColor === color) {
    swatch.className = "swatch highlight";
    currentSelectColor = swatch;
  } else {
    swatch.className = "swatch";
  }
  swatch.addEventListener("click", (e) => {
    currentSelectColor.className = "swatch";
    currentColor = e.target.style.backgroundColor;
    currentSelectColor = e.target;
    currentSelectColor.className = "swatch highlight";
  });
  colorSel.appendChild(swatch);
})
brushSizes.forEach((brushSize, i) => {
  var brush = document.createElement("canvas");
  brush.width = 16;
  brush.height = 16;
  brush.ctx = brush.getContext("2d");
  brush.ctx.beginPath();
  brush.ctx.arc(8, 8, brushSize / 2, 0, Math.PI * 2);
  brush.ctx.fill();
  brush.brushSize = brushSize;
  if (currentWidth === brushSize) {
    brush.className = "swatch highlight";
    currentSelectBrush = brush;
  } else {
    brush.className = "swatch";
  }

  brush.addEventListener("click", (e) => {
    currentSelectBrush.className = "swatch";
    currentSelectBrush = e.target;
    currentSelectBrush.className = "swatch highlight";
    currentWidth = e.target.brushSize;

  });
  colorSel.appendChild(brush);
})

const canvas = document.getElementById("can");
const mouse = createMouse().start(canvas, true);
const ctx = canvas.getContext("2d");
var updateDisplay = true; // when true the display needs updating
var ch, cw, w, h; // global canvas size vars

var currentLine;

var displayOffset = {
  x: 0,
  y: 0
};

// a point object creates point from x,y coords or object that has x,y
const point = (x, y = x.y + ((x = x.x) * 0)) => ({
  x,
  y
});
// function to add a point to the line
function addPoint(x, y) {
  this.points.push(point(x, y));
}

function drawLine(ctx, offset) { // draws a line
  ctx.strokeStyle = this.color;
  ctx.lineWidth = this.width;
  ctx.lineJoin = "round";
  ctx.lineCap = "round";
  ctx.beginPath();
  var i = 0;
  while (i < this.points.length) {
    const p = this.points[i++];
    ctx.lineTo(p.x + offset.x, p.y + offset.y);
  }
  ctx.stroke();
}

function createLine(color, width) {
  return {
    points: [],
    color,
    width,
    add: addPoint,
    draw: drawLine,
  };
}

// creates a canvas
function createCanvas(width, height) {
  const c = document.createElement("canvas");
  c.width = width;
  c.height = height;
  c.ctx = c.getContext("2d");
  return c;
}
// resize main display canvas and set global size vars
function resizeCanvas() {
  ch = ((h = canvas.height = innerHeight - 32) / 2) | 0;
  cw = ((w = canvas.width = innerWidth) / 2) | 0;
  updateDisplay = true;
}

function createMouse() {
  function preventDefault(e) { e.preventDefault() }
  const mouse = {
    x: 0,
    y: 0,
    buttonRaw: 0,
    prevButton: 0
  };
  const bm = [1, 2, 4, 6, 5, 3]; // bit masks for mouse buttons
  const mouseEvents = "mousemove,mousedown,mouseup".split(",");
  const m = mouse;
  // one mouse handler
  function mouseMove(e) {
    m.bounds = m.element.getBoundingClientRect();
    m.x = e.pageX - m.bounds.left - scrollX;
    m.y = e.pageY - m.bounds.top - scrollY;

    if (e.type === "mousedown") {
      m.buttonRaw |= bm[e.which - 1];
    } else if (e.type === "mouseup") {
      m.buttonRaw &= bm[e.which + 2];
    }
    // check if there should be a display update
    if (m.buttonRaw || m.buttonRaw !== m.prevButton) {
      updateDisplay = true;
    }
    // if the mouse is down and the prev mouse is up then start a new line
    if (m.buttonRaw !== 0 && m.prevButton === 0) { // starting new line
      currentLine = createLine(currentColor, currentWidth);
      currentLine.add(m); // add current mouse position
    } else if (m.buttonRaw !== 0 && m.prevButton !== 0) { // while mouse is down
      currentLine.add(m); // add current mouse position
    }
    m.prevButton = m.buttonRaw; // remember the previous mouse state
    e.preventDefault();
  }
  // starts the mouse
  m.start = function(element, blockContextMenu) {
    m.element = element;

    mouseEvents.forEach(n => document.addEventListener(n, mouseMove));
    if (blockContextMenu === true) {
      document.addEventListener("contextmenu", preventDefault)
    }
    return m
  }
  return m;
}
var cursor = "crosshair";
function update(timer) { // Main update loop
  cursor = "crosshair";
  globalTime = timer;
  // if the window size has changed resize the canvas
  if (w !== innerWidth || h !== innerHeight) {
    resizeCanvas()
  }
  if (updateDisplay) {
    updateDisplay = false;
    display(); // call demo code
  }

  ctx.canvas.style.cursor = cursor;
  requestAnimationFrame(update);
}
// create a drawing canvas.
const drawing = createCanvas(drawingInfo.width, drawingInfo.height);
// fill with white
drawing.ctx.fillStyle = drawingInfo.bgColor;
drawing.ctx.fillRect(0, 0, drawing.width, drawing.height);

// function to display drawing
function display() {
  ctx.clearRect(0, 0, w, h);
  ctx.fillStyle = "rgba(0,0,0,0.25)";
  const imgX = cw - (drawing.width / 2) | 0;
  const imgY = ch - (drawing.height / 2) | 0;
  // add a shadow to make it look nice
  ctx.fillRect(imgX + 5, imgY + 5, drawing.width, drawing.height);

  // add outline
  ctx.strokeStyle = "black";
  ctx.lineWidth = "2";
  ctx.strokeRect(imgX, imgY, drawing.width, drawing.height);
  // draw the image
  ctx.drawImage(drawing, imgX, imgY);
  if (mouse.buttonRaw !== 0) {
    if (currentLine !== undefined) {
      currentLine.draw(ctx, displayOffset); // draw line on display canvas
      cursor = "none";
      updateDisplay = true; // keep updating
    }
  } else if (mouse.buttonRaw === 0) {
    if (currentLine !== undefined) {
      currentLine.draw(drawing.ctx, {x: -imgX, y: -imgY }); // draw line on drawing
      currentLine = undefined;
      updateDisplay = true;
      // next line is a quick fix to stop a slight flicker due to the current frame not showing the line
      ctx.drawImage(drawing, imgX, imgY);

    }
  }
}

requestAnimationFrame(update);```
<pre class="snippet-code-css lang-css prettyprint-override"><code>#can {
  position: absolute;
  top: 32px;
  left: 0px;
  background-color: #AAA;
}

.colors {
  border: 1px solid black;
  display: inline-flex;
}

.swatch {
  min-width: 16px;
  min-height: 16px;
  max-width: 16px;
  border: 1px solid black;
  display: inline-block;
  margin: 2px;
  cursor: pointer;

}

.highlight {
  border: 1px solid red;
}</code>```

<canvas id="can"></canvas>

```
</div>
</div>
</p>

<p><strong>Update</strong> In response to the comment by the OP I have added a HTML version that you should be able to copy and paste (everything and including  <code><!DOCTYPE HTML></code> to <code></HTML></code>) into a html document (eg drawing.html) and then open in a browser that supports ES6. eg Chrome, Firefox, Edge. </p>

<p>Copy content of snippet below.</p>

<p><div class="snippet" data-lang="js" data-hide="true" data-console="false" data-babel="false">
<div class="snippet-code snippet-currently-hidden">
<pre class="snippet-code-html lang-html prettyprint-override"><code><!DOCTYPE HTML>
<html>
<head>
    <style>
#can {
  position: absolute;
  top: 32px;
  left: 0px;
  background-color: #AAA;
}

.colors {
  border: 1px solid black;
  display: inline-flex;
}

.swatch {
  min-width: 16px;
  min-height: 16px;
  max-width: 16px;
  border: 1px solid black;
  display: inline-block;
  margin: 2px;
  cursor: pointer;

}

.highlight {
  border: 1px solid red;
}
    </style>
</head>

<body>
    <canvas id="can"></canvas>
    <div class="colors" id="colorSel"></div>

<script>
// size of drawing and its starting background colour
const drawingInfo = {
  width: 384 ,
  height: 160,
  bgColor: "white",
}
const brushSizes = [1, 2, 3, 4, 5, 6, 7, 8];
const colors = "red,orange,yellow,green,cyan,blue,purple,white,gray,black".split(",");
var currentColor = "blue";
var currentWidth = 2;
var currentSelectBrush;
var currentSelectColor;
const colorSel = document.getElementById("colorSel");
colors.forEach((color, i) => {
  var swatch = document.createElement("span");
  swatch.className = "swatch";
  swatch.style.backgroundColor = color;
  if (currentColor === color) {
    swatch.className = "swatch highlight";
    currentSelectColor = swatch;
  } else {
    swatch.className = "swatch";
  }
  swatch.addEventListener("click", (e) => {
    currentSelectColor.className = "swatch";
    currentColor = e.target.style.backgroundColor;
    currentSelectColor = e.target;
    currentSelectColor.className = "swatch highlight";
  });
  colorSel.appendChild(swatch);
})
brushSizes.forEach((brushSize, i) => {
  var brush = document.createElement("canvas");
  brush.width = 16;
  brush.height = 16;
  brush.ctx = brush.getContext("2d");
  brush.ctx.beginPath();
  brush.ctx.arc(8, 8, brushSize / 2, 0, Math.PI * 2);
  brush.ctx.fill();
  brush.brushSize = brushSize;
  if (currentWidth === brushSize) {
    brush.className = "swatch highlight";
    currentSelectBrush = brush;
  } else {
    brush.className = "swatch";
  }

  brush.addEventListener("click", (e) => {
    currentSelectBrush.className = "swatch";
    currentSelectBrush = e.target;
    currentSelectBrush.className = "swatch highlight";
    currentWidth = e.target.brushSize;

  });
  colorSel.appendChild(brush);
})

const canvas = document.getElementById("can");
const mouse = createMouse().start(canvas, true);
const ctx = canvas.getContext("2d");
var updateDisplay = true; // when true the display needs updating
var ch, cw, w, h; // global canvas size vars

var currentLine;

var displayOffset = {
  x: 0,
  y: 0
};

// a point object creates point from x,y coords or object that has x,y
const point = (x, y = x.y + ((x = x.x) * 0)) => ({
  x,
  y
});
// function to add a point to the line
function addPoint(x, y) {
  this.points.push(point(x, y));
}

function drawLine(ctx, offset) { // draws a line
  ctx.strokeStyle = this.color;
  ctx.lineWidth = this.width;
  ctx.lineJoin = "round";
  ctx.lineCap = "round";
  ctx.beginPath();
  var i = 0;
  while (i < this.points.length) {
    const p = this.points[i++];
    ctx.lineTo(p.x + offset.x, p.y + offset.y);
  }
  ctx.stroke();
}

function createLine(color, width) {
  return {
    points: [],
    color,
    width,
    add: addPoint,
    draw: drawLine,
  };
}

// creates a canvas
function createCanvas(width, height) {
  const c = document.createElement("canvas");
  c.width = width;
  c.height = height;
  c.ctx = c.getContext("2d");
  return c;
}
// resize main display canvas and set global size vars
function resizeCanvas() {
  ch = ((h = canvas.height = innerHeight - 32) / 2) | 0;
  cw = ((w = canvas.width = innerWidth) / 2) | 0;
  updateDisplay = true;
}

function createMouse() {
  function preventDefault(e) { e.preventDefault() }
  const mouse = {
    x: 0,
    y: 0,
    buttonRaw: 0,
    prevButton: 0
  };
  const bm = [1, 2, 4, 6, 5, 3]; // bit masks for mouse buttons
  const mouseEvents = "mousemove,mousedown,mouseup".split(",");
  const m = mouse;
  // one mouse handler
  function mouseMove(e) {
    m.bounds = m.element.getBoundingClientRect();
    m.x = e.pageX - m.bounds.left - scrollX;
    m.y = e.pageY - m.bounds.top - scrollY;

    if (e.type === "mousedown") {
      m.buttonRaw |= bm[e.which - 1];
    } else if (e.type === "mouseup") {
      m.buttonRaw &= bm[e.which + 2];
    }
    // check if there should be a display update
    if (m.buttonRaw || m.buttonRaw !== m.prevButton) {
      updateDisplay = true;
    }
    // if the mouse is down and the prev mouse is up then start a new line
    if (m.buttonRaw !== 0 && m.prevButton === 0) { // starting new line
      currentLine = createLine(currentColor, currentWidth);
      currentLine.add(m); // add current mouse position
    } else if (m.buttonRaw !== 0 && m.prevButton !== 0) { // while mouse is down
      currentLine.add(m); // add current mouse position
    }
    m.prevButton = m.buttonRaw; // remember the previous mouse state
    e.preventDefault();
  }
  // starts the mouse
  m.start = function(element, blockContextMenu) {
    m.element = element;

    mouseEvents.forEach(n => document.addEventListener(n, mouseMove));
    if (blockContextMenu === true) {
      document.addEventListener("contextmenu", preventDefault)
    }
    return m
  }
  return m;
}
var cursor = "crosshair";
function update(timer) { // Main update loop
  cursor = "crosshair";
  globalTime = timer;
  // if the window size has changed resize the canvas
  if (w !== innerWidth || h !== innerHeight) {
    resizeCanvas()
  }
  if (updateDisplay) {
    updateDisplay = false;
    display(); // call demo code
  }

  ctx.canvas.style.cursor = cursor;
  requestAnimationFrame(update);
}
// create a drawing canvas.
const drawing = createCanvas(drawingInfo.width, drawingInfo.height);
// fill with white
drawing.ctx.fillStyle = drawingInfo.bgColor;
drawing.ctx.fillRect(0, 0, drawing.width, drawing.height);

// function to display drawing
function display() {
  ctx.clearRect(0, 0, w, h);
  ctx.fillStyle = "rgba(0,0,0,0.25)";
  const imgX = cw - (drawing.width / 2) | 0;
  const imgY = ch - (drawing.height / 2) | 0;
  // add a shadow to make it look nice
  ctx.fillRect(imgX + 5, imgY + 5, drawing.width, drawing.height);

  // add outline
  ctx.strokeStyle = "black";
  ctx.lineWidth = "2";
  ctx.strokeRect(imgX, imgY, drawing.width, drawing.height);
  // draw the image
  ctx.drawImage(drawing, imgX, imgY);
  if (mouse.buttonRaw !== 0) {
    if (currentLine !== undefined) {
      currentLine.draw(ctx, displayOffset); // draw line on display canvas
      cursor = "none";
      updateDisplay = true; // keep updating
    }
  } else if (mouse.buttonRaw === 0) {
    if (currentLine !== undefined) {
      currentLine.draw(drawing.ctx, {x: -imgX, y: -imgY }); // draw line on drawing
      currentLine = undefined;
      updateDisplay = true;
      // next line is a quick fix to stop a slight flicker due to the current frame not showing the line
      ctx.drawImage(drawing, imgX, imgY);

    }
  }
}

requestAnimationFrame(update);

/* load and add image to the drawing. It may take time to load. */
function loadImage(url){
    const image = new Image();
    image.src = url;
    image.onload = function(){
        if(drawing && drawing.ctx){
            drawing.width = image.width;
            drawing.height = image.height;
            drawing.ctx.drawImage(image,0,0);
        };
    }

 }
 loadImage("https://i.stack.imgur.com/C7qq2.png?s=328&g=1");

</script>

</body>
</html></code>```

Title: HTML5 canvas with freehand line drawing

Body:
I am a new learner of canvas in HTML5, and currently trying to make a simple draw line project for kids. I inserted background images into canvas, and try to come up with a freehand line drawing method but up  to no result. Can someone help me fix my below code? Thank you all before.

<!DOCTYPE HTML>

        <canvas id="can" width="520" height="700" style="position:absolute;top:10%;left:10%;border:2px solid;"></canvas>

Choose Color

Eraser

        <input type="button" value="save" id="btn" size="30" onclick="save()" style="position:absolute;top:5%;left:10%;">
        <input type="button" value="clear" id="clr" size="23" onclick="erase()" style="position:absolute;top:5%;left:15%;">

Body:
Creating a canvas based drawing app.

There is not that much to a drawing app. Listen to the mouse, when the button is down draw at the mouse position.

If you want to have a responsive canvas and also include undos and more then you need to start at a slightly more complex level.

Drawing and display.

First you should separate the drawing from the display. This is done by creating an offscreen canvas that holds the drawing. Its size is constant and can be panned and zoomed (even rotated) by the user.

Having an offscreen canvas to hold the drawing also lets you draw over the drawing if you are creating lines or boxes.

Some functions to aid in creating a canvas

function createCanvas(width, height) {
  const c = document.createElement("canvas");
  c.width = width;
  c.height = height;
  c.ctx = c.getContext("2d");
  return c;
}
const drawing = createCanvas(512,512);

You can draw that canvas to the display canvas with

ctx.drawImage(drawing,0,0);

The snippet draws the drawing in the center of the canvas with a shadow and border to look nice.

The mouse handler

It is important that you do the mouse interface correctly. Listening to the mouse events from the canvas has some problems. When the user drags off of the canvas you no longer get any mouse events. This means that when the mouse leaves the canvas you need to stop drawing as you don't know if the mouse is still down when it returns.

To solve this problem you listen to the document's mouse events. This will capture the mouse when a button is down, allowing the user to move the mouse anywhere on the screen while you still get the events. If the mouse goes up while off the canvas you still get that event.

NOTE the stack overflow snippet window prevents mouse capture ATM (a recent change) so the above mouse behaviour is restricted to the iFrame containing the snippet.

You should also never do any rendering from mouse events. Some rendering operations can be slow, much slower than the update speed of the mouse. If you render from the mouse events you will lose mouse events. Always do the minimum possible code inside mouse event listeners.

In the snippet the mouse event only records the current mouse state and if the mouse is down and drawing it will record the path the mouse creates. A separate loop that is synced to the display refresh rate via the function call requestAnimationFrame is responsible for rendering content. It runs at about 60fps. To stop it from drawing when nothing is happening a flag is used to indicate that the display needs updating updateDisplay When there are changes you set that to true updateDisplay=true; and the next time the display hardware is ready to display a frame it will draw all the updated content.

Drawing a line

A line is just a set of connected points. In the snippet I create a line object. It holds the points that make up the line and the line width and color.

When the mouse is down I create a new line object and start adding points to it. I flag that the display needs updating and in the display loop I draw the line on the display canvas via its draw method.

When the mouse moves up, then I draw the line on the drawing canvas. Doing it this way lets you apply some smarts to the line (snippet is simple and does nothing to the line), for example making it fade out along its length. You will only know its length when the mouse is up.

In the snippet I discard the line when the mouse is up, but if you wanted to have undos you would save each line drawn in an array. To undo you just clear the drawing and redraw all the lines except for the undone line.

The line object and associated code.

// a point object creates point from x,y coords or object that has x,y
const point = (x, y = x.y + ((x = x.x) * 0)) => ({ x, y });

// function to add a point to the line
function addPoint(x, y) { this.points.push(point(x, y)); }

// draw a line on context ctx and adds offset.x, offset.y
function drawLine(ctx, offset) {
  ctx.strokeStyle = this.color;
  ctx.lineWidth = this.width;
  ctx.lineJoin = "round";
  ctx.lineCap = "round";
  ctx.beginPath();
  var i = 0;
  while (i < this.points.length) {
    const p = this.points[i++];
    ctx.lineTo(p.x + offset.x, p.y + offset.y);
  }
  ctx.stroke();
}
// creates a new line object
function createLine(color, width) {
  return {
    points: [], // the points making up the line
    color,      // colour of the line
    width,      // width of the line
    add: addPoint,  // function to add a point
    draw: drawLine,  // function to draw the whole line
  };
}

Example snippet

The snippet turned out a little longer than I wanted. I have added comments for relevant code but if you have any question please do ask in the comments and I will update the answer with more information.

// size of drawing and its starting background colour
const drawingInfo = {
  width: 384 ,
  height: 160,
  bgColor: "white",
}
const brushSizes = [1, 2, 3, 4, 5, 6, 7, 8];
const colors = "red,orange,yellow,green,cyan,blue,purple,white,gray,black".split(",");
var currentColor = "blue";
var currentWidth = 2;
var currentSelectBrush;
var currentSelectColor;
const colorSel = document.getElementById("colorSel");
colors.forEach((color, i) => {
  var swatch = document.createElement("span");
  swatch.className = "swatch";
  swatch.style.backgroundColor = color;
  if (currentColor === color) {
    swatch.className = "swatch highlight";
    currentSelectColor = swatch;
  } else {
    swatch.className = "swatch";
  }
  swatch.addEventListener("click", (e) => {
    currentSelectColor.className = "swatch";
    currentColor = e.target.style.backgroundColor;
    currentSelectColor = e.target;
    currentSelectColor.className = "swatch highlight";
  });
  colorSel.appendChild(swatch);
})
brushSizes.forEach((brushSize, i) => {
  var brush = document.createElement("canvas");
  brush.width = 16;
  brush.height = 16;
  brush.ctx = brush.getContext("2d");
  brush.ctx.beginPath();
  brush.ctx.arc(8, 8, brushSize / 2, 0, Math.PI * 2);
  brush.ctx.fill();
  brush.brushSize = brushSize;
  if (currentWidth === brushSize) {
    brush.className = "swatch highlight";
    currentSelectBrush = brush;
  } else {
    brush.className = "swatch";
  }

  brush.addEventListener("click", (e) => {
    currentSelectBrush.className = "swatch";
    currentSelectBrush = e.target;
    currentSelectBrush.className = "swatch highlight";
    currentWidth = e.target.brushSize;

  });
  colorSel.appendChild(brush);
})

const canvas = document.getElementById("can");
const mouse = createMouse().start(canvas, true);
const ctx = canvas.getContext("2d");
var updateDisplay = true; // when true the display needs updating
var ch, cw, w, h; // global canvas size vars

var currentLine;

var displayOffset = {
  x: 0,
  y: 0
};

// a point object creates point from x,y coords or object that has x,y
const point = (x, y = x.y + ((x = x.x) * 0)) => ({
  x,
  y
});
// function to add a point to the line
function addPoint(x, y) {
  this.points.push(point(x, y));
}

function drawLine(ctx, offset) { // draws a line
  ctx.strokeStyle = this.color;
  ctx.lineWidth = this.width;
  ctx.lineJoin = "round";
  ctx.lineCap = "round";
  ctx.beginPath();
  var i = 0;
  while (i < this.points.length) {
    const p = this.points[i++];
    ctx.lineTo(p.x + offset.x, p.y + offset.y);
  }
  ctx.stroke();
}

function createLine(color, width) {
  return {
    points: [],
    color,
    width,
    add: addPoint,
    draw: drawLine,
  };
}

// creates a canvas
function createCanvas(width, height) {
  const c = document.createElement("canvas");
  c.width = width;
  c.height = height;
  c.ctx = c.getContext("2d");
  return c;
}
// resize main display canvas and set global size vars
function resizeCanvas() {
  ch = ((h = canvas.height = innerHeight - 32) / 2) | 0;
  cw = ((w = canvas.width = innerWidth) / 2) | 0;
  updateDisplay = true;
}

function createMouse() {
  function preventDefault(e) { e.preventDefault() }
  const mouse = {
    x: 0,
    y: 0,
    buttonRaw: 0,
    prevButton: 0
  };
  const bm = [1, 2, 4, 6, 5, 3]; // bit masks for mouse buttons
  const mouseEvents = "mousemove,mousedown,mouseup".split(",");
  const m = mouse;
  // one mouse handler
  function mouseMove(e) {
    m.bounds = m.element.getBoundingClientRect();
    m.x = e.pageX - m.bounds.left - scrollX;
    m.y = e.pageY - m.bounds.top - scrollY;

    if (e.type === "mousedown") {
      m.buttonRaw |= bm[e.which - 1];
    } else if (e.type === "mouseup") {
      m.buttonRaw &= bm[e.which + 2];
    }
    // check if there should be a display update
    if (m.buttonRaw || m.buttonRaw !== m.prevButton) {
      updateDisplay = true;
    }
    // if the mouse is down and the prev mouse is up then start a new line
    if (m.buttonRaw !== 0 && m.prevButton === 0) { // starting new line
      currentLine = createLine(currentColor, currentWidth);
      currentLine.add(m); // add current mouse position
    } else if (m.buttonRaw !== 0 && m.prevButton !== 0) { // while mouse is down
      currentLine.add(m); // add current mouse position
    }
    m.prevButton = m.buttonRaw; // remember the previous mouse state
    e.preventDefault();
  }
  // starts the mouse
  m.start = function(element, blockContextMenu) {
    m.element = element;

    mouseEvents.forEach(n => document.addEventListener(n, mouseMove));
    if (blockContextMenu === true) {
      document.addEventListener("contextmenu", preventDefault)
    }
    return m
  }
  return m;
}
var cursor = "crosshair";
function update(timer) { // Main update loop
  cursor = "crosshair";
  globalTime = timer;
  // if the window size has changed resize the canvas
  if (w !== innerWidth || h !== innerHeight) {
    resizeCanvas()
  }
  if (updateDisplay) {
    updateDisplay = false;
    display(); // call demo code
  }

  ctx.canvas.style.cursor = cursor;
  requestAnimationFrame(update);
}
// create a drawing canvas.
const drawing = createCanvas(drawingInfo.width, drawingInfo.height);
// fill with white
drawing.ctx.fillStyle = drawingInfo.bgColor;
drawing.ctx.fillRect(0, 0, drawing.width, drawing.height);

// function to display drawing
function display() {
  ctx.clearRect(0, 0, w, h);
  ctx.fillStyle = "rgba(0,0,0,0.25)";
  const imgX = cw - (drawing.width / 2) | 0;
  const imgY = ch - (drawing.height / 2) | 0;
  // add a shadow to make it look nice
  ctx.fillRect(imgX + 5, imgY + 5, drawing.width, drawing.height);

  // add outline
  ctx.strokeStyle = "black";
  ctx.lineWidth = "2";
  ctx.strokeRect(imgX, imgY, drawing.width, drawing.height);
  // draw the image
  ctx.drawImage(drawing, imgX, imgY);
  if (mouse.buttonRaw !== 0) {
    if (currentLine !== undefined) {
      currentLine.draw(ctx, displayOffset); // draw line on display canvas
      cursor = "none";
      updateDisplay = true; // keep updating
    }
  } else if (mouse.buttonRaw === 0) {
    if (currentLine !== undefined) {
      currentLine.draw(drawing.ctx, {x: -imgX, y: -imgY }); // draw line on drawing
      currentLine = undefined;
      updateDisplay = true;
      // next line is a quick fix to stop a slight flicker due to the current frame not showing the line
      ctx.drawImage(drawing, imgX, imgY);

    }
  }
}

requestAnimationFrame(update);

#can {
  position: absolute;
  top: 32px;
  left: 0px;
  background-color: #AAA;
}

.colors {
  border: 1px solid black;
  display: inline-flex;
}

.swatch {
  min-width: 16px;
  min-height: 16px;
  max-width: 16px;
  border: 1px solid black;
  display: inline-block;
  margin: 2px;
  cursor: pointer;

}

.highlight {
  border: 1px solid red;
}

<canvas id="can"></canvas>
  <div class="colors" id="colorSel"></div>

Update In response to the comment by the OP I have added a HTML version that you should be able to copy and paste (everything and including  <!DOCTYPE HTML> to </HTML>) into a html document (eg drawing.html) and then open in a browser that supports ES6. eg Chrome, Firefox, Edge.

Copy content of snippet below.

<!DOCTYPE HTML>
<html>
<head>
    <style>
#can {
  position: absolute;
  top: 32px;
  left: 0px;
  background-color: #AAA;
}

.colors {
  border: 1px solid black;
  display: inline-flex;
}

.swatch {
  min-width: 16px;
  min-height: 16px;
  max-width: 16px;
  border: 1px solid black;
  display: inline-block;
  margin: 2px;
  cursor: pointer;

}

.highlight {
  border: 1px solid red;
}
    </style>
</head>

<body>
    <canvas id="can"></canvas>
    <div class="colors" id="colorSel"></div>

<script>
// size of drawing and its starting background colour
const drawingInfo = {
  width: 384 ,
  height: 160,
  bgColor: "white",
}
const brushSizes = [1, 2, 3, 4, 5, 6, 7, 8];
const colors = "red,orange,yellow,green,cyan,blue,purple,white,gray,black".split(",");
var currentColor = "blue";
var currentWidth = 2;
var currentSelectBrush;
var currentSelectColor;
const colorSel = document.getElementById("colorSel");
colors.forEach((color, i) => {
  var swatch = document.createElement("span");
  swatch.className = "swatch";
  swatch.style.backgroundColor = color;
  if (currentColor === color) {
    swatch.className = "swatch highlight";
    currentSelectColor = swatch;
  } else {
    swatch.className = "swatch";
  }
  swatch.addEventListener("click", (e) => {
    currentSelectColor.className = "swatch";
    currentColor = e.target.style.backgroundColor;
    currentSelectColor = e.target;
    currentSelectColor.className = "swatch highlight";
  });
  colorSel.appendChild(swatch);
})
brushSizes.forEach((brushSize, i) => {
  var brush = document.createElement("canvas");
  brush.width = 16;
  brush.height = 16;
  brush.ctx = brush.getContext("2d");
  brush.ctx.beginPath();
  brush.ctx.arc(8, 8, brushSize / 2, 0, Math.PI * 2);
  brush.ctx.fill();
  brush.brushSize = brushSize;
  if (currentWidth === brushSize) {
    brush.className = "swatch highlight";
    currentSelectBrush = brush;
  } else {
    brush.className = "swatch";
  }

  brush.addEventListener("click", (e) => {
    currentSelectBrush.className = "swatch";
    currentSelectBrush = e.target;
    currentSelectBrush.className = "swatch highlight";
    currentWidth = e.target.brushSize;

  });
  colorSel.appendChild(brush);
})

const canvas = document.getElementById("can");
const mouse = createMouse().start(canvas, true);
const ctx = canvas.getContext("2d");
var updateDisplay = true; // when true the display needs updating
var ch, cw, w, h; // global canvas size vars

var currentLine;

var displayOffset = {
  x: 0,
  y: 0
};

// a point object creates point from x,y coords or object that has x,y
const point = (x, y = x.y + ((x = x.x) * 0)) => ({
  x,
  y
});
// function to add a point to the line
function addPoint(x, y) {
  this.points.push(point(x, y));
}

function drawLine(ctx, offset) { // draws a line
  ctx.strokeStyle = this.color;
  ctx.lineWidth = this.width;
  ctx.lineJoin = "round";
  ctx.lineCap = "round";
  ctx.beginPath();
  var i = 0;
  while (i < this.points.length) {
    const p = this.points[i++];
    ctx.lineTo(p.x + offset.x, p.y + offset.y);
  }
  ctx.stroke();
}

function createLine(color, width) {
  return {
    points: [],
    color,
    width,
    add: addPoint,
    draw: drawLine,
  };
}

// creates a canvas
function createCanvas(width, height) {
  const c = document.createElement("canvas");
  c.width = width;
  c.height = height;
  c.ctx = c.getContext("2d");
  return c;
}
// resize main display canvas and set global size vars
function resizeCanvas() {
  ch = ((h = canvas.height = innerHeight - 32) / 2) | 0;
  cw = ((w = canvas.width = innerWidth) / 2) | 0;
  updateDisplay = true;
}

function createMouse() {
  function preventDefault(e) { e.preventDefault() }
  const mouse = {
    x: 0,
    y: 0,
    buttonRaw: 0,
    prevButton: 0
  };
  const bm = [1, 2, 4, 6, 5, 3]; // bit masks for mouse buttons
  const mouseEvents = "mousemove,mousedown,mouseup".split(",");
  const m = mouse;
  // one mouse handler
  function mouseMove(e) {
    m.bounds = m.element.getBoundingClientRect();
    m.x = e.pageX - m.bounds.left - scrollX;
    m.y = e.pageY - m.bounds.top - scrollY;

    if (e.type === "mousedown") {
      m.buttonRaw |= bm[e.which - 1];
    } else if (e.type === "mouseup") {
      m.buttonRaw &= bm[e.which + 2];
    }
    // check if there should be a display update
    if (m.buttonRaw || m.buttonRaw !== m.prevButton) {
      updateDisplay = true;
    }
    // if the mouse is down and the prev mouse is up then start a new line
    if (m.buttonRaw !== 0 && m.prevButton === 0) { // starting new line
      currentLine = createLine(currentColor, currentWidth);
      currentLine.add(m); // add current mouse position
    } else if (m.buttonRaw !== 0 && m.prevButton !== 0) { // while mouse is down
      currentLine.add(m); // add current mouse position
    }
    m.prevButton = m.buttonRaw; // remember the previous mouse state
    e.preventDefault();
  }
  // starts the mouse
  m.start = function(element, blockContextMenu) {
    m.element = element;

    mouseEvents.forEach(n => document.addEventListener(n, mouseMove));
    if (blockContextMenu === true) {
      document.addEventListener("contextmenu", preventDefault)
    }
    return m
  }
  return m;
}
var cursor = "crosshair";
function update(timer) { // Main update loop
  cursor = "crosshair";
  globalTime = timer;
  // if the window size has changed resize the canvas
  if (w !== innerWidth || h !== innerHeight) {
    resizeCanvas()
  }
  if (updateDisplay) {
    updateDisplay = false;
    display(); // call demo code
  }

  ctx.canvas.style.cursor = cursor;
  requestAnimationFrame(update);
}
// create a drawing canvas.
const drawing = createCanvas(drawingInfo.width, drawingInfo.height);
// fill with white
drawing.ctx.fillStyle = drawingInfo.bgColor;
drawing.ctx.fillRect(0, 0, drawing.width, drawing.height);

// function to display drawing
function display() {
  ctx.clearRect(0, 0, w, h);
  ctx.fillStyle = "rgba(0,0,0,0.25)";
  const imgX = cw - (drawing.width / 2) | 0;
  const imgY = ch - (drawing.height / 2) | 0;
  // add a shadow to make it look nice
  ctx.fillRect(imgX + 5, imgY + 5, drawing.width, drawing.height);

  // add outline
  ctx.strokeStyle = "black";
  ctx.lineWidth = "2";
  ctx.strokeRect(imgX, imgY, drawing.width, drawing.height);
  // draw the image
  ctx.drawImage(drawing, imgX, imgY);
  if (mouse.buttonRaw !== 0) {
    if (currentLine !== undefined) {
      currentLine.draw(ctx, displayOffset); // draw line on display canvas
      cursor = "none";
      updateDisplay = true; // keep updating
    }
  } else if (mouse.buttonRaw === 0) {
    if (currentLine !== undefined) {
      currentLine.draw(drawing.ctx, {x: -imgX, y: -imgY }); // draw line on drawing
      currentLine = undefined;
      updateDisplay = true;
      // next line is a quick fix to stop a slight flicker due to the current frame not showing the line
      ctx.drawImage(drawing, imgX, imgY);

    }
  }
}

requestAnimationFrame(update);

/* load and add image to the drawing. It may take time to load. */
function loadImage(url){
    const image = new Image();
    image.src = url;
    image.onload = function(){
        if(drawing && drawing.ctx){
            drawing.width = image.width;
            drawing.height = image.height;
            drawing.ctx.drawImage(image,0,0);
        };
    }

 }
 loadImage("https://i.stack.imgur.com/C7qq2.png?s=328&g=1");

</script>

</body>
</html>


问:
How to change a field based on user's selection in an HTML select?
I have a select list containing variables from a query

```<code><tr>
  <td>County Name:</td>
    <td>
      <select name="countyName" onchange="countyID.value = countyName.value">
                <option>Select a County</option>
        <cfloop query = "getCounties">
        <option value="#countyName#" >#countyName#   #countyID#</option>
        </cfloop>
    </select>
    </td>
</tr>
</code>```

How can I populate the County ID field?

```<code><tr>
  <td>County ID:</td>
    <td><input type="Text" name="countyID">
     </td>
</tr>
</code>```

I've never used jQuery. Is there a way to use just JavaScript? As you can see I've attempted JavaScript, however I can only populate countyID with the countyName and I need it populated with countyID.

答:
Just out of curiousity, why are you using #countyName# as the values for your options? What if the county (erroneously or not) has a quotaton mark or something else that will screw with your HTML.

Why wouldn't you do:

```<code><select name="countyName" onchange="countyID.value = this.value">
    <option value="#countyID#">#countyName#</option>
</select>
</code>```

ContentLicense: CC BY-SA 2.5

Body:
I have a select list containing variables from a query

  County Name:

      <select name="countyName" onchange="countyID.value = countyName.value">
                <option>Select a County</option>
        <cfloop query = "getCounties">
        <option value="#countyName#" >#countyName#   #countyID#</option>
        </cfloop>
    </select>

How can I populate the County ID field?

  County ID:
    <input type="Text" name="countyID">

I've never used jQuery. Is there a way to use just JavaScript? As you can see I've attempted JavaScript, however I can only populate countyID with the countyName and I need it populated with countyID.

Body:
Just out of curiousity, why are you using #countyName# as the values for your options? What if the county (erroneously or not) has a quotaton mark or something else that will screw with your HTML.

Why wouldn't you do:

<select name="countyName" onchange="countyID.value = this.value">
    <option value="#countyID#">#countyName#</option>
</select>


问:
Bottom div alignment issue if upper have boder on hover
The issue when adding border property on hover the below div alignment is getting distorted. I know it is because it increase the height of hovered div which cause. Is there any work around.

The box height is depend on content inside it so we cant fix it. fiddle

.col {
  width: 20%;
  padding: 10px;
  float: left;
  box-sizing: border-box
}

.col:hover {
  border: solid 1px red
}```
<pre class="snippet-code-html lang-html prettyprint-override"><code><div>
  <div class="col">1</div>
  <div class="col">2</div>
  <div class="col">3</div>
  <div class="col">4</div>
  <div class="col">5</div>
  <div class="col">6</div>
  <div class="col">7</div>
  <div class="col">8</div>
</div></code>```

Edit

I have added the hover property to top most parent div which add transparent border to all the div. which fix this issue but it does not seem good approach because user can see something moving when hover

答:
I would use flex instead of float:

.flex {
    display:flex;        /* make parent flex */
    flex-direction: row; /* make children align in a row */
    flex-wrap:wrap;      /* allow row to wrap if it reaches end */
}

.col {
  flex-basis:20%;               /* this is like width, you could use width but I like to use basis */
  padding: 10px;
  box-sizing: border-box;
  border:1px solid transparent; /* start with this so you don't get any movement on hover */
}

.col:hover {
  border-color: red;
}```
<pre class="snippet-code-html lang-html prettyprint-override"><code><div class="flex">
  <div class="col">1</div>
  <div class="col">2</div>
  <div class="col">3</div>
  <div class="col">4</div>
  <div class="col">5</div>
  <div class="col">6</div>
  <div class="col">7</div>
  <div class="col">8</div>
</div></code>```

More information about flex

Body:
The issue when adding border property on hover the below div alignment is getting distorted. I know it is because it increase the height of hovered div which cause. Is there any work around.

The box height is depend on content inside it so we cant fix it. fiddle

.col {
  width: 20%;
  padding: 10px;
  float: left;
  box-sizing: border-box
}

.col:hover {
  border: solid 1px red
}

1

2

3

4

5

6

7

8

Edit

I have added the hover property to top most parent div which add transparent border to all the div. which fix this issue but it does not seem good approach because user can see something moving when hover

Body:
I would use flex instead of float:

.flex {
    display:flex;        /* make parent flex */
    flex-direction: row; /* make children align in a row */
    flex-wrap:wrap;      /* allow row to wrap if it reaches end */
}

.col {
  flex-basis:20%;               /* this is like width, you could use width but I like to use basis */
  padding: 10px;
  box-sizing: border-box;
  border:1px solid transparent; /* start with this so you don't get any movement on hover */
}

.col:hover {
  border-color: red;
}

<div class="flex">
  <div class="col">1</div>
  <div class="col">2</div>
  <div class="col">3</div>
  <div class="col">4</div>
  <div class="col">5</div>
  <div class="col">6</div>
  <div class="col">7</div>
  <div class="col">8</div>
</div>

More information about flex


问:
How to compare current date with a date range or discrete date values in MySQL?
I am saving multiple dates in database in one column separates by comma(,) like

2017-03-05, 2017-03-06, 2017-03-07, 2017-03-08, 2017-03-08.

2017-03-05, 2017-03-08

I just want to know that how I compare current date by these dates. In the first example, its easy, but problem is for the second one.

Can anyone help me out....?

Thanks...

答:
As others have commented, it would be preferable to normalise the data and store individual dates in multiple rows of a linked table rather than in a single field. But assuming there's a valid reason this can't be done, the following will do what you've asked:

```<code>SELECT date_csv,
       CASE WHEN CHAR_LENGTH(REPLACE(date_csv, ',', '')) = CHAR_LENGTH(date_csv) - 1
            THEN /* date_csv has a single comma */
                 CURRENT_DATE >= SUBSTRING(date_csv, 1, INSTR(date_csv, ',') - 1)
                 AND CURRENT_DATE <= SUBSTRING(date_csv, INSTR(date_csv, ',') + 1)
            ELSE /* date_csv has either no comma or multiple commas */
                 FIND_IN_SET(DATE_FORMAT(CURRENT_DATE,'%Y-%m-%d'), date_csv) > 0
       END AS 'Test result'
</code>```

Rextester demo: http://rextester.com/EPKO65812

Body:
As others have commented, it would be preferable to normalise the data and store individual dates in multiple rows of a linked table rather than in a single field. But assuming there's a valid reason this can't be done, the following will do what you've asked:

SELECT date_csv,
       CASE WHEN CHAR_LENGTH(REPLACE(date_csv, ',', '')) = CHAR_LENGTH(date_csv) - 1
            THEN /* date_csv has a single comma */
                 CURRENT_DATE >= SUBSTRING(date_csv, 1, INSTR(date_csv, ',') - 1)
                 AND CURRENT_DATE <= SUBSTRING(date_csv, INSTR(date_csv, ',') + 1)
            ELSE /* date_csv has either no comma or multiple commas */
                 FIND_IN_SET(DATE_FORMAT(CURRENT_DATE,'%Y-%m-%d'), date_csv) > 0
       END AS 'Test result'

Rextester demo: http://rextester.com/EPKO65812


问:
Chrome does not run jQuery after XAMPP installed
I work on a website and I added some jQuery to it. Things were going well I could open the site from local drive with Chrome and the site was running. I use google's jQuery link on the site.

After I installed XAMPP Chrome stopped load and run jQuery.

I got this error message on the console when it tried to load my xyz.js:

Uncaught ReferenceError: $ is not defined

First I load jquery.min.js from google and after that my own xyz.js

```<code><script async src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script async src="js/xyz.js" type="text/javascript"></script>
</code>```

Website is reached from:

file:///Path To/index.html

I did not even installed apach or anything with XAMPP I just installed and run XAMPP itself. So I uninstalled XAMPP but the problem remained unsolved.

The code runs on Edge perfectly but I prefer chrome instead.

How can I solve this issue with Chrome and jQuery?

Thanks for any answers!

答:
Remove the async property from the
<script async src="js/xyz.js" type="text/javascript"></script>
```

Body:
I work on a website and I added some jQuery to it. Things were going well I could open the site from local drive with Chrome and the site was running. I use google's jQuery link on the site.

After I installed XAMPP Chrome stopped load and run jQuery.

I got this error message on the console when it tried to load my xyz.js:

Uncaught ReferenceError: $ is not defined

First I load jquery.min.js from google and after that my own xyz.js

Website is reached from:

file:///Path To/index.html

I did not even installed apach or anything with XAMPP I just installed and run XAMPP itself. So I uninstalled XAMPP but the problem remained unsolved.

The code runs on Edge perfectly but I prefer chrome instead.

How can I solve this issue with Chrome and jQuery?

Thanks for any answers!

Body:
Remove the async property from the <script> tag including jQuery in the page.

jQuery has to be loaded before any script that relies on it, otherwise you'll see your '$ is undefined' error due to the xyz.js file attempting to use the library before it's available in the page. Try this:

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script async src="js/xyz.js" type="text/javascript"></script>


问:
Why does setBounds() method not work even after setting setLayout() as null?
Usually setBounds() method positions the called object in the specified location and in specified size..right?
I created a JFrame class and demonstrated its working on a button with setting setLayout(null).
Then I created a class which extends JPanel and put some components in it.
The Bounds for these components are set inside a method.
An object of this class is included in a class which extends JFrame.
Then this object calls setBound() method.
But the result does not show the components in JPanel extended class.
the cde fragment is given below.</p>

```<code>class Administrator extends JFrame implements ActionListener
{
  public Administrator()
  {
    setTitle("Administration");
    setSize(500,500);
    setDefaultCloseOperation(EXIT_ON_CLOSE);
    setLayout(null);
    JButton newbutton=new JButton(" New.. ");
    newbutton.addActionListener(this);
    add(newbutton);
    newbutton.setBounds(100,100,100,25);
    setVisible(true);

    public static void main(String arg[])
    {
      new Administrator();
    }

    public void actionPerformed(ActionEvent ae)
  {
    String act=(String)ae.getActionCommand();
    if(act.equals("New Registry..")||act.equals(" New.. "))
     {
        regPanel rgpnl=new regPanel();

        Dimension sz;
        sz=rgpnl.getPreferredSize();
        rgpnl.setBounds(800,800,sz.width,sz.height);
        rgpnl.arrangeComponents();
        add(rgpnl);

        repaint();
        setVisible(true);
     }
}
class regPanel extends JPanel
{
  Label namelab;
  JTextField name;
  JButton do_register;
  public regPanel()
  {
    //Container   = get ();
    setLayout(null);

    namelab=new Label("Name :");
    name=new JTextField(20);
    add(namelab);
    add(name);
    add(do_register);
   }
   public void arrangeComponents()
  {
    Dimension size;

    size=namelab.getPreferredSize();
    namelab.setBounds(20,10,size.width,size.height);
    name.getPreferredSize();
    name.setBounds(150,10,size.width,size.height);
    do_register.setBounds(10,10,size.width,size.height);

    repaint();

  }
}
</code>```

答: This may not be the answer you want to hear, but you're far better off avoiding use of null layout and absolute positioning as it can be a bear to maintain, and may make your GUI ugly or unusable if run on an OS other than the one it was developed on.  Most GUI's, even fairly complex GUI's can be made with a nesting of JPanels each using a simple layout manager, or barring that GridBagLayout or MIgLayout (not part of standard Java, but free when I last used it, and fairly easy to use).  Also, if you show us an image of the layout you're trying to achieve, or describe it in fairly good detail, we can help guide you on the best layout manager combinations to try first.</p>

Body:
Usually setBounds() method positions the called object in the specified location and in specified size..right?
I created a JFrame class and demonstrated its working on a button with setting setLayout(null).
Then I created a class which extends JPanel and put some components in it.
The Bounds for these components are set inside a method.
An object of this class is included in a class which extends JFrame.
Then this object calls setBound() method.
But the result does not show the components in JPanel extended class.
the cde fragment is given below.

class Administrator extends JFrame implements ActionListener
{
  public Administrator()
  {
    setTitle("Administration");
    setSize(500,500);
    setDefaultCloseOperation(EXIT_ON_CLOSE);
    setLayout(null);
    JButton newbutton=new JButton(" New.. ");
    newbutton.addActionListener(this);
    add(newbutton);
    newbutton.setBounds(100,100,100,25);
    setVisible(true);

    public static void main(String arg[])
    {
      new Administrator();
    }

    public void actionPerformed(ActionEvent ae)
  {
    String act=(String)ae.getActionCommand();
    if(act.equals("New Registry..")||act.equals(" New.. "))
     {
        regPanel rgpnl=new regPanel();

        Dimension sz;
        sz=rgpnl.getPreferredSize();
        rgpnl.setBounds(800,800,sz.width,sz.height);
        rgpnl.arrangeComponents();
        add(rgpnl);

        repaint();
        setVisible(true);
     }
}
class regPanel extends JPanel
{
  Label namelab;
  JTextField name;
  JButton do_register;
  public regPanel()
  {
    //Container   = get ();
    setLayout(null);

    namelab=new Label("Name :");
    name=new JTextField(20);
    add(namelab);
    add(name);
    add(do_register);
   }
   public void arrangeComponents()
  {
    Dimension size;

    size=namelab.getPreferredSize();
    namelab.setBounds(20,10,size.width,size.height);
    name.getPreferredSize();
    name.setBounds(150,10,size.width,size.height);
    do_register.setBounds(10,10,size.width,size.height);

    repaint();

  }
}


问:
Adding gradle task to a subproject in method
I have a project with a bunch of subprojects. Some of the subprojects are utility projects, and some of the projects are actual applications.

The "application" subprojects should all produce a jar file with a given main class etc. To solve this I've put the following in the parent build.gradle:

```<code>def configureApplication(project, mainClass) {
    project.jar { ... }
}
</code>```

and from each subproject's build.gradle, I call configureApplication(project, "my.main.Class")

Now I want to add a deploy task to all application subproject's so that I can deploy all applications using ./gradlew deploy. I've tried to mimic the above approach by putting this in the parent build.gradle:

```<code>def configureDeploy(project) {
    project {
        task deploy {
            println "Deploying!"
        }
    }
}
</code>```

But I'm running in to:

```<code>Could not find method call() for arguments [build_51pn93...closure3@334ebcaa] on project ':subproj'.
</code>```

I've tried about a hundred other variations for the past hour without success.

Question: How do add tasks to some of the subprojects without repeating myself in each subproject's build.gradle? (Also, is using methods in the parent build.gradle a reasonable way of achieving this, or is there a more gradle idiomatic way of doing it?)

答:
It is indeed common to add tasks for subprojects in the parent build.gradle file.

Edit: per comments, the goal is to apply this to all subproject, and not selective ones.

Consider the following settings.gradle:

```<code>include 'appA', 'appB', 'utilityC'
</code>```

Here is the root build.gradle. It defines a custom DeployTask (doc here) for each application (using subprojects), but does not configure it:

```<code>class DeployTask extends DefaultTask {
    String appName
    String destDir

    @TaskAction
    def deploy() {
        if (appName != null && destDir != null) {
            println "deploying ${appName} to ${destDir}"
        }
    }
}

subprojects {
    task deploy(type: DeployTask) {}
}
</code>```

Here is build.gradle for appA:

```<code>deploy() {
    appName = "Application A"
    destDir = "~/server/appA"
}
</code>```

Here is build.gradle for appB:

```<code>deploy() {
    appName = "Application B"
    destDir = "~/web/appB"
}
</code>```

In this simple example, utilityC does not have a build.gradle

Example output:

```<code>$ gradle :appA:deploy
deploying Application A to ~/server/appA
</code>```

and

```<code>$ gradle :appB:deploy
deploying Application B to ~/web/appB
</code>```

and

```<code>$ gradle :utilityC:deploy
[no output]
</code>```

Body:
I have a project with a bunch of subprojects. Some of the subprojects are utility projects, and some of the projects are actual applications.

The "application" subprojects should all produce a jar file with a given main class etc. To solve this I've put the following in the parent build.gradle:

def configureApplication(project, mainClass) {
    project.jar { ... }
}

and from each subproject's build.gradle, I call configureApplication(project, "my.main.Class")

Now I want to add a deploy task to all application subproject's so that I can deploy all applications using ./gradlew deploy. I've tried to mimic the above approach by putting this in the parent build.gradle:

def configureDeploy(project) {
    project {
        task deploy {
            println "Deploying!"
        }
    }
}

But I'm running in to:

Could not find method call() for arguments [build_51pn93...closure3@334ebcaa] on project ':subproj'.

I've tried about a hundred other variations for the past hour without success.

Question: How do add tasks to some of the subprojects without repeating myself in each subproject's build.gradle? (Also, is using methods in the parent build.gradle a reasonable way of achieving this, or is there a more gradle idiomatic way of doing it?)

Body:
It is indeed common to add tasks for subprojects in the parent build.gradle file.

Edit: per comments, the goal is to apply this to all subproject, and not selective ones.

Consider the following settings.gradle:

include 'appA', 'appB', 'utilityC'

Here is the root build.gradle. It defines a custom DeployTask (doc here) for each application (using subprojects), but does not configure it:

class DeployTask extends DefaultTask {
    String appName
    String destDir

    @TaskAction
    def deploy() {
        if (appName != null && destDir != null) {
            println "deploying ${appName} to ${destDir}"
        }
    }
}

subprojects {
    task deploy(type: DeployTask) {}
}

Here is build.gradle for appA:

deploy() {
    appName = "Application A"
    destDir = "~/server/appA"
}

Here is build.gradle for appB:

deploy() {
    appName = "Application B"
    destDir = "~/web/appB"
}

In this simple example, utilityC does not have a build.gradle

Example output:

$ gradle :appA:deploy
deploying Application A to ~/server/appA

and

$ gradle :appB:deploy
deploying Application B to ~/web/appB

and

$ gradle :utilityC:deploy
[no output]


问:
test case for form validation not running in django
I started learning django framework in that I have created form which verifies interdependent fields. now I have written a testCase for it but my console is showing 0 test cases ran.I am not getting why it is not running

below is my forms.py

```<code>class SearchForm(forms.ModelForm):
    fromDate=forms.DateField()
    toDate=forms.DateField(required=False)
    fromLocation=forms.CharField()
    toLocation=forms.CharField()
    def clean(self):
        """verify from and to date and location"""
        cleanedData=super().clean()
        fLocation=cleanedData.get('fromLocation')
        tLocation=cleanedData.get('toLocation')
        self.validateLocation(fLocation,tLocation)
        self.validateDates(self.fromDate,self.toDate)

    def validateLocation(self,fLocation,tLocation):
        if fLocation==tLocation:
            raise forms.ValidationError(_("from and to location can not be same"),code="invalid location")

    def validateDates(self,fromDate,toDate):
        if toDate is not None:
            if toDate <= fromDate:
                raise forms.ValidationError(_("from date should be less than to date"),code="invalid date")
</code>```

and my tests.py

```<code>from django.test import TestCase

from booking.forms import SearchForm

# Create your tests here.
class SearchTestCase(TestCase):
    def fromToLocationSameTestCase(self):
        form_data={'fromLocation':'bangalore','toLocation':'bangalore','fromDate':'2017-06-07'}
        form=SearchForm(data=form_data)
        self.assertFlase(form.is_valid())
</code>```

please let me know where I went wrong. FYI I tried by overriding clean method of forms but no luck

答:
All test methods need to begin with test_. (And in any case, standard Python naming convention for methods is lower_case_with_underscore.)

Call your method test_from_to_location_same.

Body:
I started learning django framework in that I have created form which verifies interdependent fields. now I have written a testCase for it but my console is showing 0 test cases ran.I am not getting why it is not running

below is my forms.py

class SearchForm(forms.ModelForm):
    fromDate=forms.DateField()
    toDate=forms.DateField(required=False)
    fromLocation=forms.CharField()
    toLocation=forms.CharField()
    def clean(self):
        """verify from and to date and location"""
        cleanedData=super().clean()
        fLocation=cleanedData.get('fromLocation')
        tLocation=cleanedData.get('toLocation')
        self.validateLocation(fLocation,tLocation)
        self.validateDates(self.fromDate,self.toDate)

    def validateLocation(self,fLocation,tLocation):
        if fLocation==tLocation:
            raise forms.ValidationError(_("from and to location can not be same"),code="invalid location")

    def validateDates(self,fromDate,toDate):
        if toDate is not None:
            if toDate <= fromDate:
                raise forms.ValidationError(_("from date should be less than to date"),code="invalid date")

and my tests.py

from django.test import TestCase

from booking.forms import SearchForm

# Create your tests here.
class SearchTestCase(TestCase):
    def fromToLocationSameTestCase(self):
        form_data={'fromLocation':'bangalore','toLocation':'bangalore','fromDate':'2017-06-07'}
        form=SearchForm(data=form_data)
        self.assertFlase(form.is_valid())

please let me know where I went wrong. FYI I tried by overriding clean method of forms but no luck


问:
AWS CLI: Describe Network ACLs
I am having a bit of an issue with this command. I am trying to list out only the egress ACL rules, and just the rule number. So this is my command:

```<code>aws ec2 describe-network-acls --network-acl-ids acl-c324a5a4 --output text --query 'NetworkAcls[*].Entries[*].{RN:RuleNumber}' --filter Name=entry.rule-action,Values=allow Name=entry.egress,Values=true
</code>```

The return of this is:

```<code>100
110
120
130
140
150
160
170
32767
100
110
120
130
140
150
160
170
32767
</code>```

It is basically listing both egress and ingress rules. The egress and ingress rules have the same rule number. It also lists the *DENY rule (32767), I would also like to avoid that.

Can anyone help me with this command where I want to list out only egress rule numbers?

Thanks

答:
so you want the Egress Rule Number which are allowed. You can do that using the following query:

```<code>aws ec2 describe-network-acls \
  --output text \
  --network-acl-ids acl-c324a5a4 \
  --query 'NetworkAcls[*].Entries[?(RuleAction==`allow` && Egress==`true`)].{RN:RuleNumber}'
</code>```

You can read more about Controlling Command Output from the AWS Command Line Interface

Title: AWS CLI: Describe Network ACLs

Body:
I am having a bit of an issue with this command. I am trying to list out only the egress ACL rules, and just the rule number. So this is my command:

aws ec2 describe-network-acls --network-acl-ids acl-c324a5a4 --output text --query 'NetworkAcls[*].Entries[*].{RN:RuleNumber}' --filter Name=entry.rule-action,Values=allow Name=entry.egress,Values=true

The return of this is:

100
110
120
130
140
150
160
170
32767
100
110
120
130
140
150
160
170
32767

It is basically listing both egress and ingress rules. The egress and ingress rules have the same rule number. It also lists the *DENY rule (32767), I would also like to avoid that.

Can anyone help me with this command where I want to list out only egress rule numbers?

Thanks

Body:
so you want the Egress Rule Number which are allowed. You can do that using the following query:

aws ec2 describe-network-acls \
  --output text \
  --network-acl-ids acl-c324a5a4 \
  --query 'NetworkAcls[*].Entries[?(RuleAction==`allow` && Egress==`true`)].{RN:RuleNumber}'

You can read more about Controlling Command Output from the AWS Command Line Interface


问:
how to increase the Rest service timeout time in spring STS
I am using a spring STS to develop the project which  has the embedded tc server.  I don't know what causes this  issue, but my rest service always gets timeout of 60 seconds, even though I tried to keep timeout=100 in @Transactional and I tried putting the value in jpa.xml file too. Can anybody tell me how to increase the timeout?

答:
if you are using RestTemplate than you should use following code to implement timeouts

```<code>@Bean
public RestTemplate restTemplate() {
    return new RestTemplate(clientHttpRequestFactory());
}

private ClientHttpRequestFactory clientHttpRequestFactory() {
    HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory();
    factory.setReadTimeout(2000);
    factory.setConnectTimeout(2000);
    return factory;
}}
The x
</code>```

ml configuration

```<code><bean class="org.springframework.web.client.RestTemplate">
<constructor-arg>
    <bean class="org.springframework.http.client.HttpComponentsClientHttpRequestFactory"
        p:readTimeout="2000"
        p:connectTimeout="2000" />
</constructor-arg>
</code>```

Ref :
Spring Boot REST API - request timeout?

Timeout webservice call from client side

Body:
if you are using RestTemplate than you should use following code to implement timeouts

@Bean
public RestTemplate restTemplate() {
    return new RestTemplate(clientHttpRequestFactory());
}

private ClientHttpRequestFactory clientHttpRequestFactory() {
    HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory();
    factory.setReadTimeout(2000);
    factory.setConnectTimeout(2000);
    return factory;
}}
The x

ml configuration

<bean class="org.springframework.web.client.RestTemplate">
<constructor-arg>
    <bean class="org.springframework.http.client.HttpComponentsClientHttpRequestFactory"
        p:readTimeout="2000"
        p:connectTimeout="2000" />
</constructor-arg>

Ref :
Spring Boot REST API - request timeout?

Timeout webservice call from client side