问:
how write a type definition for a HoC using flow
I'm trying to write a flow type for a HoC that will return a component and add a prop isVisible to it

```<code>type VisibleProps = {isVisible: boolean}

const VisibleComp = <P, S>(Component: Class<React.Component<void, P, S>>)
  : Class<React.Component<void, P&VisibleProps, S> =>
  class WrappedComponent extends React.Component<void, P&VisibleProps, S> {
      render() {
          return <Component {...this.props} isVisible={true} />
      }
  }
</code>```

I try several things without success :(

答:
Digging in the flow issues, I found this issue which solve my problem
https://github.com/facebook/flow/issues/3241

hope it helps.

```<code>// @flow
import React from 'react';

type Visible = {isVisible: boolean}
type WrappedProps<P,Visible> = P & Visible

const injectVisible = <P: Object>(
  Component: Class<React.Component<*, WrappedProps<P, Visible>, *>>
) => class VisibleHoC extends React.Component<*, P, Visible> {
      state: Visible
      render() {
          return <Component {...this.props} isVisible={true} />
      }
  }

class Component extends React.Component {
  props: Visible
  render() {
    return <div> {this.props.isVisible ? 'visible' : 'hidden'}</div>
  }
}

const VisibleComponent = injectVisible(Component)
</code>```

Body:
I'm trying to write a flow type for a HoC that will return a component and add a prop isVisible to it

type VisibleProps = {isVisible: boolean}

const VisibleComp =
(Component: Class<React.Component<void, P, S>>)
  : Class<React.Component<void, P&VisibleProps, S> =>
  class WrappedComponent extends React.Component<void, P&VisibleProps, S> {
      render() {
          return <Component {...this.props} isVisible={true} />
      }
  }

I try several things without success :(

Body:
Digging in the flow issues, I found this issue which solve my problem
https://github.com/facebook/flow/issues/3241

hope it helps.

// @flow
import React from 'react';

type Visible = {isVisible: boolean}
type WrappedProps<P,Visible> = P & Visible

const injectVisible = <P: Object>(
  Component: Class<React.Component<*, WrappedProps<P, Visible>, *>>
) => class VisibleHoC extends React.Component<*, P, Visible> {
      state: Visible
      render() {
          return <Component {...this.props} isVisible={true} />
      }
  }

class Component extends React.Component {
  props: Visible
  render() {
    return <div> {this.props.isVisible ? 'visible' : 'hidden'}</div>
  }
}

const VisibleComponent = injectVisible(Component)


来源: stackexchange

问:
Cancel both events of jquery accordion
```<code>  $(document).ready(function () {

        $("#accordion").accordion({
            change: function (event, ui) {
                alert('control changed')
            },
            changestart: function (event, ui) {
                alert('control changing')
            }
        });
        $("#accordion").bind("accordionchange", Change);
        $("#accordion").bind("accordionchangestart", ChangeStart);

        function Change(e, ui) {
             // code for canceling both  events
            alert('bind:changed')
        }
     function ChangeStart() {
            // code for canceling both  events
            alert('bind:changing')
        }
    })
</code>```

How to cancel both events via new bind event

答:
I would suggest preventing the default behavior:

function Change(e) {

        e.preventDefault();
    }
    function ChangeStart(e) {

        e.preventDefault
    }

If that doesn't work you can unbind the events, though this would be a pain to re-bind:

This should be what you're looking for:

```<code>$('#accordion').unbind("accordionchange").unbind("accordionchangestart");
</code>```

ContentLicense: CC BY-SA 2.5

Title: Cancel both events of jquery accordion

Body:
  $(document).ready(function () {

        $("#accordion").accordion({
            change: function (event, ui) {
                alert('control changed')
            },
            changestart: function (event, ui) {
                alert('control changing')
            }
        });
        $("#accordion").bind("accordionchange", Change);
        $("#accordion").bind("accordionchangestart", ChangeStart);

        function Change(e, ui) {
             // code for canceling both  events
            alert('bind:changed')
        }
     function ChangeStart() {
            // code for canceling both  events
            alert('bind:changing')
        }
    })

How to cancel both events via new bind event

Body:
I would suggest preventing the default behavior:

function Change(e) {

        e.preventDefault();
    }
    function ChangeStart(e) {

        e.preventDefault
    }

If that doesn't work you can unbind the events, though this would be a pain to re-bind:

This should be what you're looking for:

$('#accordion').unbind("accordionchange").unbind("accordionchangestart");


问:
PHP Countdown to Date
How could set a date and get a countdown in PHP? For example if I set the date as 3 December 2PM it would tell me how many days and hours are remaining.

No need for user inputs for the date as it will be hard coded.

Thanks.

答:
For those looking for a function capable of handling larger and smaller time span (php >5.3) : </p>

```<code>/**
 * Return a textual representation of the time left until specified date
 */
function timeleft(DateTime $date){
  $now = new DateTime();

  if($now > $date){
    return '0 second';
  }

  $interval = $date->diff($now);

  if($interval->y){
    return $interval->format("%y year").($interval->y > 1 ? 's':'');
  } else if($interval->m){
    return $interval->format("%m month").($interval->m > 1 ? 's':'');
  } else if($interval->d){
    return $interval->format("%d day").($interval->d > 1 ? 's':'');
  } else if($interval->h){
    return $interval->format("%h hour").($interval->h > 1 ? 's':'');
  } else if($interval->i){
    return $interval->format("%i minute").($interval->i > 1 ? 's':'');
  } else if($interval->s) {
    return $interval->format("%s second").($interval->s > 1 ? 's':'');
  } else {
    return 'milliseconds';
  }
}
</code>```

Title: PHP Countdown to Date

Body:
For those looking for a function capable of handling larger and smaller time span (php >5.3) :

/**
 * Return a textual representation of the time left until specified date
 */
function timeleft(DateTime $date){
  $now = new DateTime();

  if($now > $date){
    return '0 second';
  }

  $interval = $date->diff($now);

  if($interval->y){
    return $interval->format("%y year").($interval->y > 1 ? 's':'');
  } else if($interval->m){
    return $interval->format("%m month").($interval->m > 1 ? 's':'');
  } else if($interval->d){
    return $interval->format("%d day").($interval->d > 1 ? 's':'');
  } else if($interval->h){
    return $interval->format("%h hour").($interval->h > 1 ? 's':'');
  } else if($interval->i){
    return $interval->format("%i minute").($interval->i > 1 ? 's':'');
  } else if($interval->s) {
    return $interval->format("%s second").($interval->s > 1 ? 's':'');
  } else {
    return 'milliseconds';
  }
}

ContentLicense: CC BY-SA 3.0


问:
Build Short cut in Mac Os Terminal
I'm trying to build a shortcut to run a python code. This code was built my developer who is now missing in action. I'm not able to write code in Mac OS terminal. In any case, I have two pythons files in the folder proofs. When I hit jj on the terminal it runs the code 5.7.16. I thought if I changed the first line from

FPTH="/Users/robertford/PycharmProjects/inference_engine2/inference2/Proofs/5.7.16.py"

to

FPTH="/Users/robertford/PycharmProjects/inference_engine2/inference2/Proofs/prove.py"

then the short cut would run the "prove" file but it doesn't. It continues to run the 5.7.16 file. So I'm trying to build a second short cut where if I hit kk then it runs the prove file located in the proofs folder. Any help would be appreciated. Don't worry about the stuff where it says excel, MySQL and django. That's not important.

```<code>    FPTH="/Users/robertford/PycharmProjects/inference_engine2/inference2/Proofs/prove.py"
        vmysql=$(grep "mysql =" $FPTH | cut -d'=' -f2)
vexcel=$(grep “excel =" $FPTH | cut -d'=' -f2)
echo $vexcel
echo $vmysql
if [ "$vexcel" == "True" ] ; then
echo "Excel"
elif [ "$vmysql" = "True" ]
then
echo "Mysql"
else
echo "Django"
fi
if [ "$vexcel" = "True" ] ; then
echo "Excel is set”
python $FPTH
elif [ "$vmysql" = "True" ]
then
echo "Mysql is set”
python $FPTH
else
echo “Django is set”
cd /dUsers/robertford/PycharmProjects/inference_engine2
python manage.py runserver
fi
</code>```

答:
So, if I understand correctly you are trying to get /Users/robertford/PycharmProjects/inference_engine2/inference2/Proofs/prove.py to execute by typing kk into your Terminal?

You could do that by adding an alias to your .bashrc.

So:

In your Terminal type: nano ~/.bashrc

Add the following line: alias kk='python /Users/robertford/PycharmProjects/inference_engine2/inference2/Proofs/prove.py'

Press ctrl + x

Type Y and hit enter (enter might not even be necessary).

Be sure to source your bashrc. Type into Terminal: source ~/.baschrc

Done. Typing kk in Terminal now launches the script.

Title: Build Short cut in Mac Os Terminal

Body:
I'm trying to build a shortcut to run a python code. This code was built my developer who is now missing in action. I'm not able to write code in Mac OS terminal. In any case, I have two pythons files in the folder proofs. When I hit jj on the terminal it runs the code 5.7.16. I thought if I changed the first line from

FPTH="/Users/robertford/PycharmProjects/inference_engine2/inference2/Proofs/5.7.16.py"

to

FPTH="/Users/robertford/PycharmProjects/inference_engine2/inference2/Proofs/prove.py"

then the short cut would run the "prove" file but it doesn't. It continues to run the 5.7.16 file. So I'm trying to build a second short cut where if I hit kk then it runs the prove file located in the proofs folder. Any help would be appreciated. Don't worry about the stuff where it says excel, MySQL and django. That's not important.

    FPTH="/Users/robertford/PycharmProjects/inference_engine2/inference2/Proofs/prove.py"
        vmysql=$(grep "mysql =" $FPTH | cut -d'=' -f2)
vexcel=$(grep “excel =" $FPTH | cut -d'=' -f2)
echo $vexcel
echo $vmysql
if [ "$vexcel" == "True" ] ; then
echo "Excel"
elif [ "$vmysql" = "True" ]
then
echo "Mysql"
else
echo "Django"
fi
if [ "$vexcel" = "True" ] ; then
echo "Excel is set”
python $FPTH
elif [ "$vmysql" = "True" ]
then
echo "Mysql is set”
python $FPTH
else
echo “Django is set”
cd /dUsers/robertford/PycharmProjects/inference_engine2
python manage.py runserver
fi


问:
casting functions into function pointers in a c programme
I am trying to understand a software for a Tire Pressure Monitoring System but I know little about C language.
In one of the header files there is these kind of definitions :

```<code>#define TPMS_RESET         gu16AddressToFn = u16fnDALLinkFmw(gu8Derivative, FN_RESET);\
                       ((void(*)(void))(gu16AddressToFn))

/* UINT8 TPMS_READ_VOLTAGE(UINT16 *u16UUMA) */
#define  TPMS_READ_VOLTAGE  ((UINT8(*)(UINT16*))(u16fnDALLinkFmw(gu8Derivative, FN_READ_VOLT)))

/* UINT8 TPMS_COMP_VOLTAGE(UINT8 *u8CompVoltage, *UINT16 u16UUMA) */
#define  TPMS_COMP_VOLTAGE  ((UINT8(*)(UINT8*, UINT16*))(u16fnDALLinkFmw(gu8Derivative, FN_COMP_V)))

/* UINT8 TPMS_READ_TEMPERATURE(UINT16 *u16UUMA) */
#define  TPMS_READ_TEMPERATURE  ((UINT8(*)(UINT16*))(u16fnDALLinkFmw(gu8Derivative, FN_READ_T)))

/* UINT8 TPMS_COMP_TEMPERATURE(UINT8 *u8Temp, UINT16 *u16UUMA) */
#define  TPMS_COMP_TEMPERATURE   ((UINT8(*)(UINT8*, UINT16*))(u16fnDALLinkFmw(gu8Derivative, FN_COMP_T)))

/* UINT8 TPMS_READ_PRESSURE(UINT16 *u16UUMA, UINT8 u8Avg) */
#define  TPMS_READ_PRESSURE    ((UINT8(*)(UINT16*, UINT8))(u16fnDALLinkFmw(gu8Derivative, FN_READ_P)))

/* UINT8 TPMS_COMP_PRESSURE(UINT16 *u16CompPressure, UINT16 *u16UUMA) */
#define  TPMS_COMP_PRESSURE    ((UINT8(*)(UINT16*, UINT16*))(u16fnDALLinkFmw(gu8Derivative, FN_COMP_P)))

/* UINT8 TPMS_READ_ACCEL_X(UINT16 *u16UUMA, UINT8 u8Avg, UINT8 u8FiltSelect, UINT8 u8DynamicOffset) */
#define  TPMS_READ_ACCEL_X  ((UINT8(*)(UINT16*, UINT8, UINT8, UINT8))(u16fnDALLinkFmw(gu8Derivative, FN_READ_X)))

/* UINT8 TPMS_READ_ACCEL_Z(UINT16 *u16UUMA, UINT8 u8Avg, UINT8 u8FiltSelect, UINT8 u8DynamicOffset) */
#define  TPMS_READ_ACCEL_Z ((UINT8(*)(UINT16*, UINT8, UINT8, UINT8))(u16fnDALLinkFmw(gu8Derivative, FN_READ_Z)))
</code>```

I don´t really understand this trick of casting into other functions. Have you got any idea?

答:
Function pointer casting is a way to convert non-C firmware memory addresses into valid function declarations in C. This is normally done in embedded systems when you're accessing firmware functions (probably written in non-C languages / assembly) without the firmware's API exposed as a C API.

For example, in your case, the firmware provides a list of addresses to firmware functions in gu8Derivative (a jump-table in the firmware code). Using u16fnDALLinkFmw(gu8Derivative, X) you can get the jump-address of function X in firmware which is equivalent to a function pointer in C. Now, since the function declaration in firmware is not known directly in C, it is provided as a function pointer cast with an accompanying comment describing the API of the corresponding firmware function.

This NXP community post gives some more details about this exact firmware you're trying to use.

Body:
I am trying to understand a software for a Tire Pressure Monitoring System but I know little about C language.
In one of the header files there is these kind of definitions :

#define TPMS_RESET         gu16AddressToFn = u16fnDALLinkFmw(gu8Derivative, FN_RESET);\
                       ((void(*)(void))(gu16AddressToFn))

/* UINT8 TPMS_READ_VOLTAGE(UINT16 *u16UUMA) */
#define  TPMS_READ_VOLTAGE  ((UINT8(*)(UINT16*))(u16fnDALLinkFmw(gu8Derivative, FN_READ_VOLT)))

/* UINT8 TPMS_COMP_VOLTAGE(UINT8 *u8CompVoltage, *UINT16 u16UUMA) */
#define  TPMS_COMP_VOLTAGE  ((UINT8(*)(UINT8*, UINT16*))(u16fnDALLinkFmw(gu8Derivative, FN_COMP_V)))

/* UINT8 TPMS_READ_TEMPERATURE(UINT16 *u16UUMA) */
#define  TPMS_READ_TEMPERATURE  ((UINT8(*)(UINT16*))(u16fnDALLinkFmw(gu8Derivative, FN_READ_T)))

/* UINT8 TPMS_COMP_TEMPERATURE(UINT8 *u8Temp, UINT16 *u16UUMA) */
#define  TPMS_COMP_TEMPERATURE   ((UINT8(*)(UINT8*, UINT16*))(u16fnDALLinkFmw(gu8Derivative, FN_COMP_T)))

/* UINT8 TPMS_READ_PRESSURE(UINT16 *u16UUMA, UINT8 u8Avg) */
#define  TPMS_READ_PRESSURE    ((UINT8(*)(UINT16*, UINT8))(u16fnDALLinkFmw(gu8Derivative, FN_READ_P)))

/* UINT8 TPMS_COMP_PRESSURE(UINT16 *u16CompPressure, UINT16 *u16UUMA) */
#define  TPMS_COMP_PRESSURE    ((UINT8(*)(UINT16*, UINT16*))(u16fnDALLinkFmw(gu8Derivative, FN_COMP_P)))

/* UINT8 TPMS_READ_ACCEL_X(UINT16 *u16UUMA, UINT8 u8Avg, UINT8 u8FiltSelect, UINT8 u8DynamicOffset) */
#define  TPMS_READ_ACCEL_X  ((UINT8(*)(UINT16*, UINT8, UINT8, UINT8))(u16fnDALLinkFmw(gu8Derivative, FN_READ_X)))

/* UINT8 TPMS_READ_ACCEL_Z(UINT16 *u16UUMA, UINT8 u8Avg, UINT8 u8FiltSelect, UINT8 u8DynamicOffset) */
#define  TPMS_READ_ACCEL_Z ((UINT8(*)(UINT16*, UINT8, UINT8, UINT8))(u16fnDALLinkFmw(gu8Derivative, FN_READ_Z)))

I don´t really understand this trick of casting into other functions. Have you got any idea?


问:
Getting the value (but not key) from SASS list variable
I want to have a navigation bar that scales the content to the current breakpoint as defined in global site media queries but I can't seem to target the items in the SASS list correctly.

HTML

```<code><div class="contain-header">
    <header class="top-bar">
        <!--nav here-->
    </header>
</div>
</code>```

Global settings (SASS)

```<code>$breakpoints: (
  small: 0,
  medium: 640px,
  large: 1024px,
  xlarge: 1200px,
  xxlarge: 1440px,
);
</code>```

So when the screen is < 1200px, the navigation content would have a max-width of 1024px.

SASS (not working)

```<code>.contain-header {
    .top-bar {
        margin: 0 auto;
        @each $item in $breakpoints {
            @include breakpoint(#{$item}) {
                max-width: #{$item};
            }
        }
    }
}
</code>```

This causes an error on compile:

WARNING: breakpoint(): "small 0" is not defined in your $breakpoints setting.

(repeated for each item in $breakpoints())

So how do I call #{item} so that instead of outputting medium 640px it outputs 640px (or medium for that matter)? And how do I change max-width: #{$item}; to target the value of $item - 1?

N.B. I'm using Foundation where the @include breakpoint(){} is a mixin that wraps the css inside a media query & $breakpoints() is one of the framework's variables (http://foundation.zurb.com/sites/docs/media-queries.html#sass).

答:
Try using <code>@each $key, $value in $breakpoints</code> and leave out the interpolation: </p>

```<code>.contain-header {
  .top-bar {
    margin: 0 auto;
    @each $key, $value in $breakpoints {
      @include breakpoint($key) {
        max-width: $value;
      }
    }
  }
}
</code>```

Body:
I want to have a navigation bar that scales the content to the current breakpoint as defined in global site media queries but I can't seem to target the items in the SASS list correctly.

HTML

Global settings (SASS)

$breakpoints: (
  small: 0,
  medium: 640px,
  large: 1024px,
  xlarge: 1200px,
  xxlarge: 1440px,
);

So when the screen is < 1200px, the navigation content would have a max-width of 1024px.

SASS (not working)

.contain-header {
    .top-bar {
        margin: 0 auto;
        @each $item in $breakpoints {
            @include breakpoint(#{$item}) {
                max-width: #{$item};
            }
        }
    }
}

This causes an error on compile:

WARNING: breakpoint(): "small 0" is not defined in your $breakpoints setting.

(repeated for each item in $breakpoints())

So how do I call #{item} so that instead of outputting medium 640px it outputs 640px (or medium for that matter)? And how do I change max-width: #{$item}; to target the value of $item - 1?

N.B. I'm using Foundation where the @include breakpoint(){} is a mixin that wraps the css inside a media query & $breakpoints() is one of the framework's variables (http://foundation.zurb.com/sites/docs/media-queries.html#sass).

Body:
Try using @each $key, $value in $breakpoints and leave out the interpolation:

.contain-header {
  .top-bar {
    margin: 0 auto;
    @each $key, $value in $breakpoints {
      @include breakpoint($key) {
        max-width: $value;
      }
    }
  }
}


问:
SQL Case Statement - how to do it
I have the below statement which works nicely in Tableau.

However, I'd like to turn this into SQL and save all the results into a temporary column name.

Does anyone know how I might do this?

Essentially, the below removes the .com/.net etc... from the domain name.

I then have another script that removes the subdomain (everything from the first . to the left of the resulting value).

If anyone can help me with these, that would be incredible as I'm not sure how to do this in SQL

```<code>IF CONTAINS([domain], ".co.uk") then LEFT([domain],LEN([domain])-6)
elseif  CONTAINS([domain], ".com") then LEFT([domain],LEN([domain])-4)
elseif  CONTAINS([domain], ".net") then LEFT([domain],LEN([domain])-4)
elseif  CONTAINS([domain], ".org") then LEFT([domain],LEN([domain])-4)
elseif  CONTAINS([domain], ".biz") then LEFT([domain],LEN([domain])-4)
elseif  CONTAINS([domain], ".edu") then LEFT([domain],LEN([domain])-4)
elseif  CONTAINS([domain], ".ac") then LEFT([domain],LEN([domain])-3)
elseif  CONTAINS([domain], ".gov") then LEFT([domain],LEN([domain])-4)
elseif  CONTAINS([domain], ".biz") then LEFT([domain],LEN([domain])-4)
elseif  CONTAINS([domain], ".co") then LEFT([domain],LEN([domain])-3)
elseif  CONTAINS([domain], ".ca") then LEFT([domain],LEN([domain])-3)
elseif  CONTAINS([domain], ".io") then LEFT([domain],LEN([domain])-3)
elseif  CONTAINS([domain], ".in") then LEFT([domain],LEN([domain])-3)
elseif  CONTAINS([domain], ".it") then LEFT([domain],LEN([domain])-3)
elseif  CONTAINS([domain], ".uk") then LEFT([domain],LEN([domain])- 3)
elseif  CONTAINS([domain], ".ru") then LEFT([domain],LEN([domain])-3)
elseif  CONTAINS([domain], ".ie") then LEFT([domain],LEN([domain])-3)
elseif  CONTAINS([domain], ".tv") then LEFT([domain],LEN([domain])-3)
elseif  CONTAINS([domain], ".info") then LEFT([domain],LEN([domain])-5)
elseif  CONTAINS([domain], ".fr") then LEFT([domain],LEN([domain])-3)
elseif  CONTAINS([domain], ".es") then LEFT([domain],LEN([domain])-3)
elseif  CONTAINS([domain], ".pl") then LEFT([domain],LEN([domain])-3)
elseif  CONTAINS([domain], ".is") then LEFT([domain],LEN([domain])-3)
elseif  CONTAINS([domain], ".hu") then LEFT([domain],LEN([domain])-3)
elseif  CONTAINS([domain], ".xxx") then LEFT([domain],LEN([domain])-4)
elseif  CONTAINS([domain], ".nl") then LEFT([domain],LEN([domain])-3)
elseif  CONTAINS([domain], ".ro") then LEFT([domain],LEN([domain])-3)
elseif  CONTAINS([domain], ".xyz") then LEFT([domain],LEN([domain])-4)
elseif  CONTAINS([domain], ".no") then LEFT([domain],LEN([domain])-3)
elseif  CONTAINS([domain], ".eu") then LEFT([domain],LEN([domain])-3)
elseif  CONTAINS([domain], ".me") then LEFT([domain],LEN([domain])-3)
elseif  CONTAINS([domain], ".cz") then LEFT([domain],LEN([domain])-3)
elseif  CONTAINS([domain], ".fi") then LEFT([domain],LEN([domain])-3)
elseif  CONTAINS([domain], ".nl") then LEFT([domain],LEN([domain])-3)
elseif  CONTAINS([domain], ".al") then LEFT([domain],LEN([domain])-3)
elseif  CONTAINS([domain], ".am") then LEFT([domain],LEN([domain])-3)
elseif  CONTAINS([domain], ".af") then LEFT([domain],LEN([domain])-3)
elseif  CONTAINS([domain], ".st") then LEFT([domain],LEN([domain])-3)
elseif  CONTAINS([domain], ".cn") then LEFT([domain],LEN([domain])-3)
else [domain]
end
</code>```

答:
It's quite similar to what you have now, but use like instead of contains:</p>

```<code>IF domain like '%.co.uk' THEN left(domain,len(domain)-6)
IF domain like '%.com' THEN left(domain,len(domain)-4)
...
ELSE domain END AS stripped_domain
</code>```

Title: SQL Case Statement - how to do it

Body:
I have the below statement which works nicely in Tableau.

However, I'd like to turn this into SQL and save all the results into a temporary column name.

Does anyone know how I might do this?

Essentially, the below removes the .com/.net etc... from the domain name.

I then have another script that removes the subdomain (everything from the first . to the left of the resulting value).

If anyone can help me with these, that would be incredible as I'm not sure how to do this in SQL

IF CONTAINS([domain], ".co.uk") then LEFT([domain],LEN([domain])-6)
elseif  CONTAINS([domain], ".com") then LEFT([domain],LEN([domain])-4)
elseif  CONTAINS([domain], ".net") then LEFT([domain],LEN([domain])-4)
elseif  CONTAINS([domain], ".org") then LEFT([domain],LEN([domain])-4)
elseif  CONTAINS([domain], ".biz") then LEFT([domain],LEN([domain])-4)
elseif  CONTAINS([domain], ".edu") then LEFT([domain],LEN([domain])-4)
elseif  CONTAINS([domain], ".ac") then LEFT([domain],LEN([domain])-3)
elseif  CONTAINS([domain], ".gov") then LEFT([domain],LEN([domain])-4)
elseif  CONTAINS([domain], ".biz") then LEFT([domain],LEN([domain])-4)
elseif  CONTAINS([domain], ".co") then LEFT([domain],LEN([domain])-3)
elseif  CONTAINS([domain], ".ca") then LEFT([domain],LEN([domain])-3)
elseif  CONTAINS([domain], ".io") then LEFT([domain],LEN([domain])-3)
elseif  CONTAINS([domain], ".in") then LEFT([domain],LEN([domain])-3)
elseif  CONTAINS([domain], ".it") then LEFT([domain],LEN([domain])-3)
elseif  CONTAINS([domain], ".uk") then LEFT([domain],LEN([domain])- 3)
elseif  CONTAINS([domain], ".ru") then LEFT([domain],LEN([domain])-3)
elseif  CONTAINS([domain], ".ie") then LEFT([domain],LEN([domain])-3)
elseif  CONTAINS([domain], ".tv") then LEFT([domain],LEN([domain])-3)
elseif  CONTAINS([domain], ".info") then LEFT([domain],LEN([domain])-5)
elseif  CONTAINS([domain], ".fr") then LEFT([domain],LEN([domain])-3)
elseif  CONTAINS([domain], ".es") then LEFT([domain],LEN([domain])-3)
elseif  CONTAINS([domain], ".pl") then LEFT([domain],LEN([domain])-3)
elseif  CONTAINS([domain], ".is") then LEFT([domain],LEN([domain])-3)
elseif  CONTAINS([domain], ".hu") then LEFT([domain],LEN([domain])-3)
elseif  CONTAINS([domain], ".xxx") then LEFT([domain],LEN([domain])-4)
elseif  CONTAINS([domain], ".nl") then LEFT([domain],LEN([domain])-3)
elseif  CONTAINS([domain], ".ro") then LEFT([domain],LEN([domain])-3)
elseif  CONTAINS([domain], ".xyz") then LEFT([domain],LEN([domain])-4)
elseif  CONTAINS([domain], ".no") then LEFT([domain],LEN([domain])-3)
elseif  CONTAINS([domain], ".eu") then LEFT([domain],LEN([domain])-3)
elseif  CONTAINS([domain], ".me") then LEFT([domain],LEN([domain])-3)
elseif  CONTAINS([domain], ".cz") then LEFT([domain],LEN([domain])-3)
elseif  CONTAINS([domain], ".fi") then LEFT([domain],LEN([domain])-3)
elseif  CONTAINS([domain], ".nl") then LEFT([domain],LEN([domain])-3)
elseif  CONTAINS([domain], ".al") then LEFT([domain],LEN([domain])-3)
elseif  CONTAINS([domain], ".am") then LEFT([domain],LEN([domain])-3)
elseif  CONTAINS([domain], ".af") then LEFT([domain],LEN([domain])-3)
elseif  CONTAINS([domain], ".st") then LEFT([domain],LEN([domain])-3)
elseif  CONTAINS([domain], ".cn") then LEFT([domain],LEN([domain])-3)
else [domain]
end

Body:
It's quite similar to what you have now, but use like instead of contains:

IF domain like '%.co.uk' THEN left(domain,len(domain)-6)
IF domain like '%.com' THEN left(domain,len(domain)-4)
...
ELSE domain END AS stripped_domain


问:
Swift - how to get last taken 3 photos from photo library?
I need to get and show last taken 3 photos from photo library on viewDidload event without any clicks.

After this step, I should get other photos 3 by 3 when I scroll the ScrollView.

Do you know the proper way to do this with swift? Thanks.

答:
Details

Xcode 10.2 (10E125), Swift 5

Solution features

works in asynchronously and thread/queue safety

get albums ( + all photos album)

optimized for fast scrolling

get images with defined size

Info.plist

Add to Info.plist

```<code><key>NSPhotoLibraryUsageDescription</key>
<string>{bla-bla-bla}</string>
</code>```

Solution

AtomicArray here: https://stackoverflow.com/a/54565351/4488252

```<code>import UIKit
import Photos

enum PhotoAlbumViewModel {
    case regular(id: Int, title: String, count: Int, image: UIImage, isSelected: Bool)
    case allPhotos(id: Int, title: String, count: Int, image: UIImage, isSelected: Bool)

    var id: Int { switch self { case .regular(let params), .allPhotos(let params): return params.id } }
    var count: Int { switch self { case .regular(let params), .allPhotos(let params): return params.count } }
    var title: String { switch self { case .regular(let params), .allPhotos(let params): return params.title } }
}

class PhotoService {

    internal lazy var imageManager = PHCachingImageManager()

    private lazy var queue = DispatchQueue(label: "PhotoService_queue",
                                           qos: .default, attributes: .concurrent,
                                           autoreleaseFrequency: .workItem, target: nil)
    private lazy var getImagesQueue = DispatchQueue(label: "PhotoService_getImagesQueue",
                                                    qos: .userInteractive, attributes: [],
                                                    autoreleaseFrequency: .inherit, target: nil)
    private lazy var thumbnailSize = CGSize(width: 200, height: 200)
    private lazy var imageAlbumsIds = AtomicArray<Int>()
    private let getImageSemaphore = DispatchSemaphore(value: 12)

    typealias AlbumData = (fetchResult: PHFetchResult<PHAsset>, assetCollection: PHAssetCollection?)
    private let _cachedAlbumsDataSemaphore = DispatchSemaphore(value: 1)
    private lazy var _cachedAlbumsData = [Int: AlbumData]()

    deinit {
        print("____ PhotoServiceImpl deinited")
        imageManager.stopCachingImagesForAllAssets()
    }
}

// albums

extension PhotoService {

    private func getAlbumData(id: Int, completion: ((AlbumData?) -> Void)?) {
        _ = _cachedAlbumsDataSemaphore.wait(timeout: .now() + .seconds(3))
        if let cachedAlbum = _cachedAlbumsData[id] {
            completion?(cachedAlbum)
            _cachedAlbumsDataSemaphore.signal()
            return
        } else {
            _cachedAlbumsDataSemaphore.signal()
        }
        var result: AlbumData? = nil
        switch id {
            case 0:
                let fetchOptions = PHFetchOptions()
                fetchOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: true)]
                let allPhotos = PHAsset.fetchAssets(with: .image, options: fetchOptions)
                result = (allPhotos, nil)

            default:
                let collections = getAllAlbumsAssetCollections()
                let id = id - 1
                if  id < collections.count {
                    _fetchAssets(in: collections[id]) { fetchResult in
                        result = (fetchResult, collections[id])
                    }
                }
        }
        guard let _result = result else { completion?(nil); return }
        _ = _cachedAlbumsDataSemaphore.wait(timeout: .now() + .seconds(3))
        _cachedAlbumsData[id] = _result
        _cachedAlbumsDataSemaphore.signal()
        completion?(_result)
    }

    private func getAllAlbumsAssetCollections() -> PHFetchResult<PHAssetCollection> {
        let fetchOptions = PHFetchOptions()
        fetchOptions.sortDescriptors = [NSSortDescriptor(key: "endDate", ascending: true)]
        fetchOptions.predicate = NSPredicate(format: "estimatedAssetCount > 0")
        return PHAssetCollection.fetchAssetCollections(with: .album, subtype: .any, options: fetchOptions)
    }

    func getAllAlbums(completion: (([PhotoAlbumViewModel])->Void)?) {
        queue.async { [weak self] in
            guard let self = self else { return }
            var viewModels = AtomicArray<PhotoAlbumViewModel>()

            var allPhotosAlbumViewModel: PhotoAlbumViewModel?
            let dispatchGroup = DispatchGroup()
            dispatchGroup.enter()
            self.getAlbumData(id: 0) { data in
                   guard let data = data, let asset = data.fetchResult.lastObject else { dispatchGroup.leave(); return }
                self._fetchImage(from: asset, userInfo: nil, targetSize: self.thumbnailSize,
                                     deliveryMode: .fastFormat, resizeMode: .fast) { [weak self] (image, _) in
                                        guard let self = self, let image = image else { dispatchGroup.leave(); return }
                                        allPhotosAlbumViewModel = .allPhotos(id: 0, title: "All Photos",
                                                                             count: data.fetchResult.count,
                                                                             image: image, isSelected: false)
                                    self.imageAlbumsIds.append(0)
                                    dispatchGroup.leave()
                }
            }

            let numberOfAlbums = self.getAllAlbumsAssetCollections().count + 1
            for id in 1 ..< numberOfAlbums {
                dispatchGroup.enter()
                self.getAlbumData(id: id) { [weak self] data in
                    guard let self = self else { return }
                    guard let assetCollection = data?.assetCollection else { dispatchGroup.leave(); return }
                    self.imageAlbumsIds.append(id)
                    self.getAlbumViewModel(id: id, collection: assetCollection) { [weak self] model in
                        guard let self = self else { return }
                        defer { dispatchGroup.leave() }
                        guard let model = model else { return }
                        viewModels.append(model)
                    }
                }
            }

            _ = dispatchGroup.wait(timeout: .now() + .seconds(3))
            var _viewModels = [PhotoAlbumViewModel]()
            if let allPhotosAlbumViewModel = allPhotosAlbumViewModel {
                _viewModels.append(allPhotosAlbumViewModel)
            }
            _viewModels += viewModels.get()
            DispatchQueue.main.async { completion?(_viewModels) }
        }
    }

    private func getAlbumViewModel(id: Int, collection: PHAssetCollection, completion: ((PhotoAlbumViewModel?) -> Void)?) {
        _fetchAssets(in: collection) { [weak self] fetchResult in
            guard let self = self, let asset = fetchResult.lastObject else { completion?(nil); return }
            self._fetchImage(from: asset, userInfo: nil, targetSize: self.thumbnailSize,
                             deliveryMode: .fastFormat, resizeMode: .fast) { (image, nil) in
                                guard let image = image else { completion?(nil); return }
                                completion?(.regular(id: id,
                                                     title: collection.localizedTitle ?? "",
                                                     count: collection.estimatedAssetCount,
                                                     image: image, isSelected: false))
            }
        }
    }
}

// fetch

extension PhotoService {

    fileprivate func _fetchImage(from photoAsset: PHAsset,
                                 userInfo: [AnyHashable: Any]? = nil,
                                 targetSize: CGSize, //= PHImageManagerMaximumSize,
                                 deliveryMode: PHImageRequestOptionsDeliveryMode = .fastFormat,
                                 resizeMode: PHImageRequestOptionsResizeMode,
                                 completion: ((_ image: UIImage?, _ userInfo: [AnyHashable: Any]?) -> Void)?) {
        // guard authorizationStatus() == .authorized else { completion(nil); return }
        let options = PHImageRequestOptions()
        options.resizeMode = resizeMode
        options.isSynchronous = true
        options.deliveryMode = deliveryMode
        imageManager.requestImage(for: photoAsset,
                                  targetSize: targetSize,
                                  contentMode: .aspectFill,
                                  options: options) { (image, info) -> Void in
                                    guard   let info = info,
                                            let isImageDegraded = info[PHImageResultIsDegradedKey] as? Int,
                                            isImageDegraded == 0 else { completion?(nil, nil); return }
                                    completion?(image, userInfo)
        }
    }

    private func _fetchAssets(in collection: PHAssetCollection, completion: @escaping (PHFetchResult<PHAsset>) -> Void) {
        let fetchOptions = PHFetchOptions()
        fetchOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: true)]
        let assets = PHAsset.fetchAssets(in: collection, options: fetchOptions)
        completion(assets)
    }

    private func fetchImage(from asset: PHAsset,
                            userInfo: [AnyHashable: Any]?,
                            targetSize: CGSize,
                            deliveryMode: PHImageRequestOptionsDeliveryMode,
                            resizeMode: PHImageRequestOptionsResizeMode,
                            completion:  ((UIImage?, _ userInfo: [AnyHashable: Any]?) -> Void)?) {
        queue.async { [weak self] in
            self?._fetchImage(from: asset, userInfo: userInfo, targetSize: targetSize,
                              deliveryMode: deliveryMode, resizeMode: resizeMode) { (image, _) in
                                DispatchQueue.main.async { completion?(image, userInfo) }
            }
        }
    }

    func getImage(albumId: Int, index: Int,
                  userInfo: [AnyHashable: Any]?,
                  targetSize: CGSize,
                  deliveryMode: PHImageRequestOptionsDeliveryMode,
                  resizeMode: PHImageRequestOptionsResizeMode,
                  completion:  ((_ image: UIImage?, _ userInfo: [AnyHashable: Any]?) -> Void)?) {
        getImagesQueue.async { [weak self] in
            guard let self = self else { return }
            let indexPath = IndexPath(item: index, section: albumId)
            self.getAlbumData(id: albumId) { data in
                _ = self.getImageSemaphore.wait(timeout: .now() + .seconds(3))
                guard let photoAsset = data?.fetchResult.object(at: index) else { self.getImageSemaphore.signal(); return }
                self.fetchImage(from: photoAsset,
                                userInfo: userInfo,
                                targetSize: targetSize,
                                deliveryMode: deliveryMode,
                                resizeMode: resizeMode) { [weak self] (image, userInfo) in
                                    defer { self?.getImageSemaphore.signal() }
                                    completion?(image, userInfo)
                }
            }
        }
    }
}
</code>```

Usage

```<code>private lazy var photoLibrary = PhotoService()
private var albums = [PhotoAlbumViewModel]()
//....

// Get albums
photoLibrary.getAllAlbums { [weak self] albums in
    self?.albums = albums
    // reload views
}

// Get photo
photoLibrary.getImage(albumId: albums[0].id,
                      index: 1, userInfo: nil,
                      targetSize: CGSize(width: 200, height: 200),
                      deliveryMode: .fastFormat,
                      resizeMode: .fast) { [weak self, weak cell] (image, userInfo) in
                        // reload views
}
</code>```

Full Sample (collectionView with images from PhotoLibrary)

ViewController.swift

```<code>import UIKit
import Photos

class ViewController: UIViewController {

    private weak var collectionView: UICollectionView?
    var collectionViewFlowLayout: UICollectionViewFlowLayout? {
        return collectionView?.collectionViewLayout as? UICollectionViewFlowLayout
    }

    private lazy var photoLibrary = PhotoService()
    private lazy var numberOfElementsInRow = 4

    private lazy var cellIdentifier = "cellIdentifier"
    private lazy var supplementaryViewIdentifier = "supplementaryViewIdentifier"
    private var albums = [PhotoAlbumViewModel]()

    private lazy var cellsTags = [IndexPath: Int]()
    private lazy var tagKey = "cellTag"
    private lazy var thumbnailImageSize = CGSize(width: 200, height: 200)

    override func viewDidLoad() {

        let collectionViewFlowLayout = UICollectionViewFlowLayout()
        collectionViewFlowLayout.minimumLineSpacing = 5
        collectionViewFlowLayout.minimumInteritemSpacing = 5
        let _numberOfElementsInRow = CGFloat(numberOfElementsInRow)
        let allWidthBetwenCells = _numberOfElementsInRow == 0 ? 0 : collectionViewFlowLayout.minimumInteritemSpacing*(_numberOfElementsInRow-1)
        let width = (view.frame.width - allWidthBetwenCells)/_numberOfElementsInRow
        collectionViewFlowLayout.itemSize = CGSize(width: width, height: width)
        collectionViewFlowLayout.headerReferenceSize = CGSize(width: 0, height: 40)

        let collectionView = UICollectionView(frame: .zero, collectionViewLayout: collectionViewFlowLayout)
        view.addSubview(collectionView)
        collectionView.translatesAutoresizingMaskIntoConstraints = false
        collectionView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor).isActive = true
        collectionView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor).isActive = true
        collectionView.leftAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leftAnchor).isActive = true
        collectionView.rightAnchor.constraint(equalTo: view.safeAreaLayoutGuide.rightAnchor).isActive = true

        collectionView.register(CollectionViewCell.self, forCellWithReuseIdentifier: cellIdentifier)
        collectionView.register(SupplementaryView.self,
                                forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader,
                                withReuseIdentifier: supplementaryViewIdentifier)

        collectionView.backgroundColor = .white
        self.collectionView = collectionView
        collectionView.delegate = self
        showAllPhotosButtonTouchedInside()

        navigationItem.leftBarButtonItem = UIBarButtonItem(title: "All", style: .done, target: self,
                                                           action: #selector(showAllPhotosButtonTouchedInside))
        navigationItem.rightBarButtonItem = UIBarButtonItem(title: "last 3", style: .done, target: self,
                                                            action: #selector(showLastSeveralPhotosButtonTouchedInside))
    }

    @objc func showAllPhotosButtonTouchedInside() {
    photoLibrary.getAllAlbums { [weak self] albums in
        self?.set(albums: albums)
        if self?.collectionView?.dataSource == nil {
            self?.collectionView?.dataSource = self
        } else {
            self?.collectionView?.reloadData()
        }
    }
    }

    @objc func showLastSeveralPhotosButtonTouchedInside() {
        photoLibrary.getAllAlbums { [weak self] albums in
            guard let firstAlbum = albums.first else { return }
            var album: PhotoAlbumViewModel!
            let maxPhotosToDisplay = 3
            switch firstAlbum {
                case .allPhotos(let id, let title, let count, let image, let isSelected):
                    let newCount = count > maxPhotosToDisplay ? maxPhotosToDisplay : count
                    album = .allPhotos(id: id, title: title, count: newCount, image: image, isSelected: isSelected)
                case .regular(let id, let title, let count, let image, let isSelected):
                    let newCount = count > maxPhotosToDisplay ? maxPhotosToDisplay : count
                    album = .regular(id: id, title: title, count: newCount, image: image, isSelected: isSelected)
            }
            self?.set(albums: [album])
            if self?.collectionView?.dataSource == nil {
                self?.collectionView?.dataSource = self
            } else {
                self?.collectionView?.reloadData()
            }
        }
    }

    private func set(albums: [PhotoAlbumViewModel]) {
        self.albums = albums
        var counter = 0
        for (section, album) in albums.enumerated() {
            for row in 0..<album.count {
                self.cellsTags[IndexPath(row: row, section: section)] = counter
                counter += 1
            }
        }
    }
}

extension ViewController: UICollectionViewDataSource {

    func numberOfSections(in collectionView: UICollectionView) -> Int { return albums.count }
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return albums[section].count
    }

    func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
        let header = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: supplementaryViewIdentifier, for: indexPath) as! SupplementaryView
        header.label?.text = albums[indexPath.section].title
        return header
    }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellIdentifier, for: indexPath) as! CollectionViewCell
        let tag = cellsTags[indexPath]!
        cell.tag = tag
        photoLibrary.getImage(albumId: albums[indexPath.section].id,
                              index: indexPath.item, userInfo: [tagKey: tag],
                              targetSize: thumbnailImageSize,
                              deliveryMode: .fastFormat,
                              resizeMode: .fast) { [weak self, weak cell] (image, userInfo) in
                                guard   let cell = cell, let tagKey = self?.tagKey,
                                        let cellTag = userInfo?[tagKey] as? Int,
                                        cellTag == cell.tag else { return }
                                cell.imageView?.image = image
        }
        return cell
    }
}

extension ViewController: UICollectionViewDelegate {}
</code>```

CollectionViewCell.swift

```<code>import UIKit

class CollectionViewCell: UICollectionViewCell {
    weak var imageView: UIImageView?

    override init(frame: CGRect) {
        super.init(frame: frame)
        clipsToBounds = true
        let imageView = UIImageView(frame: .zero)
        imageView.contentMode = .scaleAspectFill
        addSubview(imageView)
        imageView.translatesAutoresizingMaskIntoConstraints = false
        imageView.topAnchor.constraint(equalTo: topAnchor).isActive = true
        imageView.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true
        imageView.leftAnchor.constraint(equalTo: leftAnchor).isActive = true
        imageView.rightAnchor.constraint(equalTo: rightAnchor).isActive = true
        self.imageView = imageView
        backgroundColor = UIColor.lightGray.withAlphaComponent(0.3)
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }

    override func prepareForReuse() {
        super.prepareForReuse()
        imageView?.image = nil
    }
}
</code>```

SupplementaryView.swift

```<code>import UIKit

class SupplementaryView: UICollectionReusableView {

    weak var label: UILabel?
    override init(frame: CGRect) {
        super.init(frame: frame)
        backgroundColor = .white
        let label = UILabel(frame: frame)
        label.textColor = .black
        addSubview(label)
        self.label = label
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }

    override func prepareForReuse() {
        super.prepareForReuse()
        self.label?.text = nil
    }
}
</code>```

Storyboard

Results

ContentLicense: CC BY-SA 4.0

Body:
Details

Xcode 10.2 (10E125), Swift 5

Solution features

works in asynchronously and thread/queue safety

get albums ( + all photos album)

optimized for fast scrolling

get images with defined size

Info.plist

Add to Info.plist

<key>NSPhotoLibraryUsageDescription</key>
<string>{bla-bla-bla}</string>

Solution

AtomicArray here: https://stackoverflow.com/a/54565351/4488252

import UIKit
import Photos

enum PhotoAlbumViewModel {
    case regular(id: Int, title: String, count: Int, image: UIImage, isSelected: Bool)
    case allPhotos(id: Int, title: String, count: Int, image: UIImage, isSelected: Bool)

    var id: Int { switch self { case .regular(let params), .allPhotos(let params): return params.id } }
    var count: Int { switch self { case .regular(let params), .allPhotos(let params): return params.count } }
    var title: String { switch self { case .regular(let params), .allPhotos(let params): return params.title } }
}

class PhotoService {

    internal lazy var imageManager = PHCachingImageManager()

    private lazy var queue = DispatchQueue(label: "PhotoService_queue",
                                           qos: .default, attributes: .concurrent,
                                           autoreleaseFrequency: .workItem, target: nil)
    private lazy var getImagesQueue = DispatchQueue(label: "PhotoService_getImagesQueue",
                                                    qos: .userInteractive, attributes: [],
                                                    autoreleaseFrequency: .inherit, target: nil)
    private lazy var thumbnailSize = CGSize(width: 200, height: 200)
    private lazy var imageAlbumsIds = AtomicArray<Int>()
    private let getImageSemaphore = DispatchSemaphore(value: 12)

    typealias AlbumData = (fetchResult: PHFetchResult<PHAsset>, assetCollection: PHAssetCollection?)
    private let _cachedAlbumsDataSemaphore = DispatchSemaphore(value: 1)
    private lazy var _cachedAlbumsData = [Int: AlbumData]()

    deinit {
        print("____ PhotoServiceImpl deinited")
        imageManager.stopCachingImagesForAllAssets()
    }
}

// albums

extension PhotoService {

    private func getAlbumData(id: Int, completion: ((AlbumData?) -> Void)?) {
        _ = _cachedAlbumsDataSemaphore.wait(timeout: .now() + .seconds(3))
        if let cachedAlbum = _cachedAlbumsData[id] {
            completion?(cachedAlbum)
            _cachedAlbumsDataSemaphore.signal()
            return
        } else {
            _cachedAlbumsDataSemaphore.signal()
        }
        var result: AlbumData? = nil
        switch id {
            case 0:
                let fetchOptions = PHFetchOptions()
                fetchOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: true)]
                let allPhotos = PHAsset.fetchAssets(with: .image, options: fetchOptions)
                result = (allPhotos, nil)

            default:
                let collections = getAllAlbumsAssetCollections()
                let id = id - 1
                if  id < collections.count {
                    _fetchAssets(in: collections[id]) { fetchResult in
                        result = (fetchResult, collections[id])
                    }
                }
        }
        guard let _result = result else { completion?(nil); return }
        _ = _cachedAlbumsDataSemaphore.wait(timeout: .now() + .seconds(3))
        _cachedAlbumsData[id] = _result
        _cachedAlbumsDataSemaphore.signal()
        completion?(_result)
    }

    private func getAllAlbumsAssetCollections() -> PHFetchResult<PHAssetCollection> {
        let fetchOptions = PHFetchOptions()
        fetchOptions.sortDescriptors = [NSSortDescriptor(key: "endDate", ascending: true)]
        fetchOptions.predicate = NSPredicate(format: "estimatedAssetCount > 0")
        return PHAssetCollection.fetchAssetCollections(with: .album, subtype: .any, options: fetchOptions)
    }

    func getAllAlbums(completion: (([PhotoAlbumViewModel])->Void)?) {
        queue.async { [weak self] in
            guard let self = self else { return }
            var viewModels = AtomicArray<PhotoAlbumViewModel>()

            var allPhotosAlbumViewModel: PhotoAlbumViewModel?
            let dispatchGroup = DispatchGroup()
            dispatchGroup.enter()
            self.getAlbumData(id: 0) { data in
                   guard let data = data, let asset = data.fetchResult.lastObject else { dispatchGroup.leave(); return }
                self._fetchImage(from: asset, userInfo: nil, targetSize: self.thumbnailSize,
                                     deliveryMode: .fastFormat, resizeMode: .fast) { [weak self] (image, _) in
                                        guard let self = self, let image = image else { dispatchGroup.leave(); return }
                                        allPhotosAlbumViewModel = .allPhotos(id: 0, title: "All Photos",
                                                                             count: data.fetchResult.count,
                                                                             image: image, isSelected: false)
                                    self.imageAlbumsIds.append(0)
                                    dispatchGroup.leave()
                }
            }

            let numberOfAlbums = self.getAllAlbumsAssetCollections().count + 1
            for id in 1 ..< numberOfAlbums {
                dispatchGroup.enter()
                self.getAlbumData(id: id) { [weak self] data in
                    guard let self = self else { return }
                    guard let assetCollection = data?.assetCollection else { dispatchGroup.leave(); return }
                    self.imageAlbumsIds.append(id)
                    self.getAlbumViewModel(id: id, collection: assetCollection) { [weak self] model in
                        guard let self = self else { return }
                        defer { dispatchGroup.leave() }
                        guard let model = model else { return }
                        viewModels.append(model)
                    }
                }
            }

            _ = dispatchGroup.wait(timeout: .now() + .seconds(3))
            var _viewModels = [PhotoAlbumViewModel]()
            if let allPhotosAlbumViewModel = allPhotosAlbumViewModel {
                _viewModels.append(allPhotosAlbumViewModel)
            }
            _viewModels += viewModels.get()
            DispatchQueue.main.async { completion?(_viewModels) }
        }
    }

    private func getAlbumViewModel(id: Int, collection: PHAssetCollection, completion: ((PhotoAlbumViewModel?) -> Void)?) {
        _fetchAssets(in: collection) { [weak self] fetchResult in
            guard let self = self, let asset = fetchResult.lastObject else { completion?(nil); return }
            self._fetchImage(from: asset, userInfo: nil, targetSize: self.thumbnailSize,
                             deliveryMode: .fastFormat, resizeMode: .fast) { (image, nil) in
                                guard let image = image else { completion?(nil); return }
                                completion?(.regular(id: id,
                                                     title: collection.localizedTitle ?? "",
                                                     count: collection.estimatedAssetCount,
                                                     image: image, isSelected: false))
            }
        }
    }
}

// fetch

extension PhotoService {

    fileprivate func _fetchImage(from photoAsset: PHAsset,
                                 userInfo: [AnyHashable: Any]? = nil,
                                 targetSize: CGSize, //= PHImageManagerMaximumSize,
                                 deliveryMode: PHImageRequestOptionsDeliveryMode = .fastFormat,
                                 resizeMode: PHImageRequestOptionsResizeMode,
                                 completion: ((_ image: UIImage?, _ userInfo: [AnyHashable: Any]?) -> Void)?) {
        // guard authorizationStatus() == .authorized else { completion(nil); return }
        let options = PHImageRequestOptions()
        options.resizeMode = resizeMode
        options.isSynchronous = true
        options.deliveryMode = deliveryMode
        imageManager.requestImage(for: photoAsset,
                                  targetSize: targetSize,
                                  contentMode: .aspectFill,
                                  options: options) { (image, info) -> Void in
                                    guard   let info = info,
                                            let isImageDegraded = info[PHImageResultIsDegradedKey] as? Int,
                                            isImageDegraded == 0 else { completion?(nil, nil); return }
                                    completion?(image, userInfo)
        }
    }

    private func _fetchAssets(in collection: PHAssetCollection, completion: @escaping (PHFetchResult<PHAsset>) -> Void) {
        let fetchOptions = PHFetchOptions()
        fetchOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: true)]
        let assets = PHAsset.fetchAssets(in: collection, options: fetchOptions)
        completion(assets)
    }

    private func fetchImage(from asset: PHAsset,
                            userInfo: [AnyHashable: Any]?,
                            targetSize: CGSize,
                            deliveryMode: PHImageRequestOptionsDeliveryMode,
                            resizeMode: PHImageRequestOptionsResizeMode,
                            completion:  ((UIImage?, _ userInfo: [AnyHashable: Any]?) -> Void)?) {
        queue.async { [weak self] in
            self?._fetchImage(from: asset, userInfo: userInfo, targetSize: targetSize,
                              deliveryMode: deliveryMode, resizeMode: resizeMode) { (image, _) in
                                DispatchQueue.main.async { completion?(image, userInfo) }
            }
        }
    }

    func getImage(albumId: Int, index: Int,
                  userInfo: [AnyHashable: Any]?,
                  targetSize: CGSize,
                  deliveryMode: PHImageRequestOptionsDeliveryMode,
                  resizeMode: PHImageRequestOptionsResizeMode,
                  completion:  ((_ image: UIImage?, _ userInfo: [AnyHashable: Any]?) -> Void)?) {
        getImagesQueue.async { [weak self] in
            guard let self = self else { return }
            let indexPath = IndexPath(item: index, section: albumId)
            self.getAlbumData(id: albumId) { data in
                _ = self.getImageSemaphore.wait(timeout: .now() + .seconds(3))
                guard let photoAsset = data?.fetchResult.object(at: index) else { self.getImageSemaphore.signal(); return }
                self.fetchImage(from: photoAsset,
                                userInfo: userInfo,
                                targetSize: targetSize,
                                deliveryMode: deliveryMode,
                                resizeMode: resizeMode) { [weak self] (image, userInfo) in
                                    defer { self?.getImageSemaphore.signal() }
                                    completion?(image, userInfo)
                }
            }
        }
    }
}

Usage

private lazy var photoLibrary = PhotoService()
private var albums = [PhotoAlbumViewModel]()
//....

// Get albums
photoLibrary.getAllAlbums { [weak self] albums in
    self?.albums = albums
    // reload views
}

// Get photo
photoLibrary.getImage(albumId: albums[0].id,
                      index: 1, userInfo: nil,
                      targetSize: CGSize(width: 200, height: 200),
                      deliveryMode: .fastFormat,
                      resizeMode: .fast) { [weak self, weak cell] (image, userInfo) in
                        // reload views
}

Full Sample (collectionView with images from PhotoLibrary)

ViewController.swift

import UIKit
import Photos

class ViewController: UIViewController {

    private weak var collectionView: UICollectionView?
    var collectionViewFlowLayout: UICollectionViewFlowLayout? {
        return collectionView?.collectionViewLayout as? UICollectionViewFlowLayout
    }

    private lazy var photoLibrary = PhotoService()
    private lazy var numberOfElementsInRow = 4

    private lazy var cellIdentifier = "cellIdentifier"
    private lazy var supplementaryViewIdentifier = "supplementaryViewIdentifier"
    private var albums = [PhotoAlbumViewModel]()

    private lazy var cellsTags = [IndexPath: Int]()
    private lazy var tagKey = "cellTag"
    private lazy var thumbnailImageSize = CGSize(width: 200, height: 200)

    override func viewDidLoad() {

        let collectionViewFlowLayout = UICollectionViewFlowLayout()
        collectionViewFlowLayout.minimumLineSpacing = 5
        collectionViewFlowLayout.minimumInteritemSpacing = 5
        let _numberOfElementsInRow = CGFloat(numberOfElementsInRow)
        let allWidthBetwenCells = _numberOfElementsInRow == 0 ? 0 : collectionViewFlowLayout.minimumInteritemSpacing*(_numberOfElementsInRow-1)
        let width = (view.frame.width - allWidthBetwenCells)/_numberOfElementsInRow
        collectionViewFlowLayout.itemSize = CGSize(width: width, height: width)
        collectionViewFlowLayout.headerReferenceSize = CGSize(width: 0, height: 40)

        let collectionView = UICollectionView(frame: .zero, collectionViewLayout: collectionViewFlowLayout)
        view.addSubview(collectionView)
        collectionView.translatesAutoresizingMaskIntoConstraints = false
        collectionView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor).isActive = true
        collectionView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor).isActive = true
        collectionView.leftAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leftAnchor).isActive = true
        collectionView.rightAnchor.constraint(equalTo: view.safeAreaLayoutGuide.rightAnchor).isActive = true

        collectionView.register(CollectionViewCell.self, forCellWithReuseIdentifier: cellIdentifier)
        collectionView.register(SupplementaryView.self,
                                forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader,
                                withReuseIdentifier: supplementaryViewIdentifier)

        collectionView.backgroundColor = .white
        self.collectionView = collectionView
        collectionView.delegate = self
        showAllPhotosButtonTouchedInside()

        navigationItem.leftBarButtonItem = UIBarButtonItem(title: "All", style: .done, target: self,
                                                           action: #selector(showAllPhotosButtonTouchedInside))
        navigationItem.rightBarButtonItem = UIBarButtonItem(title: "last 3", style: .done, target: self,
                                                            action: #selector(showLastSeveralPhotosButtonTouchedInside))
    }

    @objc func showAllPhotosButtonTouchedInside() {
    photoLibrary.getAllAlbums { [weak self] albums in
        self?.set(albums: albums)
        if self?.collectionView?.dataSource == nil {
            self?.collectionView?.dataSource = self
        } else {
            self?.collectionView?.reloadData()
        }
    }
    }

    @objc func showLastSeveralPhotosButtonTouchedInside() {
        photoLibrary.getAllAlbums { [weak self] albums in
            guard let firstAlbum = albums.first else { return }
            var album: PhotoAlbumViewModel!
            let maxPhotosToDisplay = 3
            switch firstAlbum {
                case .allPhotos(let id, let title, let count, let image, let isSelected):
                    let newCount = count > maxPhotosToDisplay ? maxPhotosToDisplay : count
                    album = .allPhotos(id: id, title: title, count: newCount, image: image, isSelected: isSelected)
                case .regular(let id, let title, let count, let image, let isSelected):
                    let newCount = count > maxPhotosToDisplay ? maxPhotosToDisplay : count
                    album = .regular(id: id, title: title, count: newCount, image: image, isSelected: isSelected)
            }
            self?.set(albums: [album])
            if self?.collectionView?.dataSource == nil {
                self?.collectionView?.dataSource = self
            } else {
                self?.collectionView?.reloadData()
            }
        }
    }

    private func set(albums: [PhotoAlbumViewModel]) {
        self.albums = albums
        var counter = 0
        for (section, album) in albums.enumerated() {
            for row in 0..<album.count {
                self.cellsTags[IndexPath(row: row, section: section)] = counter
                counter += 1
            }
        }
    }
}

extension ViewController: UICollectionViewDataSource {

    func numberOfSections(in collectionView: UICollectionView) -> Int { return albums.count }
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return albums[section].count
    }

    func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
        let header = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: supplementaryViewIdentifier, for: indexPath) as! SupplementaryView
        header.label?.text = albums[indexPath.section].title
        return header
    }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellIdentifier, for: indexPath) as! CollectionViewCell
        let tag = cellsTags[indexPath]!
        cell.tag = tag
        photoLibrary.getImage(albumId: albums[indexPath.section].id,
                              index: indexPath.item, userInfo: [tagKey: tag],
                              targetSize: thumbnailImageSize,
                              deliveryMode: .fastFormat,
                              resizeMode: .fast) { [weak self, weak cell] (image, userInfo) in
                                guard   let cell = cell, let tagKey = self?.tagKey,
                                        let cellTag = userInfo?[tagKey] as? Int,
                                        cellTag == cell.tag else { return }
                                cell.imageView?.image = image
        }
        return cell
    }
}

extension ViewController: UICollectionViewDelegate {}

CollectionViewCell.swift

import UIKit

class CollectionViewCell: UICollectionViewCell {
    weak var imageView: UIImageView?

    override init(frame: CGRect) {
        super.init(frame: frame)
        clipsToBounds = true
        let imageView = UIImageView(frame: .zero)
        imageView.contentMode = .scaleAspectFill
        addSubview(imageView)
        imageView.translatesAutoresizingMaskIntoConstraints = false
        imageView.topAnchor.constraint(equalTo: topAnchor).isActive = true
        imageView.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true
        imageView.leftAnchor.constraint(equalTo: leftAnchor).isActive = true
        imageView.rightAnchor.constraint(equalTo: rightAnchor).isActive = true
        self.imageView = imageView
        backgroundColor = UIColor.lightGray.withAlphaComponent(0.3)
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }

    override func prepareForReuse() {
        super.prepareForReuse()
        imageView?.image = nil
    }
}

SupplementaryView.swift

import UIKit

class SupplementaryView: UICollectionReusableView {

    weak var label: UILabel?
    override init(frame: CGRect) {
        super.init(frame: frame)
        backgroundColor = .white
        let label = UILabel(frame: frame)
        label.textColor = .black
        addSubview(label)
        self.label = label
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }

    override func prepareForReuse() {
        super.prepareForReuse()
        self.label?.text = nil
    }
}

Storyboard

Results


问:
How to add header and column to dataframe spark?
I have got a dataframe, on which I want to add a header and a first column
manually. Here is the dataframe :

```<code>import org.apache.spark.sql.SparkSession

val spark = SparkSession.builder.master("local").appName("my-spark-app").getOrCreate()
val df = spark.read.option("header",true).option("inferSchema",true).csv("C:\\gg.csv").cache()
</code>```

the content of the dataframe

```<code>12,13,14
11,10,5
3,2,45
</code>```

The expected output is

```<code>define,col1,col2,col3
c1,12,13,14
c2,11,10,5
c3,3,2,45
</code>```

答:
What you want to do is:

```<code>df.withColumn("columnName", column) //here "columnName" should be "define" for you
</code>```

Now you just need to create the said column (this might help)

Body:
I have got a dataframe, on which I want to add a header and a first column
manually. Here is the dataframe :

import org.apache.spark.sql.SparkSession

val spark = SparkSession.builder.master("local").appName("my-spark-app").getOrCreate()
val df = spark.read.option("header",true).option("inferSchema",true).csv("C:\\gg.csv").cache()

the content of the dataframe

12,13,14
11,10,5
3,2,45

The expected output is

define,col1,col2,col3
c1,12,13,14
c2,11,10,5
c3,3,2,45

Body:
What you want to do is:

df.withColumn("columnName", column) //here "columnName" should be "define" for you

Now you just need to create the said column (this might help)


问:
Spring context files organization and best practices
We have started using Spring framework in my project. After becoming acquainted with the basic features (IoC) we have started using spring aop and spring security as well.

The problem is that we now have more than 8 different context files and I feel we didn't give enough thought for the organization of those files and their roles. New files were introduced as the project evolved.
We have different context files for: metadata, aop, authorization, services, web resources (it's a RESTful application). So when a developer wants to add a new bean it's not always clear in which file he should add it. We need methodology.

The question:

Is there a best practice for spring files organization?

Should the context files encapsulate layers (DAL , Business Logic, Web) or use cases ? or Flows?

答: Breaking the config into separate files is useful to me in terms of testing.  On a small project, I'll put Spring Security config into "securityContext.xml" and the rest of my beans into "applicationContext.xml."  Then while running integration tests, it's easy to enable or disable security simple by choosing whether to include securityContext.xml.  This almost resembles AOP in a way, in that you add more functionality to the application by choosing whether to include particular files.</p>

OwnerDisplayName: LiorH


问:
Unable to use Qt + DXFLib
I'm going to use dxflib in my Qt application. Build process is OK but when I'm going to run it, the application stops working at the beginning with this error :

```<code>Unhandled exception at 0x776415de in DXFOpen.exe: 0xC00000FD: Stack overflow.
</code>```

Here is my simple app :

```<code>class CreatorAdaptor : public DL_CreationAdapter
{
    QGraphicsScene *_scene;
public:
    explicit CreatorAdaptor(QGraphicsScene *scene);
    virtual void addLine(const DL_LineData &d);
    virtual void addLayer(const DL_LayerData& data);
    virtual void addPoint(const DL_PointData& data);
    virtual void addArc(const DL_ArcData& data);
    virtual void addCircle(const DL_CircleData& data);
    virtual void addPolyline(const DL_PolylineData& data);
    virtual void addVertex(const DL_VertexData& data);
    virtual void add3dFace(const DL_3dFaceData& data);

};
</code>```

And the definition of the class :

```<code>CreatorAdaptor::CreatorAdaptor(QGraphicsScene *scene) :_scene(scene)
{
}

void CreatorAdaptor::addLine(const DL_LineData &d)
{
    qDebug()<<"add line";
    _scene->addLine(d.x1, d.y1, d.x2, d.y2);
}
...
</code>```

Here is my main :

```<code>int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QGraphicsView  *view = new QGraphicsView;
    QGraphicsScene  * scene = new QGraphicsScene;
    view->setScene(scene);
    CreatorAdaptor *dxfscene = new CreatorAdaptor(scene);
    DL_Dxf dxf;
     if(dxf.in("demo.dxf", dxfscene))
         QMessageBox::warning(0,"error", "error");
    view->show();
    return a.exec();
}
</code>```

Call Stack :

```<code>    ntdll.dll!77af15de()
    [Frames below may be incorrect and/or missing, no symbols loaded for ntdll.dll]
    ntdll.dll!77af15de()
    ntdll.dll!77ae014e()
    kernel32.dll!755e14dd()
>   msvcr100d.dll!_free_base(void * pBlock)  Line 50 + 0x13 bytes   C
    0041f648()
    QtCored4.dll!qFree(void * ptr)  Line 60 + 0xa bytes C++
    QtCored4.dll!QVectorData::free(QVectorData * x, int alignment)  Line 82 + 0x9 bytes C++
    QtCored4.dll!QVectorTypedData<char *>::free(QVectorTypedData<char *> * x, int alignment)  Line 99 + 0x10 bytes  C++
    QtCored4.dll!QVector<char *>::free(QVectorTypedData<char *> * x)  Line 468 + 0x12 bytes C++
    QtCored4.dll!QVector<char *>::~QVector<char *>()  Line 124 + 0x30 bytes C++
    QtCored4.dll!qWinMain(HINSTANCE__ * instance, HINSTANCE__ * prevInstance, char * cmdParam, int cmdShow, int & argc, QVector<char *> & argv)  Line 193   C++
    0041f7e0()
    DXFOpen.exe!__security_init_cookie()  Line 143  C
    DXFOpen.exe!WinMainCRTStartup()  Line 371   C
    kernel32.dll!755e339a()
    ntdll.dll!77b09ef2()
    ntdll.dll!77b09ec5()
</code>```

答:
I think you have to write all of the virtual functions as you did with below:

```<code>void CreatorAdaptor::addLine(const DL_LineData &d){
     // something something
}
</code>```

You may left empty them but you must define them because they are defined as virtual functions in the dxf library. Of course, the other option is to delete all of virtual function definitions in the CreatorAdaptor class.

Title: Unable to use Qt + DXFLib

Body:
I'm going to use dxflib in my Qt application. Build process is OK but when I'm going to run it, the application stops working at the beginning with this error :

Unhandled exception at 0x776415de in DXFOpen.exe: 0xC00000FD: Stack overflow.

Here is my simple app :

class CreatorAdaptor : public DL_CreationAdapter
{
    QGraphicsScene *_scene;
public:
    explicit CreatorAdaptor(QGraphicsScene *scene);
    virtual void addLine(const DL_LineData &d);
    virtual void addLayer(const DL_LayerData& data);
    virtual void addPoint(const DL_PointData& data);
    virtual void addArc(const DL_ArcData& data);
    virtual void addCircle(const DL_CircleData& data);
    virtual void addPolyline(const DL_PolylineData& data);
    virtual void addVertex(const DL_VertexData& data);
    virtual void add3dFace(const DL_3dFaceData& data);

};

And the definition of the class :

CreatorAdaptor::CreatorAdaptor(QGraphicsScene *scene) :_scene(scene)
{
}

void CreatorAdaptor::addLine(const DL_LineData &d)
{
    qDebug()<<"add line";
    _scene->addLine(d.x1, d.y1, d.x2, d.y2);
}
...

Here is my main :

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QGraphicsView  *view = new QGraphicsView;
    QGraphicsScene  * scene = new QGraphicsScene;
    view->setScene(scene);
    CreatorAdaptor *dxfscene = new CreatorAdaptor(scene);
    DL_Dxf dxf;
     if(dxf.in("demo.dxf", dxfscene))
         QMessageBox::warning(0,"error", "error");
    view->show();
    return a.exec();
}

Call Stack :

    ntdll.dll!77af15de()
    [Frames below may be incorrect and/or missing, no symbols loaded for ntdll.dll]
    ntdll.dll!77af15de()
    ntdll.dll!77ae014e()
    kernel32.dll!755e14dd()
>   msvcr100d.dll!_free_base(void * pBlock)  Line 50 + 0x13 bytes   C
    0041f648()
    QtCored4.dll!qFree(void * ptr)  Line 60 + 0xa bytes C++
    QtCored4.dll!QVectorData::free(QVectorData * x, int alignment)  Line 82 + 0x9 bytes C++
    QtCored4.dll!QVectorTypedData<char *>::free(QVectorTypedData<char *> * x, int alignment)  Line 99 + 0x10 bytes  C++
    QtCored4.dll!QVector<char *>::free(QVectorTypedData<char *> * x)  Line 468 + 0x12 bytes C++
    QtCored4.dll!QVector<char *>::~QVector<char *>()  Line 124 + 0x30 bytes C++
    QtCored4.dll!qWinMain(HINSTANCE__ * instance, HINSTANCE__ * prevInstance, char * cmdParam, int cmdShow, int & argc, QVector<char *> & argv)  Line 193   C++
    0041f7e0()
    DXFOpen.exe!__security_init_cookie()  Line 143  C
    DXFOpen.exe!WinMainCRTStartup()  Line 371   C
    kernel32.dll!755e339a()
    ntdll.dll!77b09ef2()
    ntdll.dll!77b09ec5()

Body:
I think you have to write all of the virtual functions as you did with below:

void CreatorAdaptor::addLine(const DL_LineData &d){
     // something something
}

You may left empty them but you must define them because they are defined as virtual functions in the dxf library. Of course, the other option is to delete all of virtual function definitions in the CreatorAdaptor class.


问:
Edittext cursor breaks in marshmallow rtl supported layout

I am facing weird issue in marshmallow.
When locale is ar and I type english text then cursor in edittext breaks

Refer screenshot

```<code><EditText
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:ems="10"
    android:gravity="left|start"
    android:hint="@string/app_name"
    android:inputType="textPassword"
    android:padding="10dp"
    android:textAlignment="viewStart"
    android:textDirection="locale">
    <requestFocus/>
</code>```

答:
I resolved it using below..

In your xml layout, for edit text field add this--> android:textDirection="anyRtl"

Here, "editText" is your view of edit text field. i.e,

```<code>EditText editText = (EditText) findViewById(R.id.edit_text);
</code>```

Then programatically add text watcher for that edit text.

```<code>    editText.addTextChangedListener(new TextWatcher() {
                @Override
                public void beforeTextChanged(CharSequence s, int start, int count, int after) {

                }

                @Override
                public void onTextChanged(CharSequence s, int start, int before, int count) {
                    editText.setSelection(s.length()); // this line is very important for setting cursor position
                }

                @Override
                public void afterTextChanged(Editable s) {

                }
            });
        }
</code>```

This worked for me!

Body:
I am facing weird issue in marshmallow.
When locale is ar and I type english text then cursor in edittext breaks

Refer screenshot

<EditText
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:ems="10"
    android:gravity="left|start"
    android:hint="@string/app_name"
    android:inputType="textPassword"
    android:padding="10dp"
    android:textAlignment="viewStart"
    android:textDirection="locale">
    <requestFocus/>

Body:
I resolved it using below..

In your xml layout, for edit text field add this--> android:textDirection="anyRtl"

Here, "editText" is your view of edit text field. i.e,

EditText editText = (EditText) findViewById(R.id.edit_text);

Then programatically add text watcher for that edit text.

    editText.addTextChangedListener(new TextWatcher() {
                @Override
                public void beforeTextChanged(CharSequence s, int start, int count, int after) {

                }

                @Override
                public void onTextChanged(CharSequence s, int start, int before, int count) {
                    editText.setSelection(s.length()); // this line is very important for setting cursor position
                }

                @Override
                public void afterTextChanged(Editable s) {

                }
            });
        }

This worked for me!


问:
How mod rewrite can impact on PHP, JS or AS3 variables and paths
Mod rewrite changes the look of URLs  but does it matter for server-side scripts (PHP)?

Does it change the $_GET[] in PHP? Will sth like:

if ( strpos($pulledId,':') > 0 ) {
$pulledId = substr($pulledId,0,strpos($pulledId,':'));
}

work, when there is no "id=" in diplayed URL?
How about JavaScript?
How about Flash? Can mod rewrite be a problem when loading external files from server ?

AS3 or JS are client-side scripts. So I assume they get URL as it is in a browser,
but PHP, JAVA are server-side, so they should get URL which haven't been processed by mod rewrite.

答:
No, $_GET does not change on the server. That is the main point of mod_rewrite.

On the client side, yes, the URI will be different — they can only see what's in the address bar.

With Java, it depends on where you're executing it, so see above for that also.


问:
Mongoose populate a field without ObjectId?
I have a schema:

```<code>var Schema = mongoose.Schema;

var TicketSchema = new Schema({
externalId: String,
name: String,
items: [{
    externalId: String,
    price: Number,
    quantity: {
        type: Number,
        default: 1
    },
    comment: {
        type: String,
        default: '',
        trim: true
    },
    entity: {
        type: String,
        ref: 'Entity'
    }
}],
tableId: String
});

mongoose.model('Ticket', TicketSchema);
</code>```

And I want to populate entity field with an unique field other than ObjectId.
How can I achieve that?

答:
Use crypto to hash something unique like the objectId , and then save it to your entities.

```<code>Var hash = crypto.createHmac('sha256', ticket.objectId).digest('hex');
</code>```

Ticket.entities= hash;

Body:
I have a schema:

var Schema = mongoose.Schema;

var TicketSchema = new Schema({
externalId: String,
name: String,
items: [{
    externalId: String,
    price: Number,
    quantity: {
        type: Number,
        default: 1
    },
    comment: {
        type: String,
        default: '',
        trim: true
    },
    entity: {
        type: String,
        ref: 'Entity'
    }
}],
tableId: String
});

mongoose.model('Ticket', TicketSchema);

And I want to populate entity field with an unique field other than ObjectId.
How can I achieve that?

Body:
Use crypto to hash something unique like the objectId , and then save it to your entities.

Var hash = crypto.createHmac('sha256', ticket.objectId).digest('hex');

Ticket.entities= hash;


问:
Why must I click twice to open and close my menu
Hello I got a situation which I do not understand quite well. I have the following setup:

 $(document).ready(function(){
  $('.menuBtn').on('click touch', function () {
  $(this).toggleClass('act');
   if($(this).hasClass('act')) {
    $('.mobileMenu').addClass('act');
    //$('body').addClass('positionfixed');
   }
   else {
    $('.mobileMenu').removeClass('act');
    //$('body').removeClass('positionfixed');
   }
 });
   });```
<pre class="snippet-code-css lang-css prettyprint-override"><code> .mobile-menu-button{
  display:block;
  position:fixed;
  top:20px;
  left:20px;
  z-index:99;
    background-color:#19b698;
    padding:5px 10px;
    color:#fff;
    font-family: Open Sans;
    font-weight:bold;
 }
 .mobile-menu-button i{
  font-size:26px;
  background-color:#00adee;
  padding:5px 10px;
  color:#fff;
 }
.mobileMenu {
  background-color: #fff !important;
  position: fixed;
  left: 0;
  top: 0;
  z-index: 100;
  height: 100vh;
  width: 100vw;
  display: block;
  text-align: center;
  opacity: 0;
  -webkit-transition: all 500ms cubic-bezier(0.68, -0.55, 0.265, 1.55);
  transition: all 500ms cubic-bezier(0.68, -0.55, 0.265, 1.55);
  -webkit-transform: scale(0);
     transform: scale(0);
  overflow:hidden;
 }
 .mobileMenu img{
  max-width:90%;
  margin:0 auto;
  margin-top:20px;
  margin-bottom:10px;
  border-bottom:1px dotted #717274;
  padding-bottom:20px;
 }
 .mobileMenu.act {
  opacity: 1;
  -webkit-transform: scale(1);
     transform: scale(1);
 }
 .mobileMenu.act ul li {
  opacity: 1;
  -webkit-transform: translateX(0);
     transform: translateX(0);
  display:block !important;
 }
 .mobileMenu ul {
  display: block;
  vertical-align: middle;
 }
 .mobileMenu li {
  padding: 10px 0 !important;
  -webkit-transition: all 400ms 510ms;
  transition: all 400ms 510ms;
  opacity: 0;
 }
 .mobileMenu li:nth-child(odd) {
   -webkit-transform: translateX(30%);
     transform: translateX(30%);
 }
 .mobileMenu li:nth-child(even) {
   -webkit-transform: translateX(-30%);
     transform: translateX(-30%);
 }
 .mobileMenu li:last-child {
   -webkit-transform: none;
     transform: none;
 }
 .mobileMenu a {
   color: #00adee !important;
   display: inline-block;
   font-size: 18px;
 }
 .mobileMenu a.suBtn {
   color: #fff;
 }</code>```

Open

  Close

Home

Testimonials

Contact

```

Why should I press two times on the open / close button to open / close the menu?

Anyone any idea / fix?

答:
The problem is that you checking for .act on the button instead of the menu. There are two buttons so you need to toggle twice.

Changing:

```<code>$(this).toggleClass('act');
if($(this).hasClass('act')) {
</code>```

to

```<code>$('.mobileMenu').toggleClass('act');
if($('.mobileMenu').hasClass('act')) {
</code>```

fixes it:

 $(document).ready(function(){
  $('.menuBtn').on('click touch', function () {
  $('.mobileMenu').toggleClass('act');
   if($('.mobileMenu').hasClass('act')) {
    $('.mobileMenu').addClass('act');
    //$('body').addClass('positionfixed');
   }
   else {
    $('.mobileMenu').removeClass('act');
    //$('body').removeClass('positionfixed');
   }
 });
   });```
<pre class="snippet-code-css lang-css prettyprint-override"><code> .mobile-menu-button{
  display:block;
  position:fixed;
  top:20px;
  left:20px;
  z-index:99;
    background-color:#19b698;
    padding:5px 10px;
    color:#fff;
    font-family: Open Sans;
    font-weight:bold;
 }
 .mobile-menu-button i{
  font-size:26px;
  background-color:#00adee;
  padding:5px 10px;
  color:#fff;
 }
.mobileMenu {
  background-color: #fff !important;
  position: fixed;
  left: 0;
  top: 0;
  z-index: 100;
  height: 100vh;
  width: 100vw;
  display: block;
  text-align: center;
  opacity: 0;
  -webkit-transition: all 500ms cubic-bezier(0.68, -0.55, 0.265, 1.55);
  transition: all 500ms cubic-bezier(0.68, -0.55, 0.265, 1.55);
  -webkit-transform: scale(0);
     transform: scale(0);
  overflow:hidden;
 }
 .mobileMenu img{
  max-width:90%;
  margin:0 auto;
  margin-top:20px;
  margin-bottom:10px;
  border-bottom:1px dotted #717274;
  padding-bottom:20px;
 }
 .mobileMenu.act {
  opacity: 1;
  -webkit-transform: scale(1);
     transform: scale(1);
 }
 .mobileMenu.act ul li {
  opacity: 1;
  -webkit-transform: translateX(0);
     transform: translateX(0);
  display:block !important;
 }
 .mobileMenu ul {
  display: block;
  vertical-align: middle;
 }
 .mobileMenu li {
  padding: 10px 0 !important;
  -webkit-transition: all 400ms 510ms;
  transition: all 400ms 510ms;
  opacity: 0;
 }
 .mobileMenu li:nth-child(odd) {
   -webkit-transform: translateX(30%);
     transform: translateX(30%);
 }
 .mobileMenu li:nth-child(even) {
   -webkit-transform: translateX(-30%);
     transform: translateX(-30%);
 }
 .mobileMenu li:last-child {
   -webkit-transform: none;
     transform: none;
 }
 .mobileMenu a {
   color: #00adee !important;
   display: inline-block;
   font-size: 18px;
 }
 .mobileMenu a.suBtn {
   color: #fff;
 }</code>```

Open

  Close

Home

Testimonials

Contact

```

Body:
Hello I got a situation which I do not understand quite well. I have the following setup:

 $(document).ready(function(){
  $('.menuBtn').on('click touch', function () {
  $(this).toggleClass('act');
   if($(this).hasClass('act')) {
    $('.mobileMenu').addClass('act');
    //$('body').addClass('positionfixed');
   }
   else {
    $('.mobileMenu').removeClass('act');
    //$('body').removeClass('positionfixed');
   }
 });
   });

 .mobile-menu-button{
  display:block;
  position:fixed;
  top:20px;
  left:20px;
  z-index:99;
    background-color:#19b698;
    padding:5px 10px;
    color:#fff;
    font-family: Open Sans;
    font-weight:bold;
 }
 .mobile-menu-button i{
  font-size:26px;
  background-color:#00adee;
  padding:5px 10px;
  color:#fff;
 }
.mobileMenu {
  background-color: #fff !important;
  position: fixed;
  left: 0;
  top: 0;
  z-index: 100;
  height: 100vh;
  width: 100vw;
  display: block;
  text-align: center;
  opacity: 0;
  -webkit-transition: all 500ms cubic-bezier(0.68, -0.55, 0.265, 1.55);
  transition: all 500ms cubic-bezier(0.68, -0.55, 0.265, 1.55);
  -webkit-transform: scale(0);
     transform: scale(0);
  overflow:hidden;
 }
 .mobileMenu img{
  max-width:90%;
  margin:0 auto;
  margin-top:20px;
  margin-bottom:10px;
  border-bottom:1px dotted #717274;
  padding-bottom:20px;
 }
 .mobileMenu.act {
  opacity: 1;
  -webkit-transform: scale(1);
     transform: scale(1);
 }
 .mobileMenu.act ul li {
  opacity: 1;
  -webkit-transform: translateX(0);
     transform: translateX(0);
  display:block !important;
 }
 .mobileMenu ul {
  display: block;
  vertical-align: middle;
 }
 .mobileMenu li {
  padding: 10px 0 !important;
  -webkit-transition: all 400ms 510ms;
  transition: all 400ms 510ms;
  opacity: 0;
 }
 .mobileMenu li:nth-child(odd) {
   -webkit-transform: translateX(30%);
     transform: translateX(30%);
 }
 .mobileMenu li:nth-child(even) {
   -webkit-transform: translateX(-30%);
     transform: translateX(-30%);
 }
 .mobileMenu li:last-child {
   -webkit-transform: none;
     transform: none;
 }
 .mobileMenu a {
   color: #00adee !important;
   display: inline-block;
   font-size: 18px;
 }
 .mobileMenu a.suBtn {
   color: #fff;
 }

Open

  Close

Home

Testimonials

Contact

Why should I press two times on the open / close button to open / close the menu?

Anyone any idea / fix?

Body:
The problem is that you checking for .act on the button instead of the menu. There are two buttons so you need to toggle twice.

Changing:

$(this).toggleClass('act');
if($(this).hasClass('act')) {

to

$('.mobileMenu').toggleClass('act');
if($('.mobileMenu').hasClass('act')) {

fixes it:

 $(document).ready(function(){
  $('.menuBtn').on('click touch', function () {
  $('.mobileMenu').toggleClass('act');
   if($('.mobileMenu').hasClass('act')) {
    $('.mobileMenu').addClass('act');
    //$('body').addClass('positionfixed');
   }
   else {
    $('.mobileMenu').removeClass('act');
    //$('body').removeClass('positionfixed');
   }
 });
   });

 .mobile-menu-button{
  display:block;
  position:fixed;
  top:20px;
  left:20px;
  z-index:99;
    background-color:#19b698;
    padding:5px 10px;
    color:#fff;
    font-family: Open Sans;
    font-weight:bold;
 }
 .mobile-menu-button i{
  font-size:26px;
  background-color:#00adee;
  padding:5px 10px;
  color:#fff;
 }
.mobileMenu {
  background-color: #fff !important;
  position: fixed;
  left: 0;
  top: 0;
  z-index: 100;
  height: 100vh;
  width: 100vw;
  display: block;
  text-align: center;
  opacity: 0;
  -webkit-transition: all 500ms cubic-bezier(0.68, -0.55, 0.265, 1.55);
  transition: all 500ms cubic-bezier(0.68, -0.55, 0.265, 1.55);
  -webkit-transform: scale(0);
     transform: scale(0);
  overflow:hidden;
 }
 .mobileMenu img{
  max-width:90%;
  margin:0 auto;
  margin-top:20px;
  margin-bottom:10px;
  border-bottom:1px dotted #717274;
  padding-bottom:20px;
 }
 .mobileMenu.act {
  opacity: 1;
  -webkit-transform: scale(1);
     transform: scale(1);
 }
 .mobileMenu.act ul li {
  opacity: 1;
  -webkit-transform: translateX(0);
     transform: translateX(0);
  display:block !important;
 }
 .mobileMenu ul {
  display: block;
  vertical-align: middle;
 }
 .mobileMenu li {
  padding: 10px 0 !important;
  -webkit-transition: all 400ms 510ms;
  transition: all 400ms 510ms;
  opacity: 0;
 }
 .mobileMenu li:nth-child(odd) {
   -webkit-transform: translateX(30%);
     transform: translateX(30%);
 }
 .mobileMenu li:nth-child(even) {
   -webkit-transform: translateX(-30%);
     transform: translateX(-30%);
 }
 .mobileMenu li:last-child {
   -webkit-transform: none;
     transform: none;
 }
 .mobileMenu a {
   color: #00adee !important;
   display: inline-block;
   font-size: 18px;
 }
 .mobileMenu a.suBtn {
   color: #fff;
 }

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<span class="mobile-menu-button menuBtn">Open</span>
  <nav class="mobileMenu">
  <span class="mobile-menu-button menuBtn">Close</span>
  <ul>
    <li><a href="index.html">Home</a></li>
    <li><a href="testimonials.html">Testimonials</a></li>
    <li><a href="contact.html">Contact</a></li>
  </ul>
</nav>


问:
12 month rolling from a entered month?
Hi can someone please help me, I want to create a script with a month parameter, the results I require is the next 12 month's names as column headings.

For example if the parameter is February the results should be:

```<code>March | April | May | June | July | August | September | October | November | December | January | February |
</code>```

As the column names which I want to use to fill in values at a later stage.
Can someone please advise me on this and how I can achieve this

My script I have so far don't know how to approach this

```<code>declare @MonthParam varchar(20) = 'March'
declare @MonthNumber int = (
Select CASE WHEN @MonthParam = 'January' THEN 1
            WHEN @MonthParam = 'February' THEN 2
            WHEN @MonthParam = 'March' THEN 3
            WHEN @MonthParam = 'April' THEN 4
            WHEN @MonthParam = 'May' THEN 5
            WHEN @MonthParam = 'June' THEN 6
            WHEN @MonthParam = 'July' THEN 7
            WHEN @MonthParam = 'August' THEN 8
            WHEN @MonthParam = 'September' THEN 9
            WHEN @MonthParam = 'October' THEN 10
            WHEN @MonthParam = 'November' THEN 11
            WHEN @MonthParam = 'December' THEN 12
END)
WHILE(@MonthNumber < 13)

    BEGIN

    declare @month varchar(20) = DateName( month , DateAdd( month , @MonthNumber , 0 ) - 1 )
    declare @sql varchar(max)
    set @sql = 'select val as ' + @month + ' from t'
    exec (@sql)

    SET @MonthNumber = @MonthNumber + 1;

    END
</code>```

答:
Other wise you can use the "simplified" approach.</p>

```<code>declare @MonthParam varchar(20) = 'March'
declare @Dte date = CAST(concat(@MonthParam, ' 01 1900') AS DATE)
declare @sql varchar(max) = concat('select null as ', DATENAME(MONTH, DATEADD(MONTH, 1, @Dte)),
                    ', null as ', DATENAME(MONTH, DATEADD(MONTH, 2, @Dte)),
                    ',null as ',DATENAME(MONTH, DATEADD(MONTH, 3, @Dte)),
                    ',null as ',DATENAME(MONTH, DATEADD(MONTH, 4, @Dte)),
                    ',null as ',DATENAME(MONTH, DATEADD(MONTH, 5, @Dte)),
                    ',null as ',DATENAME(MONTH, DATEADD(MONTH, 6, @Dte)),
                    ',null as ',DATENAME(MONTH, DATEADD(MONTH, 7, @Dte)),
                    ',null as ',DATENAME(MONTH, DATEADD(MONTH, 8, @Dte)),
                    ',null as ',DATENAME(MONTH, DATEADD(MONTH, 9, @Dte)),
                    ',null as ',DATENAME(MONTH, DATEADD(MONTH, 10, @Dte)),
                    ',null as ',DATENAME(MONTH, DATEADD(MONTH, 11, @Dte)),
                    ',null as ',DATENAME(MONTH, DATEADD(MONTH, 12, @Dte)))
 exec (@sql)
</code>```

Title: 12 month rolling from a entered month?

Body:
Hi can someone please help me, I want to create a script with a month parameter, the results I require is the next 12 month's names as column headings.

For example if the parameter is February the results should be:

March | April | May | June | July | August | September | October | November | December | January | February |

As the column names which I want to use to fill in values at a later stage.
Can someone please advise me on this and how I can achieve this

My script I have so far don't know how to approach this

declare @MonthParam varchar(20) = 'March'
declare @MonthNumber int = (
Select CASE WHEN @MonthParam = 'January' THEN 1
            WHEN @MonthParam = 'February' THEN 2
            WHEN @MonthParam = 'March' THEN 3
            WHEN @MonthParam = 'April' THEN 4
            WHEN @MonthParam = 'May' THEN 5
            WHEN @MonthParam = 'June' THEN 6
            WHEN @MonthParam = 'July' THEN 7
            WHEN @MonthParam = 'August' THEN 8
            WHEN @MonthParam = 'September' THEN 9
            WHEN @MonthParam = 'October' THEN 10
            WHEN @MonthParam = 'November' THEN 11
            WHEN @MonthParam = 'December' THEN 12
END)
WHILE(@MonthNumber < 13)

    BEGIN

    declare @month varchar(20) = DateName( month , DateAdd( month , @MonthNumber , 0 ) - 1 )
    declare @sql varchar(max)
    set @sql = 'select val as ' + @month + ' from t'
    exec (@sql)

    SET @MonthNumber = @MonthNumber + 1;

    END

Body:
Other wise you can use the "simplified" approach.

declare @MonthParam varchar(20) = 'March'
declare @Dte date = CAST(concat(@MonthParam, ' 01 1900') AS DATE)
declare @sql varchar(max) = concat('select null as ', DATENAME(MONTH, DATEADD(MONTH, 1, @Dte)),
                    ', null as ', DATENAME(MONTH, DATEADD(MONTH, 2, @Dte)),
                    ',null as ',DATENAME(MONTH, DATEADD(MONTH, 3, @Dte)),
                    ',null as ',DATENAME(MONTH, DATEADD(MONTH, 4, @Dte)),
                    ',null as ',DATENAME(MONTH, DATEADD(MONTH, 5, @Dte)),
                    ',null as ',DATENAME(MONTH, DATEADD(MONTH, 6, @Dte)),
                    ',null as ',DATENAME(MONTH, DATEADD(MONTH, 7, @Dte)),
                    ',null as ',DATENAME(MONTH, DATEADD(MONTH, 8, @Dte)),
                    ',null as ',DATENAME(MONTH, DATEADD(MONTH, 9, @Dte)),
                    ',null as ',DATENAME(MONTH, DATEADD(MONTH, 10, @Dte)),
                    ',null as ',DATENAME(MONTH, DATEADD(MONTH, 11, @Dte)),
                    ',null as ',DATENAME(MONTH, DATEADD(MONTH, 12, @Dte)))
 exec (@sql)