问:
dplyr - filter by group size
What is the best way to filter a data.frame to only get groups of say size 5?

So my data looks as follows:

```<code>require(dplyr)
n <- 1e5
x <- rnorm(n)
# Category size ranging each from 1 to 5
cat <- rep(seq_len(n/3), sample(1:5, n/3, replace = TRUE))[1:n]

dat <- data.frame(x = x, cat = cat)
</code>```

The dplyr way i could come up with was

```<code>dat <- group_by(dat, cat)

system.time({
  out1 <- dat %>% filter(n() == 5L)
})
#    user  system elapsed
#   1.157   0.218   1.497
</code>```

But this is very slow... Is there a better way in dplyr?

So far my workaround solutions looks as follows:

```<code>system.time({
  all_ind <- rep(seq_len(n_groups(dat)), group_size(dat))
  take_only <- which(group_size(dat) == 5L)
  out2 <- dat[all_ind %in% take_only, ]
})
#    user  system elapsed
#   0.026   0.008   0.036
all.equal(out1, out2) # TRUE
</code>```

But this doesn't feel very dplyr like...

答:
Comparing the answers timewise:

```<code>require(dplyr)
require(data.table)
n <- 1e5
x <- rnorm(n)
# Category size ranging each from 1 to 5
cat <- rep(seq_len(n/3), sample(1:5, n/3, replace = TRUE))[1:n]

dat <- data.frame(x = x, cat = cat)

# second data set for the dt approch
dat2 <- data.frame(x = x, cat = cat)

sol_floo0 <- function(dat){
  dat <- group_by(dat, cat)
  all_ind <- rep(seq_len(n_groups(dat)), group_size(dat))
  take_only <- which(group_size(dat) == 5L)
  dat[all_ind %in% take_only, ]
}

sol_floo0_v2 <- function(dat){
  g <- group_by(dat, cat) %>% group_size()
  ind <- rep(g == 5, g)
  dat[ind, ]
}

sol_docendo_discimus <- function(dat){
  dat <- group_by(dat, cat)
  semi_join(dat, count(dat, cat) %>% filter(n == 5), by = "cat")
}

sol_akrun <- function(dat2){
  setDT(dat2)[dat2[, .I[.N==5], by = cat]$V1]
}

sol_sotos <- function(dat2){
  setDT(dat2)[, if(.N == 5) .SD, by = cat]
}

sol_chirayu_chamoli <- function(dat){
  rle_ <- rle(dat$cat)
  dat[dat$cat %in% rle_$values[rle_$lengths==5], ]
}

microbenchmark::microbenchmark(times = 20,
                               sol_floo0(dat),
                               sol_floo0_v2(dat),
                               sol_docendo_discimus(dat),
                               sol_akrun(dat2),
                               sol_sotos(dat2),
                               sol_chirayu_chamoli(dat))
</code>```

Results in:

```<code>Unit: milliseconds
                      expr       min        lq      mean    median        uq       max neval  cld
            sol_floo0(dat)  58.00439  65.28063  93.54014  69.82658  82.79997 280.23114    20   cd
         sol_floo0_v2(dat)  42.27791  50.27953  72.51729  58.63931  67.62540 238.97413    20  bc
 sol_docendo_discimus(dat) 100.54095 113.15476 126.74142 121.69013 132.62533 183.05818    20    d
           sol_akrun(dat2)  26.88369  34.01925  41.04378  37.07957  45.44784  63.95430    20 ab
           sol_sotos(dat2)  16.10177  19.78403  24.04375  23.06900  28.05470  35.83611    20 a
  sol_chirayu_chamoli(dat)  20.67951  24.18100  38.01172  27.61618  31.97834 230.51026    20 ab
</code>```

Title: dplyr - filter by group size

Body:
What is the best way to filter a data.frame to only get groups of say size 5?

So my data looks as follows:

require(dplyr)
n <- 1e5
x <- rnorm(n)
# Category size ranging each from 1 to 5
cat <- rep(seq_len(n/3), sample(1:5, n/3, replace = TRUE))[1:n]

dat <- data.frame(x = x, cat = cat)

The dplyr way i could come up with was

dat <- group_by(dat, cat)

system.time({
  out1 <- dat %>% filter(n() == 5L)
})
#    user  system elapsed
#   1.157   0.218   1.497

But this is very slow... Is there a better way in dplyr?

So far my workaround solutions looks as follows:

system.time({
  all_ind <- rep(seq_len(n_groups(dat)), group_size(dat))
  take_only <- which(group_size(dat) == 5L)
  out2 <- dat[all_ind %in% take_only, ]
})
#    user  system elapsed
#   0.026   0.008   0.036
all.equal(out1, out2) # TRUE

But this doesn't feel very dplyr like...

Body:
Comparing the answers timewise:

require(dplyr)
require(data.table)
n <- 1e5
x <- rnorm(n)
# Category size ranging each from 1 to 5
cat <- rep(seq_len(n/3), sample(1:5, n/3, replace = TRUE))[1:n]

dat <- data.frame(x = x, cat = cat)

# second data set for the dt approch
dat2 <- data.frame(x = x, cat = cat)

sol_floo0 <- function(dat){
  dat <- group_by(dat, cat)
  all_ind <- rep(seq_len(n_groups(dat)), group_size(dat))
  take_only <- which(group_size(dat) == 5L)
  dat[all_ind %in% take_only, ]
}

sol_floo0_v2 <- function(dat){
  g <- group_by(dat, cat) %>% group_size()
  ind <- rep(g == 5, g)
  dat[ind, ]
}

sol_docendo_discimus <- function(dat){
  dat <- group_by(dat, cat)
  semi_join(dat, count(dat, cat) %>% filter(n == 5), by = "cat")
}

sol_akrun <- function(dat2){
  setDT(dat2)[dat2[, .I[.N==5], by = cat]$V1]
}

sol_sotos <- function(dat2){
  setDT(dat2)[, if(.N == 5) .SD, by = cat]
}

sol_chirayu_chamoli <- function(dat){
  rle_ <- rle(dat$cat)
  dat[dat$cat %in% rle_$values[rle_$lengths==5], ]
}

microbenchmark::microbenchmark(times = 20,
                               sol_floo0(dat),
                               sol_floo0_v2(dat),
                               sol_docendo_discimus(dat),
                               sol_akrun(dat2),
                               sol_sotos(dat2),
                               sol_chirayu_chamoli(dat))

Results in:

Unit: milliseconds
                      expr       min        lq      mean    median        uq       max neval  cld
            sol_floo0(dat)  58.00439  65.28063  93.54014  69.82658  82.79997 280.23114    20   cd
         sol_floo0_v2(dat)  42.27791  50.27953  72.51729  58.63931  67.62540 238.97413    20  bc
 sol_docendo_discimus(dat) 100.54095 113.15476 126.74142 121.69013 132.62533 183.05818    20    d
           sol_akrun(dat2)  26.88369  34.01925  41.04378  37.07957  45.44784  63.95430    20 ab
           sol_sotos(dat2)  16.10177  19.78403  24.04375  23.06900  28.05470  35.83611    20 a
  sol_chirayu_chamoli(dat)  20.67951  24.18100  38.01172  27.61618  31.97834 230.51026    20 ab


来源: stackexchange

问:
Best options for animation in THREE.JS
What is the best options for animations (texture animations, moving objects, hiding/showing object,...) in three.js ? Do you use extra lib. such as tween.js or something else ? Thanks.</p>

答:
small roundup in 2017: check out this simple timeline-lib which can easily trigger the above mentioned FSM (statebased anim) & tween.js (smooth anim):

keyframes

ContentLicense: CC BY-SA 3.0

Title: Best options for animation in THREE.JS


问:
Sort NSArray with a specific key
I'm have requested an array from server and now I wanna filter all data which have "status_read": 1 in an new array. How can I do it? This is my data response:

```<code>{
  "status": "success",
  "message": "success",
  "data": [
    {
      "logo": "http://**.com/timepicker/images/default_o.jpg",
      "title": "Title 1",
      "icon": "https://**.com/admin/dashboard/dist/img/a.png",
      "type": 1,
      "link_detail": "",
      "id_call": 12,
      "status_read": 1
    },
    {
      "logo": "http://**.com/timepicker/images/default_go.jpg",
      "title": "Title 2",
      "icon": "https://**.com/admin/dashboard/dist/img/b.png",
      "type": 0,
      "link_detail": "http://google.com",
      "id_call": 0,
      "status_read": 0
    }
  ]
}
</code>```

Here is my code for filter array:

```<code>NSString *dictionaryKey = @"status_read";
NSInteger predicateValue = 1;
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"%K == %i", dictionaryKey, predicateValue];
NSArray *filteredArr = [readNotif filteredArrayUsingPredicate:predicate];
generalArray = filteredArr;
[self.notifTableView reloadData];
</code>```

答:
```<code>NSArray *arr = [result_dic valueForKey:@"data"];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"%K == %@",@"status_read",@"1"];

NSArray *filteredArray = [arr filteredArrayUsingPredicate:predicate];
NSLog(@"Filtered Array: %@",filteredArray);
</code>```

Title: Sort NSArray with a specific key

Body:
I'm have requested an array from server and now I wanna filter all data which have "status_read": 1 in an new array. How can I do it? This is my data response:

{
  "status": "success",
  "message": "success",
  "data": [
    {
      "logo": "http://**.com/timepicker/images/default_o.jpg",
      "title": "Title 1",
      "icon": "https://**.com/admin/dashboard/dist/img/a.png",
      "type": 1,
      "link_detail": "",
      "id_call": 12,
      "status_read": 1
    },
    {
      "logo": "http://**.com/timepicker/images/default_go.jpg",
      "title": "Title 2",
      "icon": "https://**.com/admin/dashboard/dist/img/b.png",
      "type": 0,
      "link_detail": "http://google.com",
      "id_call": 0,
      "status_read": 0
    }
  ]
}

Here is my code for filter array:

NSString *dictionaryKey = @"status_read";
NSInteger predicateValue = 1;
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"%K == %i", dictionaryKey, predicateValue];
NSArray *filteredArr = [readNotif filteredArrayUsingPredicate:predicate];
generalArray = filteredArr;
[self.notifTableView reloadData];


问:
Oracle recovery problem
I execute the following command and the error occurs:

```<code>recover database until time '2009-01-09 12:26';
ORA-00283: recovery session canceled due to errors
ORA-19907: recovery time or SCN does not belong to recovered incarnation;
</code>```

How can I solve this problem?

答:
There's a suggested action here

I'm not an Oracle user, so that's as far as I can go.  Just Googling the code found that though.

OwnerDisplayName: Chinar

ContentLicense: CC BY-SA 2.5

Title: Oracle recovery problem

Body:
I execute the following command and the error occurs:

recover database until time '2009-01-09 12:26';
ORA-00283: recovery session canceled due to errors
ORA-19907: recovery time or SCN does not belong to recovered incarnation;

How can I solve this problem?

OwnerDisplayName: ChrisA


问:
How to correctly implement "hamburger" to back button functionality when using Fragments
How to move to a new fragment and automatically have the "hamburger" menu change to a <- button which brings the user back to the previous menu?

This seems to be an arcane art, no matter how many stackoverflow questions I read and things I try the "hamburger" menu always just opens the drawer. I am getting confused with certain posts using backstacklisteners to change icons, others using the onoptionselected and others directly attaching a click listener.

Activity

```<code>    public class MainActivity extends AppCompatActivity {

        private ActionBarDrawerToggle drawerToggle;
        private ActionBar actionBar;

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            setToolbar();
            // show first fragment here
        }

        private void setToolbar() {
            Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
            setSupportActionBar(toolbar);
            actionBar = getSupportActionBar();

            if (actionBar != null) {
                actionBar.setDisplayHomeAsUpEnabled(true);
                DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer);
                drawerToggle = new ActionBarDrawerToggle(this, drawer, toolbar, R.string.open, R.string.close);
                drawerToggle.setDrawerIndicatorEnabled(true);
                drawerToggle.syncState();
            }
        }

        @Override
        protected void onPostCreate(Bundle savedInstanceState) {
            super.onPostCreate(savedInstanceState);
            drawerToggle.syncState();
        }

        @Override
        public void onConfigurationChanged(Configuration newConfig) {
            super.onConfigurationChanged(newConfig);
            drawerToggle.onConfigurationChanged(newConfig);
        }

        @Override
        public boolean onCreateOptionsMenu(Menu menu) {

    getMenuInflater().inflate(R.menu.toolbar_menu, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case R.id.mnuSettings:
                showSettingsFragment();
                return true;
            default:
                return super.onOptionsItemSelected(item);
        }
    }

    private void showSettingsFragment() {
        getFragmentManager()
                .beginTransaction()
                .replace(R.id.fragHolder, new SettingsFragment())
                .addToBackStack(null)
                .commit();
    }
}
</code>```

Activity Layout

```<code><?xml version="1.0" encoding="utf-8"?>

<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
                                        xmlns:app="http://schemas.android.com/apk/res-auto"
                                        xmlns:tools="http://schemas.android.com/tools"
                                        android:id="@+id/drawer"
                                        android:layout_width="match_parent"
                                        android:layout_height="match_parent"
                                        android:fitsSystemWindows="true">

    <LinearLayout
         android:layout_width="match_parent"
         android:layout_height="match_parent"
         android:orientation="vertical">

        <android.support.design.widget.AppBarLayout
             android:layout_width="match_parent"
             android:layout_height="wrap_content">

            <android.support.v7.widget.Toolbar
                 android:id="@+id/toolbar"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
                 android:background="@color/primary"
                 android:minHeight="?attr/actionBarSize"
                 app:popupTheme="@style/Theme.AppCompat.Light"
                 app:theme="@style/Theme.AppCompat">

            </android.support.v7.widget.Toolbar>

            <FrameLayout
                 android:id="@+id/pnlSearch"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
                 android:layout_margin="8dp">

                <EditText
                     android:id="@+id/txtSearch"
                     android:layout_width="match_parent"
                     android:layout_height="44dp"
                     android:background="#FAFAFA"
                     android:gravity="center"
                     android:hint="@string/search_hint"
                     android:imeOptions="flagNoExtractUi|actionDone"
                     android:inputType="textNoSuggestions"
                     android:maxLines="1"
                     android:textSize="16sp"/>

                <ImageView
                     android:layout_width="24dp"
                     android:layout_height="24dp"
                     android:layout_gravity="start|center_vertical"
                     android:layout_marginLeft="15dp"
                     android:layout_marginStart="15dp"
                     android:alpha="0.2"
                     android:contentDescription="@string/magnifying_glass_icon"
                     android:src="@drawable/ic_search_black_24dp"/>

                <Button
                     android:id="@+id/btnClear"
                     android:layout_width="24dp"
                     android:layout_height="24dp"
                     android:layout_gravity="end|center_vertical"
                     android:layout_marginEnd="15dp"
                     android:layout_marginRight="15dp"
                     android:alpha="0.5"
                     android:background="@drawable/ic_clear_black_24dp"
                     android:visibility="gone"/>

            </FrameLayout>

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

        <FrameLayout
             android:id="@+id/fragHolder"
             android:layout_width="match_parent"
             android:layout_height="match_parent"/>

    </LinearLayout>

    <android.support.design.widget.NavigationView
         android:layout_width="wrap_content"
         android:layout_height="match_parent"
         android:layout_gravity="start"
         app:headerLayout="@layout/nav_header"
         app:menu="@menu/toolbar_menu"/>

</android.support.v4.widget.DrawerLayout>
</code>```

SettingsFragment:

```<code>public class SettingsFragment extends PreferenceFragment {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setHasOptionsMenu(true);
        addPreferencesFromResource(R.xml.preferences);
    }

    @Override
    public void onResume() {
        super.onResume();
        setToolbarTitle();
    }

    private void setToolbarTitle() {
        ActionBar actionBar = ((AppCompatActivity) getActivity()).getSupportActionBar();
        if (actionBar != null) {
            actionBar.setTitle(R.string.settings);
        }
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case android.R.id.home:
                getFragmentManager().popBackStack();
                return true;
            default:
                return super.onOptionsItemSelected(item);
        }
    }
}
</code>```

What I am looking for is the standard way to acheive this and not to start adding click/backstack listeners without understanding how its really meant to be done.

答:
In your activity write this function:

```<code>public static void setUpIndicator(){
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
            getSupportActionBar().setHomeAsUpIndicator(appCompatActivity.getResources().getDrawable(R.drawable.abc_ic_ab_back_mtrl_am_alpha, null));
        else
            getSupportActionBar().setHomeAsUpIndicator(appCompatActivity.getResources().getDrawable(R.drawable.abc_ic_ab_back_mtrl_am_alpha));
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
        getSupportActionBar().setDefaultDisplayHomeAsUpEnabled(true);
        toolbar.setNavigationOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                onBackPressed();
            }
        });
    }
</code>```

Call this function inside your fragment's onCreate.

Body:
How to move to a new fragment and automatically have the "hamburger" menu change to a <- button which brings the user back to the previous menu?

This seems to be an arcane art, no matter how many stackoverflow questions I read and things I try the "hamburger" menu always just opens the drawer. I am getting confused with certain posts using backstacklisteners to change icons, others using the onoptionselected and others directly attaching a click listener.

Activity

    public class MainActivity extends AppCompatActivity {

        private ActionBarDrawerToggle drawerToggle;
        private ActionBar actionBar;

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            setToolbar();
            // show first fragment here
        }

        private void setToolbar() {
            Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
            setSupportActionBar(toolbar);
            actionBar = getSupportActionBar();

            if (actionBar != null) {
                actionBar.setDisplayHomeAsUpEnabled(true);
                DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer);
                drawerToggle = new ActionBarDrawerToggle(this, drawer, toolbar, R.string.open, R.string.close);
                drawerToggle.setDrawerIndicatorEnabled(true);
                drawerToggle.syncState();
            }
        }

        @Override
        protected void onPostCreate(Bundle savedInstanceState) {
            super.onPostCreate(savedInstanceState);
            drawerToggle.syncState();
        }

        @Override
        public void onConfigurationChanged(Configuration newConfig) {
            super.onConfigurationChanged(newConfig);
            drawerToggle.onConfigurationChanged(newConfig);
        }

        @Override
        public boolean onCreateOptionsMenu(Menu menu) {

    getMenuInflater().inflate(R.menu.toolbar_menu, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case R.id.mnuSettings:
                showSettingsFragment();
                return true;
            default:
                return super.onOptionsItemSelected(item);
        }
    }

    private void showSettingsFragment() {
        getFragmentManager()
                .beginTransaction()
                .replace(R.id.fragHolder, new SettingsFragment())
                .addToBackStack(null)
                .commit();
    }
}

Activity Layout

<?xml version="1.0" encoding="utf-8"?>

<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
                                        xmlns:app="http://schemas.android.com/apk/res-auto"
                                        xmlns:tools="http://schemas.android.com/tools"
                                        android:id="@+id/drawer"
                                        android:layout_width="match_parent"
                                        android:layout_height="match_parent"
                                        android:fitsSystemWindows="true">

    <LinearLayout
         android:layout_width="match_parent"
         android:layout_height="match_parent"
         android:orientation="vertical">

        <android.support.design.widget.AppBarLayout
             android:layout_width="match_parent"
             android:layout_height="wrap_content">

            <android.support.v7.widget.Toolbar
                 android:id="@+id/toolbar"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
                 android:background="@color/primary"
                 android:minHeight="?attr/actionBarSize"
                 app:popupTheme="@style/Theme.AppCompat.Light"
                 app:theme="@style/Theme.AppCompat">

            </android.support.v7.widget.Toolbar>

            <FrameLayout
                 android:id="@+id/pnlSearch"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
                 android:layout_margin="8dp">

                <EditText
                     android:id="@+id/txtSearch"
                     android:layout_width="match_parent"
                     android:layout_height="44dp"
                     android:background="#FAFAFA"
                     android:gravity="center"
                     android:hint="@string/search_hint"
                     android:imeOptions="flagNoExtractUi|actionDone"
                     android:inputType="textNoSuggestions"
                     android:maxLines="1"
                     android:textSize="16sp"/>

                <ImageView
                     android:layout_width="24dp"
                     android:layout_height="24dp"
                     android:layout_gravity="start|center_vertical"
                     android:layout_marginLeft="15dp"
                     android:layout_marginStart="15dp"
                     android:alpha="0.2"
                     android:contentDescription="@string/magnifying_glass_icon"
                     android:src="@drawable/ic_search_black_24dp"/>

                <Button
                     android:id="@+id/btnClear"
                     android:layout_width="24dp"
                     android:layout_height="24dp"
                     android:layout_gravity="end|center_vertical"
                     android:layout_marginEnd="15dp"
                     android:layout_marginRight="15dp"
                     android:alpha="0.5"
                     android:background="@drawable/ic_clear_black_24dp"
                     android:visibility="gone"/>

            </FrameLayout>

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

        <FrameLayout
             android:id="@+id/fragHolder"
             android:layout_width="match_parent"
             android:layout_height="match_parent"/>

    </LinearLayout>

    <android.support.design.widget.NavigationView
         android:layout_width="wrap_content"
         android:layout_height="match_parent"
         android:layout_gravity="start"
         app:headerLayout="@layout/nav_header"
         app:menu="@menu/toolbar_menu"/>

</android.support.v4.widget.DrawerLayout>

SettingsFragment:

public class SettingsFragment extends PreferenceFragment {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setHasOptionsMenu(true);
        addPreferencesFromResource(R.xml.preferences);
    }

    @Override
    public void onResume() {
        super.onResume();
        setToolbarTitle();
    }

    private void setToolbarTitle() {
        ActionBar actionBar = ((AppCompatActivity) getActivity()).getSupportActionBar();
        if (actionBar != null) {
            actionBar.setTitle(R.string.settings);
        }
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case android.R.id.home:
                getFragmentManager().popBackStack();
                return true;
            default:
                return super.onOptionsItemSelected(item);
        }
    }
}

What I am looking for is the standard way to acheive this and not to start adding click/backstack listeners without understanding how its really meant to be done.

Body:
In your activity write this function:

public static void setUpIndicator(){
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
            getSupportActionBar().setHomeAsUpIndicator(appCompatActivity.getResources().getDrawable(R.drawable.abc_ic_ab_back_mtrl_am_alpha, null));
        else
            getSupportActionBar().setHomeAsUpIndicator(appCompatActivity.getResources().getDrawable(R.drawable.abc_ic_ab_back_mtrl_am_alpha));
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
        getSupportActionBar().setDefaultDisplayHomeAsUpEnabled(true);
        toolbar.setNavigationOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                onBackPressed();
            }
        });
    }

Call this function inside your fragment's onCreate.


问:
Firebase javascript background service worker notification icon not show
My firebase-messaging-sw.js working fine to show background notification as it should but it didn't show the icon while notification.title and notification.click_action worked correctly.

This is my service worker's messaging.setBackgroundMessageHandler

```<code>messaging.setBackgroundMessageHandler(function (payload) {
console.log('[firebase-messaging-sw.js] Received background message ', payload);
// Customize notification here
const notificationTitle = 'Background Message Title';
const notificationOptions = {
    body: 'Background Message body.',
    icon: '/image/logo.png'
};

return self.registration.showNotification(notificationTitle,
    notificationOptions);
</code>```

});

This is where I placed my icon

This is the result

Thanks for your time to help.

答:
Put your image in root directory and check. </p>

<p>Please refer to this URL- </p>

```<code>https://github.com/firebase/quickstart-js
</code>```

Body:
My firebase-messaging-sw.js working fine to show background notification as it should but it didn't show the icon while notification.title and notification.click_action worked correctly.

This is my service worker's messaging.setBackgroundMessageHandler

messaging.setBackgroundMessageHandler(function (payload) {
console.log('[firebase-messaging-sw.js] Received background message ', payload);
// Customize notification here
const notificationTitle = 'Background Message Title';
const notificationOptions = {
    body: 'Background Message body.',
    icon: '/image/logo.png'
};

return self.registration.showNotification(notificationTitle,
    notificationOptions);

});

This is where I placed my icon

This is the result

Thanks for your time to help.

Body:
Put your image in root directory and check.

Please refer to this URL-

https://github.com/firebase/quickstart-js


问:
How to play tick sound of UIPickerView on iOS 10?
The title has it... There is a new sound on iOS 10 that UIPickerView plays each time the selected item is changed. Is there a way to play that sound? Ideally with AudioServicesPlaySystemSound(_) if there is system sound for it or in any other way if there is not any.

答:
You can use system click sounds or save them and use from local resources</p>

```<code>//  NSURL *fileURL = [NSURL URLWithString:@"/System/Library/Audio/UISounds/wheels_of_time.caf"]; // Too loud
//  NSURL *fileURL = [NSURL URLWithString:@"/System/Library/Audio/UISounds/nano/TimerWheelHoursDetent_Haptic.caf"]; // Hours tick
SystemSoundID soundID;
NSURL *fileURL = [NSURL URLWithString:@"/System/Library/Audio/UISounds/nano/TimerWheelMinutesDetent_Haptic.caf"]; // Minutes tick
AudioServicesCreateSystemSoundID((__bridge_retained CFURLRef)fileURL, &soundID);
AudioServicesPlaySystemSound(soundID);
AudioServicesDisposeSystemSoundID(soundID);
</code>```

Body:
You can use system click sounds or save them and use from local resources

//  NSURL *fileURL = [NSURL URLWithString:@"/System/Library/Audio/UISounds/wheels_of_time.caf"]; // Too loud
//  NSURL *fileURL = [NSURL URLWithString:@"/System/Library/Audio/UISounds/nano/TimerWheelHoursDetent_Haptic.caf"]; // Hours tick
SystemSoundID soundID;
NSURL *fileURL = [NSURL URLWithString:@"/System/Library/Audio/UISounds/nano/TimerWheelMinutesDetent_Haptic.caf"]; // Minutes tick
AudioServicesCreateSystemSoundID((__bridge_retained CFURLRef)fileURL, &soundID);
AudioServicesPlaySystemSound(soundID);
AudioServicesDisposeSystemSoundID(soundID);


问:
Which format controller will take while parsing received JSON date?
I am posting JSON Data to my controller. One of the fields contains date. When i send date in MM/dd/yyyy format, the controller is taking dd/MM/yyyy format. Due to this my month is becoming day at server side. If i send 3/20/2017 then it is becoming 01/01/0001 at server side because 20 is not a valid month. How do i force controller to take 3/20/2017 in MM/dd/yyyy format. I initially though iis is referring my system time format. But it did not work even after i changed my system date format to MM/dd/yyyy.

Sample JSON which i am sending to server. Request type is POST. (Here i am posting only date field but in my actual request i have other fields too.)

```<code>{date:"3/20/2017"}
</code>```

Model:

```<code>Test{
public DateTime Date{get;set;}
}
</code>```

Action:

```<code>ActionResult Demo(Test test)
{
//some code
}
</code>```

答:
Suppose you have this AJAX call:

```<code>var date = "3/20/2017";
...
$.ajax({
        ...
        url: '/Controller/Demo',
        type: 'POST',
        data: { date: date },
        dataType: 'json',
        ...
       });
</code>```

In controller side, use DateTime.ParseExact to convert date into DateTime format:

```<code>[HttpPost]
public ActionResult Demo(String date)
{
    // other stuff
    ...
    var test = new Test();
    test.Date = DateTime.ParseExact(date, "M/d/yyyy", CultureInfo.InvariantCulture);
    ...
    // other stuff
}
</code>```

To prevent hassles with date formatting, conversion to UTC with toISOString() method is more recommended (see /a/23502790 for details):

View (JS)

```<code>var date = new Date("3/20/2017").toISOString();
</code>```

Controller

```<code>test.Date = DateTime.Parse(date);
</code>```

Body:
I am posting JSON Data to my controller. One of the fields contains date. When i send date in MM/dd/yyyy format, the controller is taking dd/MM/yyyy format. Due to this my month is becoming day at server side. If i send 3/20/2017 then it is becoming 01/01/0001 at server side because 20 is not a valid month. How do i force controller to take 3/20/2017 in MM/dd/yyyy format. I initially though iis is referring my system time format. But it did not work even after i changed my system date format to MM/dd/yyyy.

Sample JSON which i am sending to server. Request type is POST. (Here i am posting only date field but in my actual request i have other fields too.)

{date:"3/20/2017"}

Model:

Test{
public DateTime Date{get;set;}
}

Action:

ActionResult Demo(Test test)
{
//some code
}

Body:
Suppose you have this AJAX call:

var date = "3/20/2017";
...
$.ajax({
        ...
        url: '/Controller/Demo',
        type: 'POST',
        data: { date: date },
        dataType: 'json',
        ...
       });

In controller side, use DateTime.ParseExact to convert date into DateTime format:

[HttpPost]
public ActionResult Demo(String date)
{
    // other stuff
    ...
    var test = new Test();
    test.Date = DateTime.ParseExact(date, "M/d/yyyy", CultureInfo.InvariantCulture);
    ...
    // other stuff
}

To prevent hassles with date formatting, conversion to UTC with toISOString() method is more recommended (see /a/23502790 for details):

View (JS)

var date = new Date("3/20/2017").toISOString();

Controller

test.Date = DateTime.Parse(date);


问:
Is it ok to still use tables?

Possible Duplicate:

  Why not use tables for layout in HTML?

Just wondering, I thought I have read before that it is bad to use tables, so my question is, is it still acceptable to use tables in development?

答:
Tables work best for tabular data - if you are showing results of some query, like a list of customers or transactions or currency values, go ahead, you should be using tables.

What is bad is using tables for layout where the logical orger is not left-to-right i.e. if you have a navigation pane on the left, do you want to read the navigation before the content? probably not...

However if you have a form with labels and input fields do you want to read the label before the input control, yes, you probably do.

The reason for this is that screen readers and similar assistive technologies force this order on their users. also it is usually much harder to read the resultant HTML when you use tables for layout

Title: Is it ok to still use tables?


问:
Hibernate mapping for complex joins
I have legacy code that I am trying to map to the new code.

```<code>OLD_PERSON
pid
sid
name
age

NEW_PERSON
pid
sid
fid
age

RESOLVE_PERSON
pid
fid
status
</code>```

Java class

```<code>domain.Person {
 ID _id;
 String _name;
 Integer _age;
}
</code>```

In the legacy world, there was just one table: OLD_TABLE. The hibernate mapping was simple, just one class and its columns. In the new world, I have to use the above 3 tables and produce one Entity where the name comes from OLD_PERSON and age from NEW_PERSON. So basically a SQL query is:

```<code>select op.name as name, np.age as age
from OLD_PERSON op
INNER JOIN RESOLVE_PERSON rp
on rp.pid = op.pid
INNER JOIN NEW_PERSON np
on np.pid = rp.pid and np.fid = rp.fid and np.sid = op.sid
where rp.status = 'CURRENT'
</code>```

Upon research/googling I found that I can use "Secondary tables" which are equivalent of "JOIN table" in hibernate xml. Note: I cannot use annotation as this code is old and I am still on hibernate3.5.6.

So I added a join table inside my mapping file:

```<code><class name="domain.Person" table="OLD_PERSON">
        <composite-id name="_id" class="Id">
            <key-property access="property" name="key1" type="long" column="pid" />
            <key-property access="property" name="key2" type="int" column="sid" />

            <generator class="assigned" />
        </composite-id>

        <property name="_Name" type="String" column="name" />

        <join table="NEW_PERSON" fetch="join" inverse="false">
          <key>
            <column name="pid" />
            <column name="sid" />
          </key>
            <property name="_age" column="age" not-null="true" />
        </join>
</class>
</code>```

But the join to NEW_PERSON table requires an inner join with RESOLVE_PERSON table. I tried using subselect but its not the correct thing to use. I am unable to plug in formula anywhere here.

Any pointers on how this can be achieved? What I am essentially asking for is how to apply a criteria/constraint check on the JOIN.

答:
I had a similar situation as your problem. I have mapped the third table to an entity and use the DAO for this entity for getting something by its property.

Here is the code (since I have used annotation, so this is not something you can use directly, but hopefully it will give you some inspiration),

```<code>@Entity
@Table(name = "resolve_person")
public class ResolvePerson implements java.io.Serializable {
    private OldPerson old;
    private NewPerson new;

    ...

    @ManyToOne // you may change it to other relationships
    @JoinColumn(name = "pid", nullable = false)
    public OldPerson getOldPerson () {
        return this.old;
    }

    public void setOldPerson (OldPerson old) {
        this.old = old;
    }

    @Id
    @GeneratedValue(generator = "idGenerator")
    @GenericGenerator(name = "idGenerator", strategy = "foreign",
            parameters = { @org.hibernate.annotations.Parameter(name = "property", value = "fid") })
    @Column(name = "fid", nullable = false, unique = true)
    public NewPerson getNewPerson () {
        return this.New;
    }

    public void setNewPerson (NewPerson new) {
        this.new = new;
    }
}
</code>```

The DAO is quite normal,

```<code>public List findByProperty(String propertyName, Object value) {
        log.debug("finding ResolvePerson instance with property: "
                + propertyName + ", value: " + value);
        try {
            String queryString = "from ResolvePerson as model where model."
                    + propertyName + "= ?";
            Query queryObject = getSession().createQuery(queryString);
            queryObject.setParameter(0, value);
            return queryObject.list();
        } catch (RuntimeException re) {
            log.error("find by property name failed", re);
            throw re;
        }
    }
</code>```

Now you can query with the property "status" set to "current".

Title: Hibernate mapping for complex joins

Body:
I have legacy code that I am trying to map to the new code.

OLD_PERSON
pid
sid
name
age

NEW_PERSON
pid
sid
fid
age

RESOLVE_PERSON
pid
fid
status

Java class

domain.Person {
 ID _id;
 String _name;
 Integer _age;
}

In the legacy world, there was just one table: OLD_TABLE. The hibernate mapping was simple, just one class and its columns. In the new world, I have to use the above 3 tables and produce one Entity where the name comes from OLD_PERSON and age from NEW_PERSON. So basically a SQL query is:

select op.name as name, np.age as age
from OLD_PERSON op
INNER JOIN RESOLVE_PERSON rp
on rp.pid = op.pid
INNER JOIN NEW_PERSON np
on np.pid = rp.pid and np.fid = rp.fid and np.sid = op.sid
where rp.status = 'CURRENT'

Upon research/googling I found that I can use "Secondary tables" which are equivalent of "JOIN table" in hibernate xml. Note: I cannot use annotation as this code is old and I am still on hibernate3.5.6.

So I added a join table inside my mapping file:

<class name="domain.Person" table="OLD_PERSON">
        <composite-id name="_id" class="Id">
            <key-property access="property" name="key1" type="long" column="pid" />
            <key-property access="property" name="key2" type="int" column="sid" />

            <generator class="assigned" />
        </composite-id>

        <property name="_Name" type="String" column="name" />

        <join table="NEW_PERSON" fetch="join" inverse="false">
          <key>
            <column name="pid" />
            <column name="sid" />
          </key>
            <property name="_age" column="age" not-null="true" />
        </join>
</class>

But the join to NEW_PERSON table requires an inner join with RESOLVE_PERSON table. I tried using subselect but its not the correct thing to use. I am unable to plug in formula anywhere here.

Any pointers on how this can be achieved? What I am essentially asking for is how to apply a criteria/constraint check on the JOIN.

Body:
I had a similar situation as your problem. I have mapped the third table to an entity and use the DAO for this entity for getting something by its property.

Here is the code (since I have used annotation, so this is not something you can use directly, but hopefully it will give you some inspiration),

@Entity
@Table(name = "resolve_person")
public class ResolvePerson implements java.io.Serializable {
    private OldPerson old;
    private NewPerson new;

    ...

    @ManyToOne // you may change it to other relationships
    @JoinColumn(name = "pid", nullable = false)
    public OldPerson getOldPerson () {
        return this.old;
    }

    public void setOldPerson (OldPerson old) {
        this.old = old;
    }

    @Id
    @GeneratedValue(generator = "idGenerator")
    @GenericGenerator(name = "idGenerator", strategy = "foreign",
            parameters = { @org.hibernate.annotations.Parameter(name = "property", value = "fid") })
    @Column(name = "fid", nullable = false, unique = true)
    public NewPerson getNewPerson () {
        return this.New;
    }

    public void setNewPerson (NewPerson new) {
        this.new = new;
    }
}

The DAO is quite normal,

public List findByProperty(String propertyName, Object value) {
        log.debug("finding ResolvePerson instance with property: "
                + propertyName + ", value: " + value);
        try {
            String queryString = "from ResolvePerson as model where model."
                    + propertyName + "= ?";
            Query queryObject = getSession().createQuery(queryString);
            queryObject.setParameter(0, value);
            return queryObject.list();
        } catch (RuntimeException re) {
            log.error("find by property name failed", re);
            throw re;
        }
    }

Now you can query with the property "status" set to "current".


问:
WARNING (theano.sandbox.cuda): CUDA is installed, but device gpu is not available (error: cuda unavailable)
in Ubuntu MATE 16.04 I'm trying to run the deep-learning python examples here using the GPU:

testing Theano with GPU

I did run the example code,

```<code>THEANO_FLAGS=mode=FAST_RUN,device=gpu,floatX=float32 python check1.py
</code>```

but it seems that it is used the CPU and not the GPU. Here is the last part of terminal output:

```<code>WARNING (theano.sandbox.cuda): CUDA is installed, but device gpu0 is not  available  (error: cuda unavailable)
...
Used the cpu
</code>```

I tried to run this code too:

```<code>THEANO_FLAGS=device=cuda0 python check1.py
</code>```

but the output is:

```<code>ERROR (theano.sandbox.gpuarray): pygpu was configured but could not be imported
Traceback (most recent call last):
  File "/usr/local/lib/python2.7/dist-packages/theano/sandbox/gpuarray/__init__.py", line 20, in <module>
    import pygpu
ImportError: No module named pygpu
...
used cpu
</code>```

I installed the cuda toolkit from apt.
Here there are (hopefully) useful data:

```<code>python --version
Python 2.7.12

g++ -v
gcc version 5.4.0

nvcc --version
Cuda compilation tools, release 7.5, V7.5.17

lspci
NVIDIA Corporation GM107 [GeForce GTX 750 Ti] (rev a2)

nvidia-smi

+------------------------------------------------------+
| NVIDIA-SMI 361.42     Driver Version: 361.42         |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|===============================+======================+======================|
|   0  GeForce GTX 750 Ti  Off  | 0000:01:00.0      On |                  N/A |
| 29%   35C    P8     1W /  38W |    100MiB /  2044MiB |      0%      Default |
+-------------------------------+----------------------+----------------------+

+-----------------------------------------------------------------------------+
| Processes:                                                       GPU Memory |
|  GPU       PID  Type  Process name                               Usage      |
|=============================================================================|
|    0      2861    G   /usr/lib/xorg/Xorg                              90MiB |
+-----------------------------------------------------------------------------+
</code>```

答: In my system, this issue got resolved just by rebooting the system. Maybe you can give it a try.  </p>

Body:
in Ubuntu MATE 16.04 I'm trying to run the deep-learning python examples here using the GPU:

testing Theano with GPU

I did run the example code,

THEANO_FLAGS=mode=FAST_RUN,device=gpu,floatX=float32 python check1.py

but it seems that it is used the CPU and not the GPU. Here is the last part of terminal output:

WARNING (theano.sandbox.cuda): CUDA is installed, but device gpu0 is not  available  (error: cuda unavailable)
...
Used the cpu

I tried to run this code too:

THEANO_FLAGS=device=cuda0 python check1.py

but the output is:

ERROR (theano.sandbox.gpuarray): pygpu was configured but could not be imported
Traceback (most recent call last):
  File "/usr/local/lib/python2.7/dist-packages/theano/sandbox/gpuarray/__init__.py", line 20, in <module>
    import pygpu
ImportError: No module named pygpu
...
used cpu

I installed the cuda toolkit from apt.
Here there are (hopefully) useful data:

python --version
Python 2.7.12

g++ -v
gcc version 5.4.0

nvcc --version
Cuda compilation tools, release 7.5, V7.5.17

lspci
NVIDIA Corporation GM107 [GeForce GTX 750 Ti] (rev a2)

nvidia-smi

+------------------------------------------------------+
| NVIDIA-SMI 361.42     Driver Version: 361.42         |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|===============================+======================+======================|
|   0  GeForce GTX 750 Ti  Off  | 0000:01:00.0      On |                  N/A |
| 29%   35C    P8     1W /  38W |    100MiB /  2044MiB |      0%      Default |
+-------------------------------+----------------------+----------------------+

+-----------------------------------------------------------------------------+
| Processes:                                                       GPU Memory |
|  GPU       PID  Type  Process name                               Usage      |
|=============================================================================|
|    0      2861    G   /usr/lib/xorg/Xorg                              90MiB |
+-----------------------------------------------------------------------------+


问:
Getting real world coordinates from Forge model
Is it possible to get the real world coordinates form the original model in the Forge viewer? It looks like when a model is loaded into the Viewer it is placed with the center of the model in the origin of the Viewer. </p>

答: Afaik, the Forge viewer centres the model. In other words, the origin of the viewer coordinate system is the centroid of the model. The scale of the model remains unchanged. As a result, you can transform the original model coordinates to Forge viewer and vice versa simply by adding or subtracting the model centroid.</p>


问:
Using HTTP PATCH - real example
I am trying to figure out how can I implement a HTTP patch in my application. I have never used it before. I use Express.js and sequelize (MySQL).

I looked on SO and on internet for real life example, but could not find anything of real value. Those links gave me better understanding what is PATCH, but I still fail to see its benefit in my case. It must be something I am missing.

This is my simplified setup:

```<code>router:
basePath:
    controller: PutUser
    method: PUT
    path: /user/:userId/

Payload:
{email: 'newemail@hello.com'}

Controller:
Then here I find the user by its id and give the payload. User gets updated
</code>```

What is confusing me, is if I were to implement a PATCH, the only things that changes is in router, I use PATCH instead. I also use userId to find the user and change its email. What am I missing? Is this how it is supposed to be?

答:
You are not missing anything. The difference between PUT and PATCH is more semantically. The method itself does not deliver much additional information/requirement in HTTP level. According to RFC5789, using PUT or PATCH depends on your server-side logic:

The difference between the PUT and PATCH requests is reflected in the
way the server processes the enclosed entity to modify the resource
identified by the Request-URI.

Thus, if your user resource has many fields, such as email, name, address, age etc, then PATCH is the better choice if you only want to change email. If your user resource only have email field, or if you want to reset all fields information, then PUT is the better choice.

I guess you are confused because this "update email" operation is an "override" operation, which makes it very similar to PUT or POST. There is a more appropriate example though (pseudocode):

```<code>PATCH /user/<userId>
Payload:
{
    patchField: 'age',
    patchOperation: 'X+1'
}
</code>```

Title: Using HTTP PATCH - real example

Body:
I am trying to figure out how can I implement a HTTP patch in my application. I have never used it before. I use Express.js and sequelize (MySQL).

I looked on SO and on internet for real life example, but could not find anything of real value. Those links gave me better understanding what is PATCH, but I still fail to see its benefit in my case. It must be something I am missing.

This is my simplified setup:

router:
basePath:
    controller: PutUser
    method: PUT
    path: /user/:userId/

Payload:
{email: 'newemail@hello.com'}

Controller:
Then here I find the user by its id and give the payload. User gets updated

What is confusing me, is if I were to implement a PATCH, the only things that changes is in router, I use PATCH instead. I also use userId to find the user and change its email. What am I missing? Is this how it is supposed to be?

Body:
You are not missing anything. The difference between PUT and PATCH is more semantically. The method itself does not deliver much additional information/requirement in HTTP level. According to RFC5789, using PUT or PATCH depends on your server-side logic:

The difference between the PUT and PATCH requests is reflected in the
way the server processes the enclosed entity to modify the resource
identified by the Request-URI.

Thus, if your user resource has many fields, such as email, name, address, age etc, then PATCH is the better choice if you only want to change email. If your user resource only have email field, or if you want to reset all fields information, then PUT is the better choice.

I guess you are confused because this "update email" operation is an "override" operation, which makes it very similar to PUT or POST. There is a more appropriate example though (pseudocode):

PATCH /user/<userId>
Payload:
{
    patchField: 'age',
    patchOperation: 'X+1'
}


问:
How to find the average colour of an image in Python with OpenCV?
I tried this code:

```<code>import cv2
image = cv2.imread("sample.jpg")
pixel = image[200, 550]
print pixel
</code>```

But I am getting error as:

'Nonetype' no attributes error getitem

This error is getting displayed after executing the third line of code.

答:
How to fix the error

There are two potential causes for this error to happen:

The file name is misspelled.

The image file is not in the current working directory.

To fix this issue you should make sure the filename is correctly spelled (do case sensitive check just in case) and the image file is in the current working directory (there are two options here: you could either change the current working directory in your IDE or specify the full path of the file).

Average colour vs. dominant colour

Then to calculate the "average colour" you have to decide what you mean by that. In a grayscale image it is simply the mean of gray levels across the image. Colours are usually represented through 3-dimensional vectors whilst gray levels are scalars.

The average colour is the sum of all pixels divided by the number of pixels. However, this approach may yield a colour different to the most prominent visual color. What you might really want is dominant color rather than average colour.

Implementation

Let's go through the code slowly. We start by importing the necessary modules and reading the image:

```<code>import cv2
import numpy as np
from skimage import io

img = io.imread('https://i.stack.imgur.com/DNM65.png')[:, :, :-1]
</code>```

Then we can calculate the mean of each chromatic channel following a method analog to the one proposed by @Ruan B.:

```<code>average = img.mean(axis=0).mean(axis=0)
</code>```

Next we apply k-means clustering to create a palette with the most representative colours of the image (in this toy example n_colors was set to 5).

```<code>pixels = np.float32(img.reshape(-1, 3))

n_colors = 5
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 200, .1)
flags = cv2.KMEANS_RANDOM_CENTERS

_, labels, palette = cv2.kmeans(pixels, n_colors, None, criteria, 10, flags)
_, counts = np.unique(labels, return_counts=True)
</code>```

And finally the dominant colour is the palette colour which occurs most frequently on the quantized image:

```<code>dominant = palette[np.argmax(counts)]
</code>```

Comparison of results

To illustrate the differences between both approaches I've used the following sample image:

The obtained values for the average colour, i.e. a colour whose components are the means of the three chromatic channels, and the dominant colour calculated throug k-means clustering are rather different:

```<code>In [30]: average
Out[30]: array([91.63179156, 69.30190754, 58.11971896])

In [31]: dominant
Out[31]: array([179.3999  ,  27.341282,   2.294441], dtype=float32)
</code>```

Let's see how those colours look to better understand the differences between both approaches. On the left part of the figure below it is displayed the average colour. It clearly emerges that the calculated average colour does not properly describe the colour content of the original image. In fact, there's no a single pixel with that colour in the original image. The right part of the figure shows the five most representative colours sorted from top to bottom in descending order of importance (occurrence frequency). This palette makes it evident that the dominant color is the red, which is consistent with the fact that the largest region of uniform colour in the original image corresponds to the red Lego piece.

This is the code used to generate the figure above:

```<code>import matplotlib.pyplot as plt

avg_patch = np.ones(shape=img.shape, dtype=np.uint8)*np.uint8(average)

indices = np.argsort(counts)[::-1]
freqs = np.cumsum(np.hstack([[0], counts[indices]/float(counts.sum())]))
rows = np.int_(img.shape[0]*freqs)

dom_patch = np.zeros(shape=img.shape, dtype=np.uint8)
for i in range(len(rows) - 1):
    dom_patch[rows[i]:rows[i + 1], :, :] += np.uint8(palette[indices[i]])

fig, (ax0, ax1) = plt.subplots(1, 2, figsize=(12,6))
ax0.imshow(avg_patch)
ax0.set_title('Average color')
ax0.axis('off')
ax1.imshow(dom_patch)
ax1.set_title('Dominant colors')
ax1.axis('off')
plt.show(fig)
</code>```

TL;DR answer

In summary, despite the calculation of the average colour - as proposed in @Ruan B.'s answer - is correct, the yielded result may not adequately represent the colour content of the image. A more sensible approach is that of determining the dominant colour through vector quantization (clustering).

Body:
I tried this code:

import cv2
image = cv2.imread("sample.jpg")
pixel = image[200, 550]
print pixel

But I am getting error as:

'Nonetype' no attributes error getitem

This error is getting displayed after executing the third line of code.

Body:
How to fix the error

There are two potential causes for this error to happen:

The file name is misspelled.

The image file is not in the current working directory.

To fix this issue you should make sure the filename is correctly spelled (do case sensitive check just in case) and the image file is in the current working directory (there are two options here: you could either change the current working directory in your IDE or specify the full path of the file).

Average colour vs. dominant colour

Then to calculate the "average colour" you have to decide what you mean by that. In a grayscale image it is simply the mean of gray levels across the image. Colours are usually represented through 3-dimensional vectors whilst gray levels are scalars.

The average colour is the sum of all pixels divided by the number of pixels. However, this approach may yield a colour different to the most prominent visual color. What you might really want is dominant color rather than average colour.

Implementation

Let's go through the code slowly. We start by importing the necessary modules and reading the image:

import cv2
import numpy as np
from skimage import io

img = io.imread('https://i.stack.imgur.com/DNM65.png')[:, :, :-1]

Then we can calculate the mean of each chromatic channel following a method analog to the one proposed by @Ruan B.:

average = img.mean(axis=0).mean(axis=0)

Next we apply k-means clustering to create a palette with the most representative colours of the image (in this toy example n_colors was set to 5).

pixels = np.float32(img.reshape(-1, 3))

n_colors = 5
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 200, .1)
flags = cv2.KMEANS_RANDOM_CENTERS

_, labels, palette = cv2.kmeans(pixels, n_colors, None, criteria, 10, flags)
_, counts = np.unique(labels, return_counts=True)

And finally the dominant colour is the palette colour which occurs most frequently on the quantized image:

dominant = palette[np.argmax(counts)]

Comparison of results

To illustrate the differences between both approaches I've used the following sample image:

The obtained values for the average colour, i.e. a colour whose components are the means of the three chromatic channels, and the dominant colour calculated throug k-means clustering are rather different:

In [30]: average
Out[30]: array([91.63179156, 69.30190754, 58.11971896])

In [31]: dominant
Out[31]: array([179.3999  ,  27.341282,   2.294441], dtype=float32)

Let's see how those colours look to better understand the differences between both approaches. On the left part of the figure below it is displayed the average colour. It clearly emerges that the calculated average colour does not properly describe the colour content of the original image. In fact, there's no a single pixel with that colour in the original image. The right part of the figure shows the five most representative colours sorted from top to bottom in descending order of importance (occurrence frequency). This palette makes it evident that the dominant color is the red, which is consistent with the fact that the largest region of uniform colour in the original image corresponds to the red Lego piece.

This is the code used to generate the figure above:

import matplotlib.pyplot as plt

avg_patch = np.ones(shape=img.shape, dtype=np.uint8)*np.uint8(average)

indices = np.argsort(counts)[::-1]
freqs = np.cumsum(np.hstack([[0], counts[indices]/float(counts.sum())]))
rows = np.int_(img.shape[0]*freqs)

dom_patch = np.zeros(shape=img.shape, dtype=np.uint8)
for i in range(len(rows) - 1):
    dom_patch[rows[i]:rows[i + 1], :, :] += np.uint8(palette[indices[i]])

fig, (ax0, ax1) = plt.subplots(1, 2, figsize=(12,6))
ax0.imshow(avg_patch)
ax0.set_title('Average color')
ax0.axis('off')
ax1.imshow(dom_patch)
ax1.set_title('Dominant colors')
ax1.axis('off')
plt.show(fig)

TL;DR answer

In summary, despite the calculation of the average colour - as proposed in @Ruan B.'s answer - is correct, the yielded result may not adequately represent the colour content of the image. A more sensible approach is that of determining the dominant colour through vector quantization (clustering).

ContentLicense: CC BY-SA 4.0


问:
Vertically connected images with line - CSS HTML
can anyone please suggest a method for creating a div portion like in the image. The height should depend on the outer div. I need to use this as a separator between two divs with text on its left and right. Each circled image should come next to the related heading

答:
Vertical time line by Codyhouse! first you have to need call reset css, style css and jQuery I used png image but SVG would be better!

jQuery(document).ready(function($) {
  var timelineBlocks = $('.cd-timeline-block'),
    offset = 0.8;

  //hide timeline blocks which are outside the viewport
  hideBlocks(timelineBlocks, offset);

  //on scolling, show/animate timeline blocks when enter the viewport
  $(window).on('scroll', function() {
    (!window.requestAnimationFrame) ?
    setTimeout(function() {
      showBlocks(timelineBlocks, offset);
    }, 100): window.requestAnimationFrame(function() {
      showBlocks(timelineBlocks, offset);
    });
  });

  function hideBlocks(blocks, offset) {
    blocks.each(function() {
      ($(this).offset().top > $(window).scrollTop() + $(window).height() * offset) && $(this).find('.cd-timeline-img, .cd-timeline-content').addClass('is-hidden');
    });
  }

  function showBlocks(blocks, offset) {
    blocks.each(function() {
      ($(this).offset().top <= $(window).scrollTop() + $(window).height() * offset && $(this).find('.cd-timeline-img').hasClass('is-hidden')) && $(this).find('.cd-timeline-img, .cd-timeline-content').removeClass('is-hidden').addClass('bounce-in');
    });
  }
});```
<pre class="snippet-code-css lang-css prettyprint-override"><code>/* http://meyerweb.com/eric/tools/css/reset/
   v2.0 | 20110126
   License: none (public domain)
*/

html,
body,
div,
span,
applet,
object,
iframe,
h1,
h2,
h3,
h4,
h5,
h6,
p,
blockquote,
pre,
a,
abbr,
acronym,
address,
big,
cite,
code,
del,
dfn,
em,
img,
ins,
kbd,
q,
s,
samp,
small,
strike,
strong,
sub,
sup,
tt,
var,
b,
u,
i,
center,
dl,
dt,
dd,
ol,
ul,
li,
fieldset,
form,
label,
legend,
table,
caption,
tbody,
tfoot,
thead,
tr,
th,
td,
article,
aside,
canvas,
details,
embed,
figure,
figcaption,
footer,
header,
hgroup,
menu,
nav,
output,
ruby,
section,
summary,
time,
mark,
audio,
video {
  margin: 0;
  padding: 0;
  border: 0;
  font-size: 100%;
  font: inherit;
  vertical-align: baseline;
}

/* HTML5 display-role reset for older browsers */

article,
aside,
details,
figcaption,
figure,
footer,
header,
hgroup,
menu,
nav,
section,
main {
  display: block;
}

body {
  line-height: 1;
}

ol,
ul {
  list-style: none;
}

blockquote,
q {
  quotes: none;
}

blockquote:before,
blockquote:after,
q:before,
q:after {
  content: '';
  content: none;
}

table {
  border-collapse: collapse;
  border-spacing: 0;
}

/* --------------------------------

Primary style

-------------------------------- */

html * {
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

*,
*:after,
*:before {
  -webkit-box-sizing: border-box;
  -moz-box-sizing: border-box;
  box-sizing: border-box;
}

body {
  font-size: 100%;
  font-family: "Droid Serif", serif;
  color: #7f8c97;
  background-color: #e9f0f5;
}

a {
  color: #acb7c0;
  text-decoration: none;
  font-family: "Open Sans", sans-serif;
}

img {
  max-width: 100%;
}

h1,
h2 {
  font-family: "Open Sans", sans-serif;
  font-weight: bold;
}

/* --------------------------------

Modules - reusable parts of our design

-------------------------------- */

.cd-container {
  /* this class is used to give a max-width to the element it is applied to, and center it horizontally when it reaches that max-width */
  width: 90%;
  max-width: 1170px;
  margin: 0 auto;
}

.cd-container::after {
  /* clearfix */
  content: '';
  display: table;
  clear: both;
}

/* --------------------------------

Main components

-------------------------------- */

header {
  height: 200px;
  line-height: 200px;
  text-align: center;
  background: #303e49;
}

header h1 {
  color: white;
  font-size: 18px;
  font-size: 1.125rem;
}

@media only screen and (min-width: 1170px) {
  header {
    height: 300px;
    line-height: 300px;
  }
  header h1 {
    font-size: 24px;
    font-size: 1.5rem;
  }
}

#cd-timeline {
  position: relative;
  padding: 2em 0;
  margin-top: 2em;
  margin-bottom: 2em;
}

#cd-timeline::before {
  /* this is the vertical line */
  content: '';
  position: absolute;
  top: 0;
  left: 18px;
  height: 100%;
  width: 4px;
  background: #d7e4ed;
}

@media only screen and (min-width: 1170px) {
  #cd-timeline {
    margin-top: 3em;
    margin-bottom: 3em;
  }
  #cd-timeline::before {
    left: 50%;
    margin-left: -2px;
  }
}

.cd-timeline-block {
  position: relative;
  margin: 2em 0;
}

.cd-timeline-block:after {
  content: "";
  display: table;
  clear: both;
}

.cd-timeline-block:first-child {
  margin-top: 0;
}

.cd-timeline-block:last-child {
  margin-bottom: 0;
}

@media only screen and (min-width: 1170px) {
  .cd-timeline-block {
    margin: 4em 0;
  }
  .cd-timeline-block:first-child {
    margin-top: 0;
  }
  .cd-timeline-block:last-child {
    margin-bottom: 0;
  }
}

.cd-timeline-img {
  position: absolute;
  top: 0;
  left: 0;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  box-shadow: 0 0 0 4px white, inset 0 2px 0 rgba(0, 0, 0, 0.08), 0 3px 0 4px rgba(0, 0, 0, 0.05);
}

.cd-timeline-img img {
  display: block;
  width: 24px;
  height: 24px;
  position: relative;
  left: 50%;
  top: 50%;
  margin-left: -12px;
  margin-top: -12px;
}

.cd-timeline-img.cd-picture {
  background: #75ce66;
}

.cd-timeline-img.cd-movie {
  background: #c03b44;
}

.cd-timeline-img.cd-location {
  background: #f0ca45;
}

@media only screen and (min-width: 1170px) {
  .cd-timeline-img {
    width: 60px;
    height: 60px;
    left: 50%;
    margin-left: -30px;
    /* Force Hardware Acceleration in WebKit */
    -webkit-transform: translateZ(0);
    -webkit-backface-visibility: hidden;
  }
  .cssanimations .cd-timeline-img.is-hidden {
    visibility: hidden;
  }
  .cssanimations .cd-timeline-img.bounce-in {
    visibility: visible;
    -webkit-animation: cd-bounce-1 0.6s;
    -moz-animation: cd-bounce-1 0.6s;
    animation: cd-bounce-1 0.6s;
  }
}

@-webkit-keyframes cd-bounce-1 {
  0% {
    opacity: 0;
    -webkit-transform: scale(0.5);
  }
  60% {
    opacity: 1;
    -webkit-transform: scale(1.2);
  }
  100% {
    -webkit-transform: scale(1);
  }
}

@-moz-keyframes cd-bounce-1 {
  0% {
    opacity: 0;
    -moz-transform: scale(0.5);
  }
  60% {
    opacity: 1;
    -moz-transform: scale(1.2);
  }
  100% {
    -moz-transform: scale(1);
  }
}

@keyframes cd-bounce-1 {
  0% {
    opacity: 0;
    -webkit-transform: scale(0.5);
    -moz-transform: scale(0.5);
    -ms-transform: scale(0.5);
    -o-transform: scale(0.5);
    transform: scale(0.5);
  }
  60% {
    opacity: 1;
    -webkit-transform: scale(1.2);
    -moz-transform: scale(1.2);
    -ms-transform: scale(1.2);
    -o-transform: scale(1.2);
    transform: scale(1.2);
  }
  100% {
    -webkit-transform: scale(1);
    -moz-transform: scale(1);
    -ms-transform: scale(1);
    -o-transform: scale(1);
    transform: scale(1);
  }
}

.cd-timeline-content {
  position: relative;
  margin-left: 60px;
  background: white;
  border-radius: 0.25em;
  padding: 1em;
  box-shadow: 0 3px 0 #d7e4ed;
}

.cd-timeline-content:after {
  content: "";
  display: table;
  clear: both;
}

.cd-timeline-content h2 {
  color: #303e49;
}

.cd-timeline-content p,
.cd-timeline-content .cd-read-more,
.cd-timeline-content .cd-date {
  font-size: 13px;
  font-size: 0.8125rem;
}

.cd-timeline-content .cd-read-more,
.cd-timeline-content .cd-date {
  display: inline-block;
}

.cd-timeline-content p {
  margin: 1em 0;
  line-height: 1.6;
}

.cd-timeline-content .cd-read-more {
  float: right;
  padding: .8em 1em;
  background: #acb7c0;
  color: white;
  border-radius: 0.25em;
}

.no-touch .cd-timeline-content .cd-read-more:hover {
  background-color: #bac4cb;
}

.cd-timeline-content .cd-date {
  float: left;
  padding: .8em 0;
  opacity: .7;
}

.cd-timeline-content::before {
  content: '';
  position: absolute;
  top: 16px;
  right: 100%;
  height: 0;
  width: 0;
  border: 7px solid transparent;
  border-right: 7px solid white;
}

@media only screen and (min-width: 768px) {
  .cd-timeline-content h2 {
    font-size: 20px;
    font-size: 1.25rem;
  }
  .cd-timeline-content p {
    font-size: 16px;
    font-size: 1rem;
  }
  .cd-timeline-content .cd-read-more,
  .cd-timeline-content .cd-date {
    font-size: 14px;
    font-size: 0.875rem;
  }
}

@media only screen and (min-width: 1170px) {
  .cd-timeline-content {
    margin-left: 0;
    padding: 1.6em;
    width: 45%;
  }
  .cd-timeline-content::before {
    top: 24px;
    left: 100%;
    border-color: transparent;
    border-left-color: white;
  }
  .cd-timeline-content .cd-read-more {
    float: left;
  }
  .cd-timeline-content .cd-date {
    position: absolute;
    width: 100%;
    left: 122%;
    top: 6px;
    font-size: 16px;
    font-size: 1rem;
  }
  .cd-timeline-block:nth-child(even) .cd-timeline-content {
    float: right;
  }
  .cd-timeline-block:nth-child(even) .cd-timeline-content::before {
    top: 24px;
    left: auto;
    right: 100%;
    border-color: transparent;
    border-right-color: white;
  }
  .cd-timeline-block:nth-child(even) .cd-timeline-content .cd-read-more {
    float: right;
  }
  .cd-timeline-block:nth-child(even) .cd-timeline-content .cd-date {
    left: auto;
    right: 122%;
    text-align: right;
  }
  .cssanimations .cd-timeline-content.is-hidden {
    visibility: hidden;
  }
  .cssanimations .cd-timeline-content.bounce-in {
    visibility: visible;
    -webkit-animation: cd-bounce-2 0.6s;
    -moz-animation: cd-bounce-2 0.6s;
    animation: cd-bounce-2 0.6s;
  }
}

@media only screen and (min-width: 1170px) {
  /* inverse bounce effect on even content blocks */
  .cssanimations .cd-timeline-block:nth-child(even) .cd-timeline-content.bounce-in {
    -webkit-animation: cd-bounce-2-inverse 0.6s;
    -moz-animation: cd-bounce-2-inverse 0.6s;
    animation: cd-bounce-2-inverse 0.6s;
  }
}

@-webkit-keyframes cd-bounce-2 {
  0% {
    opacity: 0;
    -webkit-transform: translateX(-100px);
  }
  60% {
    opacity: 1;
    -webkit-transform: translateX(20px);
  }
  100% {
    -webkit-transform: translateX(0);
  }
}

@-moz-keyframes cd-bounce-2 {
  0% {
    opacity: 0;
    -moz-transform: translateX(-100px);
  }
  60% {
    opacity: 1;
    -moz-transform: translateX(20px);
  }
  100% {
    -moz-transform: translateX(0);
  }
}

@keyframes cd-bounce-2 {
  0% {
    opacity: 0;
    -webkit-transform: translateX(-100px);
    -moz-transform: translateX(-100px);
    -ms-transform: translateX(-100px);
    -o-transform: translateX(-100px);
    transform: translateX(-100px);
  }
  60% {
    opacity: 1;
    -webkit-transform: translateX(20px);
    -moz-transform: translateX(20px);
    -ms-transform: translateX(20px);
    -o-transform: translateX(20px);
    transform: translateX(20px);
  }
  100% {
    -webkit-transform: translateX(0);
    -moz-transform: translateX(0);
    -ms-transform: translateX(0);
    -o-transform: translateX(0);
    transform: translateX(0);
  }
}

@-webkit-keyframes cd-bounce-2-inverse {
  0% {
    opacity: 0;
    -webkit-transform: translateX(100px);
  }
  60% {
    opacity: 1;
    -webkit-transform: translateX(-20px);
  }
  100% {
    -webkit-transform: translateX(0);
  }
}

@-moz-keyframes cd-bounce-2-inverse {
  0% {
    opacity: 0;
    -moz-transform: translateX(100px);
  }
  60% {
    opacity: 1;
    -moz-transform: translateX(-20px);
  }
  100% {
    -moz-transform: translateX(0);
  }
}

@keyframes cd-bounce-2-inverse {
  0% {
    opacity: 0;
    -webkit-transform: translateX(100px);
    -moz-transform: translateX(100px);
    -ms-transform: translateX(100px);
    -o-transform: translateX(100px);
    transform: translateX(100px);
  }
  60% {
    opacity: 1;
    -webkit-transform: translateX(-20px);
    -moz-transform: translateX(-20px);
    -ms-transform: translateX(-20px);
    -o-transform: translateX(-20px);
    transform: translateX(-20px);
  }
  100% {
    -webkit-transform: translateX(0);
    -moz-transform: translateX(0);
    -ms-transform: translateX(0);
    -o-transform: translateX(0);
    transform: translateX(0);
  }
}</code>```

<link href='http://fonts.googleapis.com/css?family=Droid+Serif|Open+Sans:400,700' rel='stylesheet' type='text/css'>

Title of section 1

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Iusto, optio, dolorum provident rerum aut hic quasi placeat iure tempora laudantium ipsa ad debitis unde? Iste voluptatibus minus veritatis qui ut.

      Read more
      Jan 14

Title of section 2

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Iusto, optio, dolorum provident rerum aut hic quasi placeat iure tempora laudantium ipsa ad debitis unde?

      Read more
      Jan 18

Title of section 3

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Excepturi, obcaecati, quisquam id molestias eaque asperiores voluptatibus cupiditate error assumenda delectus odit similique earum voluptatem doloremque dolorem ipsam quae rerum quis. Odit,
        itaque, deserunt corporis vero ipsum nisi eius odio natus ullam provident pariatur temporibus quia eos repellat consequuntur perferendis enim amet quae quasi repudiandae sed quod veniam dolore possimus rem voluptatum eveniet eligendi quis fugiat
        aliquam sunt similique aut adipisci.

      Read more
      Jan 24

Title of section 4

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Iusto, optio, dolorum provident rerum aut hic quasi placeat iure tempora laudantium ipsa ad debitis unde? Iste voluptatibus minus veritatis qui ut.

      Read more
      Feb 14

Title of section 5

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Iusto, optio, dolorum provident rerum.

      Read more
      Feb 18

Final Section

This is the content of the last section

      Feb 26

```

Body:
Vertical time line by Codyhouse! first you have to need call reset css, style css and jQuery I used png image but SVG would be better!

jQuery(document).ready(function($) {
  var timelineBlocks = $('.cd-timeline-block'),
    offset = 0.8;

  //hide timeline blocks which are outside the viewport
  hideBlocks(timelineBlocks, offset);

  //on scolling, show/animate timeline blocks when enter the viewport
  $(window).on('scroll', function() {
    (!window.requestAnimationFrame) ?
    setTimeout(function() {
      showBlocks(timelineBlocks, offset);
    }, 100): window.requestAnimationFrame(function() {
      showBlocks(timelineBlocks, offset);
    });
  });

  function hideBlocks(blocks, offset) {
    blocks.each(function() {
      ($(this).offset().top > $(window).scrollTop() + $(window).height() * offset) && $(this).find('.cd-timeline-img, .cd-timeline-content').addClass('is-hidden');
    });
  }

  function showBlocks(blocks, offset) {
    blocks.each(function() {
      ($(this).offset().top <= $(window).scrollTop() + $(window).height() * offset && $(this).find('.cd-timeline-img').hasClass('is-hidden')) && $(this).find('.cd-timeline-img, .cd-timeline-content').removeClass('is-hidden').addClass('bounce-in');
    });
  }
});

/* http://meyerweb.com/eric/tools/css/reset/
   v2.0 | 20110126
   License: none (public domain)
*/

html,
body,
div,
span,
applet,
object,
iframe,
h1,
h2,
h3,
h4,
h5,
h6,
p,
blockquote,
pre,
a,
abbr,
acronym,
address,
big,
cite,
code,
del,
dfn,
em,
img,
ins,
kbd,
q,
s,
samp,
small,
strike,
strong,
sub,
sup,
tt,
var,
b,
u,
i,
center,
dl,
dt,
dd,
ol,
ul,
li,
fieldset,
form,
label,
legend,
table,
caption,
tbody,
tfoot,
thead,
tr,
th,
td,
article,
aside,
canvas,
details,
embed,
figure,
figcaption,
footer,
header,
hgroup,
menu,
nav,
output,
ruby,
section,
summary,
time,
mark,
audio,
video {
  margin: 0;
  padding: 0;
  border: 0;
  font-size: 100%;
  font: inherit;
  vertical-align: baseline;
}

/* HTML5 display-role reset for older browsers */

article,
aside,
details,
figcaption,
figure,
footer,
header,
hgroup,
menu,
nav,
section,
main {
  display: block;
}

body {
  line-height: 1;
}

ol,
ul {
  list-style: none;
}

blockquote,
q {
  quotes: none;
}

blockquote:before,
blockquote:after,
q:before,
q:after {
  content: '';
  content: none;
}

table {
  border-collapse: collapse;
  border-spacing: 0;
}

/* --------------------------------

Primary style

-------------------------------- */

html * {
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

*,
*:after,
*:before {
  -webkit-box-sizing: border-box;
  -moz-box-sizing: border-box;
  box-sizing: border-box;
}

body {
  font-size: 100%;
  font-family: "Droid Serif", serif;
  color: #7f8c97;
  background-color: #e9f0f5;
}

a {
  color: #acb7c0;
  text-decoration: none;
  font-family: "Open Sans", sans-serif;
}

img {
  max-width: 100%;
}

h1,
h2 {
  font-family: "Open Sans", sans-serif;
  font-weight: bold;
}

/* --------------------------------

Modules - reusable parts of our design

-------------------------------- */

.cd-container {
  /* this class is used to give a max-width to the element it is applied to, and center it horizontally when it reaches that max-width */
  width: 90%;
  max-width: 1170px;
  margin: 0 auto;
}

.cd-container::after {
  /* clearfix */
  content: '';
  display: table;
  clear: both;
}

/* --------------------------------

Main components

-------------------------------- */

header {
  height: 200px;
  line-height: 200px;
  text-align: center;
  background: #303e49;
}

header h1 {
  color: white;
  font-size: 18px;
  font-size: 1.125rem;
}

@media only screen and (min-width: 1170px) {
  header {
    height: 300px;
    line-height: 300px;
  }
  header h1 {
    font-size: 24px;
    font-size: 1.5rem;
  }
}

#cd-timeline {
  position: relative;
  padding: 2em 0;
  margin-top: 2em;
  margin-bottom: 2em;
}

#cd-timeline::before {
  /* this is the vertical line */
  content: '';
  position: absolute;
  top: 0;
  left: 18px;
  height: 100%;
  width: 4px;
  background: #d7e4ed;
}

@media only screen and (min-width: 1170px) {
  #cd-timeline {
    margin-top: 3em;
    margin-bottom: 3em;
  }
  #cd-timeline::before {
    left: 50%;
    margin-left: -2px;
  }
}

.cd-timeline-block {
  position: relative;
  margin: 2em 0;
}

.cd-timeline-block:after {
  content: "";
  display: table;
  clear: both;
}

.cd-timeline-block:first-child {
  margin-top: 0;
}

.cd-timeline-block:last-child {
  margin-bottom: 0;
}

@media only screen and (min-width: 1170px) {
  .cd-timeline-block {
    margin: 4em 0;
  }
  .cd-timeline-block:first-child {
    margin-top: 0;
  }
  .cd-timeline-block:last-child {
    margin-bottom: 0;
  }
}

.cd-timeline-img {
  position: absolute;
  top: 0;
  left: 0;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  box-shadow: 0 0 0 4px white, inset 0 2px 0 rgba(0, 0, 0, 0.08), 0 3px 0 4px rgba(0, 0, 0, 0.05);
}

.cd-timeline-img img {
  display: block;
  width: 24px;
  height: 24px;
  position: relative;
  left: 50%;
  top: 50%;
  margin-left: -12px;
  margin-top: -12px;
}

.cd-timeline-img.cd-picture {
  background: #75ce66;
}

.cd-timeline-img.cd-movie {
  background: #c03b44;
}

.cd-timeline-img.cd-location {
  background: #f0ca45;
}

@media only screen and (min-width: 1170px) {
  .cd-timeline-img {
    width: 60px;
    height: 60px;
    left: 50%;
    margin-left: -30px;
    /* Force Hardware Acceleration in WebKit */
    -webkit-transform: translateZ(0);
    -webkit-backface-visibility: hidden;
  }
  .cssanimations .cd-timeline-img.is-hidden {
    visibility: hidden;
  }
  .cssanimations .cd-timeline-img.bounce-in {
    visibility: visible;
    -webkit-animation: cd-bounce-1 0.6s;
    -moz-animation: cd-bounce-1 0.6s;
    animation: cd-bounce-1 0.6s;
  }
}

@-webkit-keyframes cd-bounce-1 {
  0% {
    opacity: 0;
    -webkit-transform: scale(0.5);
  }
  60% {
    opacity: 1;
    -webkit-transform: scale(1.2);
  }
  100% {
    -webkit-transform: scale(1);
  }
}

@-moz-keyframes cd-bounce-1 {
  0% {
    opacity: 0;
    -moz-transform: scale(0.5);
  }
  60% {
    opacity: 1;
    -moz-transform: scale(1.2);
  }
  100% {
    -moz-transform: scale(1);
  }
}

@keyframes cd-bounce-1 {
  0% {
    opacity: 0;
    -webkit-transform: scale(0.5);
    -moz-transform: scale(0.5);
    -ms-transform: scale(0.5);
    -o-transform: scale(0.5);
    transform: scale(0.5);
  }
  60% {
    opacity: 1;
    -webkit-transform: scale(1.2);
    -moz-transform: scale(1.2);
    -ms-transform: scale(1.2);
    -o-transform: scale(1.2);
    transform: scale(1.2);
  }
  100% {
    -webkit-transform: scale(1);
    -moz-transform: scale(1);
    -ms-transform: scale(1);
    -o-transform: scale(1);
    transform: scale(1);
  }
}

.cd-timeline-content {
  position: relative;
  margin-left: 60px;
  background: white;
  border-radius: 0.25em;
  padding: 1em;
  box-shadow: 0 3px 0 #d7e4ed;
}

.cd-timeline-content:after {
  content: "";
  display: table;
  clear: both;
}

.cd-timeline-content h2 {
  color: #303e49;
}

.cd-timeline-content p,
.cd-timeline-content .cd-read-more,
.cd-timeline-content .cd-date {
  font-size: 13px;
  font-size: 0.8125rem;
}

.cd-timeline-content .cd-read-more,
.cd-timeline-content .cd-date {
  display: inline-block;
}

.cd-timeline-content p {
  margin: 1em 0;
  line-height: 1.6;
}

.cd-timeline-content .cd-read-more {
  float: right;
  padding: .8em 1em;
  background: #acb7c0;
  color: white;
  border-radius: 0.25em;
}

.no-touch .cd-timeline-content .cd-read-more:hover {
  background-color: #bac4cb;
}

.cd-timeline-content .cd-date {
  float: left;
  padding: .8em 0;
  opacity: .7;
}

.cd-timeline-content::before {
  content: '';
  position: absolute;
  top: 16px;
  right: 100%;
  height: 0;
  width: 0;
  border: 7px solid transparent;
  border-right: 7px solid white;
}

@media only screen and (min-width: 768px) {
  .cd-timeline-content h2 {
    font-size: 20px;
    font-size: 1.25rem;
  }
  .cd-timeline-content p {
    font-size: 16px;
    font-size: 1rem;
  }
  .cd-timeline-content .cd-read-more,
  .cd-timeline-content .cd-date {
    font-size: 14px;
    font-size: 0.875rem;
  }
}

@media only screen and (min-width: 1170px) {
  .cd-timeline-content {
    margin-left: 0;
    padding: 1.6em;
    width: 45%;
  }
  .cd-timeline-content::before {
    top: 24px;
    left: 100%;
    border-color: transparent;
    border-left-color: white;
  }
  .cd-timeline-content .cd-read-more {
    float: left;
  }
  .cd-timeline-content .cd-date {
    position: absolute;
    width: 100%;
    left: 122%;
    top: 6px;
    font-size: 16px;
    font-size: 1rem;
  }
  .cd-timeline-block:nth-child(even) .cd-timeline-content {
    float: right;
  }
  .cd-timeline-block:nth-child(even) .cd-timeline-content::before {
    top: 24px;
    left: auto;
    right: 100%;
    border-color: transparent;
    border-right-color: white;
  }
  .cd-timeline-block:nth-child(even) .cd-timeline-content .cd-read-more {
    float: right;
  }
  .cd-timeline-block:nth-child(even) .cd-timeline-content .cd-date {
    left: auto;
    right: 122%;
    text-align: right;
  }
  .cssanimations .cd-timeline-content.is-hidden {
    visibility: hidden;
  }
  .cssanimations .cd-timeline-content.bounce-in {
    visibility: visible;
    -webkit-animation: cd-bounce-2 0.6s;
    -moz-animation: cd-bounce-2 0.6s;
    animation: cd-bounce-2 0.6s;
  }
}

@media only screen and (min-width: 1170px) {
  /* inverse bounce effect on even content blocks */
  .cssanimations .cd-timeline-block:nth-child(even) .cd-timeline-content.bounce-in {
    -webkit-animation: cd-bounce-2-inverse 0.6s;
    -moz-animation: cd-bounce-2-inverse 0.6s;
    animation: cd-bounce-2-inverse 0.6s;
  }
}

@-webkit-keyframes cd-bounce-2 {
  0% {
    opacity: 0;
    -webkit-transform: translateX(-100px);
  }
  60% {
    opacity: 1;
    -webkit-transform: translateX(20px);
  }
  100% {
    -webkit-transform: translateX(0);
  }
}

@-moz-keyframes cd-bounce-2 {
  0% {
    opacity: 0;
    -moz-transform: translateX(-100px);
  }
  60% {
    opacity: 1;
    -moz-transform: translateX(20px);
  }
  100% {
    -moz-transform: translateX(0);
  }
}

@keyframes cd-bounce-2 {
  0% {
    opacity: 0;
    -webkit-transform: translateX(-100px);
    -moz-transform: translateX(-100px);
    -ms-transform: translateX(-100px);
    -o-transform: translateX(-100px);
    transform: translateX(-100px);
  }
  60% {
    opacity: 1;
    -webkit-transform: translateX(20px);
    -moz-transform: translateX(20px);
    -ms-transform: translateX(20px);
    -o-transform: translateX(20px);
    transform: translateX(20px);
  }
  100% {
    -webkit-transform: translateX(0);
    -moz-transform: translateX(0);
    -ms-transform: translateX(0);
    -o-transform: translateX(0);
    transform: translateX(0);
  }
}

@-webkit-keyframes cd-bounce-2-inverse {
  0% {
    opacity: 0;
    -webkit-transform: translateX(100px);
  }
  60% {
    opacity: 1;
    -webkit-transform: translateX(-20px);
  }
  100% {
    -webkit-transform: translateX(0);
  }
}

@-moz-keyframes cd-bounce-2-inverse {
  0% {
    opacity: 0;
    -moz-transform: translateX(100px);
  }
  60% {
    opacity: 1;
    -moz-transform: translateX(-20px);
  }
  100% {
    -moz-transform: translateX(0);
  }
}

@keyframes cd-bounce-2-inverse {
  0% {
    opacity: 0;
    -webkit-transform: translateX(100px);
    -moz-transform: translateX(100px);
    -ms-transform: translateX(100px);
    -o-transform: translateX(100px);
    transform: translateX(100px);
  }
  60% {
    opacity: 1;
    -webkit-transform: translateX(-20px);
    -moz-transform: translateX(-20px);
    -ms-transform: translateX(-20px);
    -o-transform: translateX(-20px);
    transform: translateX(-20px);
  }
  100% {
    -webkit-transform: translateX(0);
    -moz-transform: translateX(0);
    -ms-transform: translateX(0);
    -o-transform: translateX(0);
    transform: translateX(0);
  }
}

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link href='http://fonts.googleapis.com/css?family=Droid+Serif|Open+Sans:400,700' rel='stylesheet' type='text/css'>

<section id="cd-timeline" class="cd-container">
  <div class="cd-timeline-block">
    <div class="cd-timeline-img cd-picture">
      <img src="http://i.imgur.com/Q4yP2cI.png" alt="Picture">
    </div>
    <!-- cd-timeline-img -->

    <div class="cd-timeline-content">
      <h2>Title of section 1</h2>
      <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Iusto, optio, dolorum provident rerum aut hic quasi placeat iure tempora laudantium ipsa ad debitis unde? Iste voluptatibus minus veritatis qui ut.</p>
      <a href="#0" class="cd-read-more">Read more</a>
      <span class="cd-date">Jan 14</span>
    </div>
    <!-- cd-timeline-content -->
  </div>
  <!-- cd-timeline-block -->

  <div class="cd-timeline-block">
    <div class="cd-timeline-img cd-movie">
      <img src="http://i.imgur.com/Q4yP2cI.png" alt="Movie">
    </div>
    <!-- cd-timeline-img -->

    <div class="cd-timeline-content">
      <h2>Title of section 2</h2>
      <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Iusto, optio, dolorum provident rerum aut hic quasi placeat iure tempora laudantium ipsa ad debitis unde?</p>
      <a href="#0" class="cd-read-more">Read more</a>
      <span class="cd-date">Jan 18</span>
    </div>
    <!-- cd-timeline-content -->
  </div>
  <!-- cd-timeline-block -->

  <div class="cd-timeline-block">
    <div class="cd-timeline-img cd-picture">
      <img src="http://i.imgur.com/Q4yP2cI.png" alt="Picture">
    </div>
    <!-- cd-timeline-img -->

    <div class="cd-timeline-content">
      <h2>Title of section 3</h2>
      <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Excepturi, obcaecati, quisquam id molestias eaque asperiores voluptatibus cupiditate error assumenda delectus odit similique earum voluptatem doloremque dolorem ipsam quae rerum quis. Odit,
        itaque, deserunt corporis vero ipsum nisi eius odio natus ullam provident pariatur temporibus quia eos repellat consequuntur perferendis enim amet quae quasi repudiandae sed quod veniam dolore possimus rem voluptatum eveniet eligendi quis fugiat
        aliquam sunt similique aut adipisci.</p>
      <a href="#0" class="cd-read-more">Read more</a>
      <span class="cd-date">Jan 24</span>
    </div>
    <!-- cd-timeline-content -->
  </div>
  <!-- cd-timeline-block -->

  <div class="cd-timeline-block">
    <div class="cd-timeline-img cd-location">
      <img src="http://i.imgur.com/Q4yP2cI.png" alt="Location">
    </div>
    <!-- cd-timeline-img -->

    <div class="cd-timeline-content">
      <h2>Title of section 4</h2>
      <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Iusto, optio, dolorum provident rerum aut hic quasi placeat iure tempora laudantium ipsa ad debitis unde? Iste voluptatibus minus veritatis qui ut.</p>
      <a href="#0" class="cd-read-more">Read more</a>
      <span class="cd-date">Feb 14</span>
    </div>
    <!-- cd-timeline-content -->
  </div>
  <!-- cd-timeline-block -->

  <div class="cd-timeline-block">
    <div class="cd-timeline-img cd-location">
      <img src="http://i.imgur.com/Q4yP2cI.png" alt="Location">
    </div>
    <!-- cd-timeline-img -->

    <div class="cd-timeline-content">
      <h2>Title of section 5</h2>
      <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Iusto, optio, dolorum provident rerum.</p>
      <a href="#0" class="cd-read-more">Read more</a>
      <span class="cd-date">Feb 18</span>
    </div>
    <!-- cd-timeline-content -->
  </div>
  <!-- cd-timeline-block -->

  <div class="cd-timeline-block">
    <div class="cd-timeline-img cd-movie">
      <img src="http://i.imgur.com/Q4yP2cI.png" alt="Movie">
    </div>
    <!-- cd-timeline-img -->

    <div class="cd-timeline-content">
      <h2>Final Section</h2>
      <p>This is the content of the last section</p>
      <span class="cd-date">Feb 26</span>
    </div>
    <!-- cd-timeline-content -->
  </div>
  <!-- cd-timeline-block -->
</section>
<!-- cd-timeline -->


问:
html dropdown menu dependant on json data
I would like to change the file depending on the first option selected eg. if they pick "X" i want to access the "x.json file" if they select "V" then the "V.json file". do i do a filename= $(this) as below?

```<code>HTML:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
     "http://www.w3.org/TR/html4/strict.dtd">
<HTML>
<HEAD>
<TITLE>A document with SCRIPT</TITLE>
<META http-equiv="Content-Script-Type" content="text/tcl">
<script src="http://code.jquery.com/jquery-1.11.0.min.js"></script>

</SCRIPT>
</HEAD>
<BODY>

<select id="first-choice">
  <option selected value="base">Please Select</option>
  <option value="beverages">Beverages</option>
  <option value="snacks">Snacks</option>
</select>

<br>

<select id="second-choice">
  <option>Please choose from above</option>
</select>

<SCRIPT type="text/javascript">

$("#first-choice").change(function() {

    var $dropdown = $(this);

    $.getJSON("data.json", function(data) {

        var key = $dropdown.val();
        var vals = [];

        switch(key) {
            case 'beverages':
                vals = data.beverages.split(",");
                break;
            case 'snacks':
                vals = data.snacks.split(",");
                break;
            case 'base':
                vals = ['Please choose from above'];
        }

        var $secondChoice = $("#second-choice");
        $secondChoice.empty();
        $.each(vals, function(index, value) {
            $secondChoice.append("<option>" + value + "</option>");
        });

    });
});

</SCRIPT>
</BODY>
</HTML>
</code>```

JSON: (want to seperate into two files)

```<code>{
  "beverages": "Coffee,Coke",
  "snacks": "Chips,Cookies"
}
</code>```

答:
Try this:

var dummyData = {"beverages": "Coffee,Coke","snacks": "Chips,Cookies"};

$("#first-choice").change(function() {

    var key = $(this).val();
    $.getJSON("data.json", function(data) {
      handleResponse(data, key);
    }).fail(function(){
      //just using this call back to handle dummyData cause obviosly the url should fail
      handleResponse(dummyData, key);
    });
});

function handleResponse(data, key){
       var keyValues =  data[key];
       var options = '<option>Please choose from above</option>';

       if(keyValues) {
            options += keyValues.split(',').map(function(value){
            return '<option value ="'+value+'" >'+value+'</option>';
       })
       }
       //just overwriting options each time, think is better than appending
       $('#second-choice').html(options);

}```
<pre class="snippet-code-html lang-html prettyprint-override"><code><script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<select id="first-choice">
  <option selected value="base">Please Select</option>
  <option value="beverages">Beverages</option>
  <option value="snacks">Snacks</option>
</select>

<br>

<select id="second-choice">
  <option>Please choose from above</option>
</select></code>```

Body:
I would like to change the file depending on the first option selected eg. if they pick "X" i want to access the "x.json file" if they select "V" then the "V.json file". do i do a filename= $(this) as below?

HTML:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
     "http://www.w3.org/TR/html4/strict.dtd">

<TITLE>A document with SCRIPT</TITLE>
<META http-equiv="Content-Script-Type" content="text/tcl">

</SCRIPT>

<select id="first-choice">
  <option selected value="base">Please Select</option>
  <option value="beverages">Beverages</option>
  <option value="snacks">Snacks</option>
</select>

<select id="second-choice">
  <option>Please choose from above</option>
</select>

JSON: (want to seperate into two files)

{
  "beverages": "Coffee,Coke",
  "snacks": "Chips,Cookies"
}

Body:
Try this:

var dummyData = {"beverages": "Coffee,Coke","snacks": "Chips,Cookies"};

$("#first-choice").change(function() {

    var key = $(this).val();
    $.getJSON("data.json", function(data) {
      handleResponse(data, key);
    }).fail(function(){
      //just using this call back to handle dummyData cause obviosly the url should fail
      handleResponse(dummyData, key);
    });
});

function handleResponse(data, key){
       var keyValues =  data[key];
       var options = '<option>Please choose from above</option>';

       if(keyValues) {
            options += keyValues.split(',').map(function(value){
            return '<option value ="'+value+'" >'+value+'</option>';
       })
       }
       //just overwriting options each time, think is better than appending
       $('#second-choice').html(options);

}

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<select id="first-choice">
  <option selected value="base">Please Select</option>
  <option value="beverages">Beverages</option>
  <option value="snacks">Snacks</option>
</select>

<br>

<select id="second-choice">
  <option>Please choose from above</option>
</select>


问:
Dealing with immutability in a GUI-based application
I have a GUI based application (Kotlin) that consists of a list of Notes to the left (it shows the note's title) and the selected Note's edition screen to the right.

When the users modify the title in the edition screen, the list item must show the new title.

In a mutable world, I'd do something like this:

```<code>interface Note {
    fun title(): String
    fun content(): String
    fun setTitle(newTitle: String)
    fun setContent(newTitle: String)
    fun addListener(l: Listener)
}

class NoteListItem(n: Note) : Listener {

    init {
        n.addListener(this)
    }

    override fun onChange() { //from Listener
        repaint();
    }

    fun repaint() {
       //code
    }

}

class NoteEditionScreen(n: Note) {

    fun onTitleTextChanged(newTitle: String) {
        n.setTitle(newTitle)
    }

    //...

}
</code>```

Inside Note.setTitle method, listeners are notified.

Both "screens" have the same instance of Note, so changes are propagated.

However, with immutability:

```<code>interface Note {
    fun title()
    fun content()
    fun title(newTitle: String) : Note
    fun content(newContent: String) : Note
}
</code>```

the method Note.title(String) returns a new instance of Note instead of changing the state.

In that case, how can I "notify" to the NoteListItem the title has changed?

答:
Obviously, those two concepts don't go together nicely here.

The essence of the elements on your UI is: they allow for changes. The user doesn't know (or care) if the underlying object is immutable or  not. He wants to change that title.

Thus, there are two options for you:

give up on your Node being immutable

introduce an abstraction layer that is used by your UI

In other words: you can add a mutable NodeContainer that is used for displaying immutable node objects on your UI.

Now you have to balance between having the advantages of keeping your Node class immutable and the disadvantages of adding mutable wrapper thingy around the Node class. But that is your decision; depending on your context.

Body:
I have a GUI based application (Kotlin) that consists of a list of Notes to the left (it shows the note's title) and the selected Note's edition screen to the right.

When the users modify the title in the edition screen, the list item must show the new title.

In a mutable world, I'd do something like this:

interface Note {
    fun title(): String
    fun content(): String
    fun setTitle(newTitle: String)
    fun setContent(newTitle: String)
    fun addListener(l: Listener)
}

class NoteListItem(n: Note) : Listener {

    init {
        n.addListener(this)
    }

    override fun onChange() { //from Listener
        repaint();
    }

    fun repaint() {
       //code
    }

}

class NoteEditionScreen(n: Note) {

    fun onTitleTextChanged(newTitle: String) {
        n.setTitle(newTitle)
    }

    //...

}

Inside Note.setTitle method, listeners are notified.

Both "screens" have the same instance of Note, so changes are propagated.

However, with immutability:

interface Note {
    fun title()
    fun content()
    fun title(newTitle: String) : Note
    fun content(newContent: String) : Note
}

the method Note.title(String) returns a new instance of Note instead of changing the state.

In that case, how can I "notify" to the NoteListItem the title has changed?