问:
Read URLs for CSV files into vector
This question is similar to the one I asked here. I've tried the techniques from the answer, but for some reason I'm getting no matches to my xpath and am looking for some additional guidance.

I am trying to scrape the URLs of all the downloadable CSV files from the following webpage: Page with CSV Files. Here's what I've tried so far.

```<code>library(rvest)
library(dplyr)

myURL <- 'https://marketplace.spp.org/pages/rtbm-lmp-by-location#%2F2017%2F11%2FBy_Day'

attempt1 <- read_html( myURL ) %>%
  html_nodes( xpath='//*[contains(@class, "f-csv")]/..' ) %>%
  html_attr('href')

attempt2 <- read_html( myURL ) %>%
  html_nodes( xpath='//*[contains(@class, "files") and contains(@href, ".csv")]' ) %>%
  html_attr('href')
</code>```

Both attempts return empty character vectors. The calls to html_nodes() both return lists of zero elements.

When I search for the filemanager class in the page, I get a nonempty list, but I'm having trouble drilling down further.

This returns a non-empty list:

```<code>filemanager <- read_html( myURL ) %>%
  html_nodes( xpath='//*[contains(@class, "filemanager")]' )
</code>```

From right-clicking the download icon, I see the URL for the file dated 2017-11-01 (note the filename is different from the displayed update time) should be: https://marketplace.spp.org/file-api/download/rtbm-lmp-by-location?path=%2F2017%2F11%2FBy_Day%2FRTBM-LMP-DAILY-SL-20171101.csv. This downloads the CSV for me when I click it.

Any thoughts on how to return the download URLs for the CSV files?

答:
The site makes an XHR request and dynamically builds those blocks, so no amount of plain web scraping is going to work.

Hack-grabbing the XHR request that it makes isn't going to work either b/c the site is coded semi-well and has extensive CSRF protection.

So, we need to get one normal page of the site which has CSRF metadata in it, extract those tokens, then make a faux XHR request to the same target the page does.

The site was also pretty uniform (another sign they did OK w/r/t building the site/app) so it was fairly easy to make a generic function that lets you input year, month and "type" (I made some guesses based on the info in the 'boxes' on the site) and get a list of the contents of the CSV files back as data frames. By default, it uses the current year and month and defaults to "By_Day".

The CSVs take a bit to download, so it prints a message for each one as it downloads. You may not need that functionality, but it shld be straightforward to do what you need with the initial XHR response.

I tried to keep the dependencies to a minimum, but purrr and dplyr wld make for (IMO) better additions.

```<code>rtbm_lmp_by_location <- function(year = format(Sys.Date(), "%Y"),
                                 month = format(Sys.Date(), "%m"),
                                 by_type = c("By_Day", "By_Interval", "RePrice")) {

  require(rvest)
  require(jsonlite)
  require(httr)

  by_type <- match.arg(by_type, c("By_Day", "By_Interval", "RePrice"))

  res <- GET("https://marketplace.spp.org/pages/rtbm-lmp-by-location")
  doc <- content(res)

  x_csrf_token <- html_attr(html_node(doc, "meta[id='_csrf']"), "content")
  x_spp_csrf_token <- html_attr(html_node(doc, "meta[id='_spp_csrf']"), "content")

  POST(
    url = "https://marketplace.spp.org/file-api/",
    add_headers(
      Host = "marketplace.spp.org",
      Referer = "https://marketplace.spp.org/pages/rtbm-lmp-by-location",
      `X-CSRF-TOKEN` = x_csrf_token,
      `X-SPP-CSRF-TOKEN` = x_spp_csrf_token,
      `X-Requested-With` = "XMLHttpRequest"
    ),
    body = list(
      name = "rtbm-lmp-by-location",
      fsName = "rtbm-lmp-by-location",
      type = "folder",
      path = sprintf("/%s/%s/%s", year, month, by_type)
    ),
    encode = "json"
  ) -> res

  res <- content(res, as="text")
  res <- jsonlite::fromJSON(res, flatten=TRUE)
  res$path <- sprintf("https://marketplace.spp.org/file-api/download/rtbm-lmp-by-location?path=%s",
                      res$path)

  lapply(res$path, function(.x) {
    message(sprintf("Downloading <%s>...", .x))
    read.csv(.x, stringsAsFactors=FALSE)
  })

}

fils <- rtbm_lmp_by_location()
## Downloading <https://marketplace.spp.org/file-api/download/rtbm-lmp-by-location?path=/2017/11/By_Day/RTBM-LMP-DAILY-SL-20171101.csv>...
## Downloading <https://marketplace.spp.org/file-api/download/rtbm-lmp-by-location?path=/2017/11/By_Day/RTBM-LMP-DAILY-SL-20171102.csv>...
## Downloading <https://marketplace.spp.org/file-api/download/rtbm-lmp-by-location?path=/2017/11/By_Day/RTBM-LMP-DAILY-SL-20171103.csv>...
## Downloading <https://marketplace.spp.org/file-api/download/rtbm-lmp-by-location?path=/2017/11/By_Day/RTBM-LMP-DAILY-SL-20171104.csv>...
## Downloading <https://marketplace.spp.org/file-api/download/rtbm-lmp-by-location?path=/2017/11/By_Day/RTBM-LMP-DAILY-SL-20171105.csv>...
## Downloading <https://marketplace.spp.org/file-api/download/rtbm-lmp-by-location?path=/2017/11/By_Day/RTBM-LMP-DAILY-SL-20171106.csv>...
## Downloading <https://marketplace.spp.org/file-api/download/rtbm-lmp-by-location?path=/2017/11/By_Day/RTBM-LMP-DAILY-SL-20171107.csv>...
## Downloading <https://marketplace.spp.org/file-api/download/rtbm-lmp-by-location?path=/2017/11/By_Day/RTBM-LMP-DAILY-SL-20171108.csv>...
</code>```

And, here's the data it pulled back:

```<code>str(fils)
## List of 8
##  $ :'data.frame': 272448 obs. of  8 variables:
##   ..$ Interval                : chr [1:272448] "11/01/2017 00:05:00" "11/01/2017 00:05:00" "11/01/2017 00:05:00" "11/01/2017 00:05:00" ...
##   ..$ GMT.Interval            : chr [1:272448] "11/01/2017 05:05:00" "11/01/2017 05:05:00" "11/01/2017 05:05:00" "11/01/2017 05:05:00" ...
##   ..$ Settlement.Location.Name: chr [1:272448] "AEC" "AECC_CSWS" "AECC_ELKINS" "AECC_FITZHUGH" ...
##   ..$ PNODE.Name              : chr [1:272448] "SOUC" "CSWS_AECC_LA" "CSWSELKINSUNELKINS_RA" "CSWSFITZHUGHPLT1" ...
##   ..$ LMP                     : num [1:272448] 16.2 18 21.3 15.9 21.4 ...
##   ..$ MLC                     : num [1:272448] 0.8342 0.3078 0.0295 0.5966 -0.1799 ...
##   ..$ MCC                     : num [1:272448] 0 2.34 5.94 0 6.19 ...
##   ..$ MEC                     : num [1:272448] 15.3 15.3 15.3 15.3 15.3 ...
##  $ :'data.frame': 272448 obs. of  8 variables:
##   ..$ Interval                : chr [1:272448] "11/02/2017 00:05:00" "11/02/2017 00:05:00" "11/02/2017 00:05:00" "11/02/2017 00:05:00" ...
##   ..$ GMT.Interval            : chr [1:272448] "11/02/2017 05:05:00" "11/02/2017 05:05:00" "11/02/2017 05:05:00" "11/02/2017 05:05:00" ...
##   ..$ Settlement.Location.Name: chr [1:272448] "AEC" "AECC_CSWS" "AECC_ELKINS" "AECC_FITZHUGH" ...
##   ..$ PNODE.Name              : chr [1:272448] "SOUC" "CSWS_AECC_LA" "CSWSELKINSUNELKINS_RA" "CSWSFITZHUGHPLT1" ...
##   ..$ LMP                     : num [1:272448] 17.1 16.7 16.6 16.8 16.4 ...
##   ..$ MLC                     : num [1:272448] 0.5527 0.1549 0.0498 0.2766 -0.1663 ...
##   ..$ MCC                     : num [1:272448] 0 0 0 0 0 0 0 0 0 0 ...
##   ..$ MEC                     : num [1:272448] 16.6 16.6 16.6 16.6 16.6 ...
##  $ :'data.frame': 272448 obs. of  8 variables:
##   ..$ Interval                : chr [1:272448] "11/03/2017 00:05:00" "11/03/2017 00:05:00" "11/03/2017 00:05:00" "11/03/2017 00:05:00" ...
##   ..$ GMT.Interval            : chr [1:272448] "11/03/2017 05:05:00" "11/03/2017 05:05:00" "11/03/2017 05:05:00" "11/03/2017 05:05:00" ...
##   ..$ Settlement.Location.Name: chr [1:272448] "AEC" "AECC_CSWS" "AECC_ELKINS" "AECC_FITZHUGH" ...
##   ..$ PNODE.Name              : chr [1:272448] "SOUC" "CSWS_AECC_LA" "CSWSELKINSUNELKINS_RA" "CSWSFITZHUGHPLT1" ...
##   ..$ LMP                     : num [1:272448] 18.9 18.3 17.8 18.6 17.5 ...
##   ..$ MLC                     : num [1:272448] 0.819 0.191 -0.221 0.566 -0.584 ...
##   ..$ MCC                     : num [1:272448] 0 0 0 0 0 0 0 0 -0.0076 0 ...
##   ..$ MEC                     : num [1:272448] 18.1 18.1 18.1 18.1 18.1 ...
##  $ :'data.frame': 272448 obs. of  8 variables:
##   ..$ Interval                : chr [1:272448] "11/04/2017 00:05:00" "11/04/2017 00:05:00" "11/04/2017 00:05:00" "11/04/2017 00:05:00" ...
##   ..$ GMT.Interval            : chr [1:272448] "11/04/2017 05:05:00" "11/04/2017 05:05:00" "11/04/2017 05:05:00" "11/04/2017 05:05:00" ...
##   ..$ Settlement.Location.Name: chr [1:272448] "AEC" "AECC_CSWS" "AECC_ELKINS" "AECC_FITZHUGH" ...
##   ..$ PNODE.Name              : chr [1:272448] "SOUC" "CSWS_AECC_LA" "CSWSELKINSUNELKINS_RA" "CSWSFITZHUGHPLT1" ...
##   ..$ LMP                     : num [1:272448] 0.0107 4.4038 5.2691 0.0108 5.1795 ...
##   ..$ MLC                     : num [1:272448] 3e-04 2e-04 0e+00 4e-04 -1e-04 1e-04 -1e-04 0e+00 1e-04 3e-04 ...
##   ..$ MCC                     : num [1:272448] 0 4.39 5.26 0 5.17 ...
##   ..$ MEC                     : num [1:272448] 0.0104 0.0104 0.0104 0.0104 0.0104 0.0104 0.0104 0.0104 0.0105 0.0104 ...
##  $ :'data.frame': 283800 obs. of  8 variables:
##   ..$ Interval                : chr [1:283800] "11/05/2017 00:05:00" "11/05/2017 00:05:00" "11/05/2017 00:05:00" "11/05/2017 00:05:00" ...
##   ..$ GMT.Interval            : chr [1:283800] "11/05/2017 05:05:00" "11/05/2017 05:05:00" "11/05/2017 05:05:00" "11/05/2017 05:05:00" ...
##   ..$ Settlement.Location.Name: chr [1:283800] "AEC" "AECC_CSWS" "AECC_ELKINS" "AECC_FITZHUGH" ...
##   ..$ PNODE.Name              : chr [1:283800] "SOUC" "CSWS_AECC_LA" "CSWSELKINSUNELKINS_RA" "CSWSFITZHUGHPLT1" ...
##   ..$ LMP                     : num [1:283800] 12 14.7 18.4 12.1 18.6 ...
##   ..$ MLC                     : num [1:283800] 0.4667 0.3877 0.2521 0.5528 0.0704 ...
##   ..$ MCC                     : num [1:283800] 0.0008 2.8321 6.6661 0 7.0045 ...
##   ..$ MEC                     : num [1:283800] 11.5 11.5 11.5 11.5 11.5 ...
##  $ :'data.frame': 272448 obs. of  8 variables:
##   ..$ Interval                : chr [1:272448] "11/06/2017 00:05:00" "11/06/2017 00:05:00" "11/06/2017 00:05:00" "11/06/2017 00:05:00" ...
##   ..$ GMT.Interval            : chr [1:272448] "11/06/2017 06:05:00" "11/06/2017 06:05:00" "11/06/2017 06:05:00" "11/06/2017 06:05:00" ...
##   ..$ Settlement.Location.Name: chr [1:272448] "AEC" "AECC_CSWS" "AECC_ELKINS" "AECC_FITZHUGH" ...
##   ..$ PNODE.Name              : chr [1:272448] "SOUC" "CSWS_AECC_LA" "CSWSELKINSUNELKINS_RA" "CSWSFITZHUGHPLT1" ...
##   ..$ LMP                     : num [1:272448] 19.6 19.1 19.1 19.5 18.7 ...
##   ..$ MLC                     : num [1:272448] 0.0621 0.0153 0.0905 0.2946 -0.2689 ...
##   ..$ MCC                     : num [1:272448] 0.6728 0.2223 0.0854 0.282 0.0761 ...
##   ..$ MEC                     : num [1:272448] 18.9 18.9 18.9 18.9 18.9 ...
##  $ :'data.frame': 272448 obs. of  8 variables:
##   ..$ Interval                : chr [1:272448] "11/07/2017 00:05:00" "11/07/2017 00:05:00" "11/07/2017 00:05:00" "11/07/2017 00:05:00" ...
##   ..$ GMT.Interval            : chr [1:272448] "11/07/2017 06:05:00" "11/07/2017 06:05:00" "11/07/2017 06:05:00" "11/07/2017 06:05:00" ...
##   ..$ Settlement.Location.Name: chr [1:272448] "AEC" "AECC_CSWS" "AECC_ELKINS" "AECC_FITZHUGH" ...
##   ..$ PNODE.Name              : chr [1:272448] "SOUC" "CSWS_AECC_LA" "CSWSELKINSUNELKINS_RA" "CSWSFITZHUGHPLT1" ...
##   ..$ LMP                     : num [1:272448] 21.5 20.2 19.6 21.1 19.2 ...
##   ..$ MLC                     : num [1:272448] 0.232 -0.277 -0.62 0.344 -0.985 ...
##   ..$ MCC                     : num [1:272448] 0 -0.819 -1.145 -0.58 -1.156 ...
##   ..$ MEC                     : num [1:272448] 21.3 21.3 21.3 21.3 21.3 ...
##  $ :'data.frame': 272448 obs. of  8 variables:
##   ..$ Interval                : chr [1:272448] "11/08/2017 00:05:00" "11/08/2017 00:05:00" "11/08/2017 00:05:00" "11/08/2017 00:05:00" ...
##   ..$ GMT.Interval            : chr [1:272448] "11/08/2017 06:05:00" "11/08/2017 06:05:00" "11/08/2017 06:05:00" "11/08/2017 06:05:00" ...
##   ..$ Settlement.Location.Name: chr [1:272448] "AEC" "AECC_CSWS" "AECC_ELKINS" "AECC_FITZHUGH" ...
##   ..$ PNODE.Name              : chr [1:272448] "SOUC" "CSWS_AECC_LA" "CSWSELKINSUNELKINS_RA" "CSWSFITZHUGHPLT1" ...
##   ..$ LMP                     : num [1:272448] 19 19 18.9 19.4 18.6 ...
##   ..$ MLC                     : num [1:272448] 0.1562 0.1086 0.0215 0.465 -0.3251 ...
##   ..$ MCC                     : num [1:272448] 0 0 0 0 0 0 0 0 0 0 ...
##   ..$ MEC                     : num [1:272448] 18.9 18.9 18.9 18.9 18.9 ...
</code>```

Having done all that and seeing the URLs it retrieves:

```<code>https://marketplace.spp.org/file-api/download/rtbm-lmp-by-location?path=/2017/11/By_Day/RTBM-LMP-DAILY-SL-20171108.csv
</code>```

You can really not even bother with all ^^ and just sprintf() or glue the variable path components together for any given day of the year:

```<code>rtbm_lmp_by_location_by_day <- function(date) {
  date <- as.Date(date)
  y <- format(date, "%Y")
  m <- as.numeric(format(date, "%m"))
  ymd <- format(date, "%Y%m%d")
  sprintf("https://marketplace.spp.org/file-api/download/rtbm-lmp-by-location?path=/%s/%s/By_Day/RTBM-LMP-DAILY-SL-%s.csv",
          y, m, ymd) -> fil
  res <- httr::HEAD(fil)
  if (httr::status_code(res) != 200) {
    message("File not found")
    return(invisible(NULL))
  } else {
    message(sprintf("Downloading <%s>", fil))
    read.csv(fil, stringsAsFactors=FALSE)
  }
}

xdf <- rtbm_lmp_by_location_by_day("2017-11-08")
## Downloading <https://marketplace.spp.org/file-api/download/rtbm-lmp-by-location?path=/2017/11/By_Day/RTBM-LMP-DAILY-SL-20171108.csv>

str(xdf)
## 'data.frame': 272448 obs. of  8 variables:
##  $ Interval                : chr  "11/08/2017 00:05:00" "11/08/2017 00:05:00" "11/08/2017 00:05:00" "11/08/2017 00:05:00" ...
##  $ GMT.Interval            : chr  "11/08/2017 06:05:00" "11/08/2017 06:05:00" "11/08/2017 06:05:00" "11/08/2017 06:05:00" ...
##  $ Settlement.Location.Name: chr  "AEC" "AECC_CSWS" "AECC_ELKINS" "AECC_FITZHUGH" ...
##  $ PNODE.Name              : chr  "SOUC" "CSWS_AECC_LA" "CSWSELKINSUNELKINS_RA" "CSWSFITZHUGHPLT1" ...
##  $ LMP                     : num  19 19 18.9 19.4 18.6 ...
##  $ MLC                     : num  0.1562 0.1086 0.0215 0.465 -0.3251 ...
##  $ MCC                     : num  0 0 0 0 0 0 0 0 0 0 ...
##  $ MEC                     : num  18.9 18.9 18.9 18.9 18.9 ...
</code>```

It shld be a straightforward process to figure out the patterns for the other categories.

Title: Read URLs for CSV files into vector

Body:
This question is similar to the one I asked here. I've tried the techniques from the answer, but for some reason I'm getting no matches to my xpath and am looking for some additional guidance.

I am trying to scrape the URLs of all the downloadable CSV files from the following webpage: Page with CSV Files. Here's what I've tried so far.

library(rvest)
library(dplyr)

myURL <- 'https://marketplace.spp.org/pages/rtbm-lmp-by-location#%2F2017%2F11%2FBy_Day'

attempt1 <- read_html( myURL ) %>%
  html_nodes( xpath='//*[contains(@class, "f-csv")]/..' ) %>%
  html_attr('href')

attempt2 <- read_html( myURL ) %>%
  html_nodes( xpath='//*[contains(@class, "files") and contains(@href, ".csv")]' ) %>%
  html_attr('href')

Both attempts return empty character vectors. The calls to html_nodes() both return lists of zero elements.

When I search for the filemanager class in the page, I get a nonempty list, but I'm having trouble drilling down further.

This returns a non-empty list:

filemanager <- read_html( myURL ) %>%
  html_nodes( xpath='//*[contains(@class, "filemanager")]' )

From right-clicking the download icon, I see the URL for the file dated 2017-11-01 (note the filename is different from the displayed update time) should be: https://marketplace.spp.org/file-api/download/rtbm-lmp-by-location?path=%2F2017%2F11%2FBy_Day%2FRTBM-LMP-DAILY-SL-20171101.csv. This downloads the CSV for me when I click it.

Any thoughts on how to return the download URLs for the CSV files?

Body:
The site makes an XHR request and dynamically builds those blocks, so no amount of plain web scraping is going to work.

Hack-grabbing the XHR request that it makes isn't going to work either b/c the site is coded semi-well and has extensive CSRF protection.

So, we need to get one normal page of the site which has CSRF metadata in it, extract those tokens, then make a faux XHR request to the same target the page does.

The site was also pretty uniform (another sign they did OK w/r/t building the site/app) so it was fairly easy to make a generic function that lets you input year, month and "type" (I made some guesses based on the info in the 'boxes' on the site) and get a list of the contents of the CSV files back as data frames. By default, it uses the current year and month and defaults to "By_Day".

The CSVs take a bit to download, so it prints a message for each one as it downloads. You may not need that functionality, but it shld be straightforward to do what you need with the initial XHR response.

I tried to keep the dependencies to a minimum, but purrr and dplyr wld make for (IMO) better additions.

rtbm_lmp_by_location <- function(year = format(Sys.Date(), "%Y"),
                                 month = format(Sys.Date(), "%m"),
                                 by_type = c("By_Day", "By_Interval", "RePrice")) {

  require(rvest)
  require(jsonlite)
  require(httr)

  by_type <- match.arg(by_type, c("By_Day", "By_Interval", "RePrice"))

  res <- GET("https://marketplace.spp.org/pages/rtbm-lmp-by-location")
  doc <- content(res)

  x_csrf_token <- html_attr(html_node(doc, "meta[id='_csrf']"), "content")
  x_spp_csrf_token <- html_attr(html_node(doc, "meta[id='_spp_csrf']"), "content")

  POST(
    url = "https://marketplace.spp.org/file-api/",
    add_headers(
      Host = "marketplace.spp.org",
      Referer = "https://marketplace.spp.org/pages/rtbm-lmp-by-location",
      `X-CSRF-TOKEN` = x_csrf_token,
      `X-SPP-CSRF-TOKEN` = x_spp_csrf_token,
      `X-Requested-With` = "XMLHttpRequest"
    ),
    body = list(
      name = "rtbm-lmp-by-location",
      fsName = "rtbm-lmp-by-location",
      type = "folder",
      path = sprintf("/%s/%s/%s", year, month, by_type)
    ),
    encode = "json"
  ) -> res

  res <- content(res, as="text")
  res <- jsonlite::fromJSON(res, flatten=TRUE)
  res$path <- sprintf("https://marketplace.spp.org/file-api/download/rtbm-lmp-by-location?path=%s",
                      res$path)

  lapply(res$path, function(.x) {
    message(sprintf("Downloading <%s>...", .x))
    read.csv(.x, stringsAsFactors=FALSE)
  })

}

fils <- rtbm_lmp_by_location()
## Downloading <https://marketplace.spp.org/file-api/download/rtbm-lmp-by-location?path=/2017/11/By_Day/RTBM-LMP-DAILY-SL-20171101.csv>...
## Downloading <https://marketplace.spp.org/file-api/download/rtbm-lmp-by-location?path=/2017/11/By_Day/RTBM-LMP-DAILY-SL-20171102.csv>...
## Downloading <https://marketplace.spp.org/file-api/download/rtbm-lmp-by-location?path=/2017/11/By_Day/RTBM-LMP-DAILY-SL-20171103.csv>...
## Downloading <https://marketplace.spp.org/file-api/download/rtbm-lmp-by-location?path=/2017/11/By_Day/RTBM-LMP-DAILY-SL-20171104.csv>...
## Downloading <https://marketplace.spp.org/file-api/download/rtbm-lmp-by-location?path=/2017/11/By_Day/RTBM-LMP-DAILY-SL-20171105.csv>...
## Downloading <https://marketplace.spp.org/file-api/download/rtbm-lmp-by-location?path=/2017/11/By_Day/RTBM-LMP-DAILY-SL-20171106.csv>...
## Downloading <https://marketplace.spp.org/file-api/download/rtbm-lmp-by-location?path=/2017/11/By_Day/RTBM-LMP-DAILY-SL-20171107.csv>...
## Downloading <https://marketplace.spp.org/file-api/download/rtbm-lmp-by-location?path=/2017/11/By_Day/RTBM-LMP-DAILY-SL-20171108.csv>...

And, here's the data it pulled back:

str(fils)
## List of 8
##  $ :'data.frame': 272448 obs. of  8 variables:
##   ..$ Interval                : chr [1:272448] "11/01/2017 00:05:00" "11/01/2017 00:05:00" "11/01/2017 00:05:00" "11/01/2017 00:05:00" ...
##   ..$ GMT.Interval            : chr [1:272448] "11/01/2017 05:05:00" "11/01/2017 05:05:00" "11/01/2017 05:05:00" "11/01/2017 05:05:00" ...
##   ..$ Settlement.Location.Name: chr [1:272448] "AEC" "AECC_CSWS" "AECC_ELKINS" "AECC_FITZHUGH" ...
##   ..$ PNODE.Name              : chr [1:272448] "SOUC" "CSWS_AECC_LA" "CSWSELKINSUNELKINS_RA" "CSWSFITZHUGHPLT1" ...
##   ..$ LMP                     : num [1:272448] 16.2 18 21.3 15.9 21.4 ...
##   ..$ MLC                     : num [1:272448] 0.8342 0.3078 0.0295 0.5966 -0.1799 ...
##   ..$ MCC                     : num [1:272448] 0 2.34 5.94 0 6.19 ...
##   ..$ MEC                     : num [1:272448] 15.3 15.3 15.3 15.3 15.3 ...
##  $ :'data.frame': 272448 obs. of  8 variables:
##   ..$ Interval                : chr [1:272448] "11/02/2017 00:05:00" "11/02/2017 00:05:00" "11/02/2017 00:05:00" "11/02/2017 00:05:00" ...
##   ..$ GMT.Interval            : chr [1:272448] "11/02/2017 05:05:00" "11/02/2017 05:05:00" "11/02/2017 05:05:00" "11/02/2017 05:05:00" ...
##   ..$ Settlement.Location.Name: chr [1:272448] "AEC" "AECC_CSWS" "AECC_ELKINS" "AECC_FITZHUGH" ...
##   ..$ PNODE.Name              : chr [1:272448] "SOUC" "CSWS_AECC_LA" "CSWSELKINSUNELKINS_RA" "CSWSFITZHUGHPLT1" ...
##   ..$ LMP                     : num [1:272448] 17.1 16.7 16.6 16.8 16.4 ...
##   ..$ MLC                     : num [1:272448] 0.5527 0.1549 0.0498 0.2766 -0.1663 ...
##   ..$ MCC                     : num [1:272448] 0 0 0 0 0 0 0 0 0 0 ...
##   ..$ MEC                     : num [1:272448] 16.6 16.6 16.6 16.6 16.6 ...
##  $ :'data.frame': 272448 obs. of  8 variables:
##   ..$ Interval                : chr [1:272448] "11/03/2017 00:05:00" "11/03/2017 00:05:00" "11/03/2017 00:05:00" "11/03/2017 00:05:00" ...
##   ..$ GMT.Interval            : chr [1:272448] "11/03/2017 05:05:00" "11/03/2017 05:05:00" "11/03/2017 05:05:00" "11/03/2017 05:05:00" ...
##   ..$ Settlement.Location.Name: chr [1:272448] "AEC" "AECC_CSWS" "AECC_ELKINS" "AECC_FITZHUGH" ...
##   ..$ PNODE.Name              : chr [1:272448] "SOUC" "CSWS_AECC_LA" "CSWSELKINSUNELKINS_RA" "CSWSFITZHUGHPLT1" ...
##   ..$ LMP                     : num [1:272448] 18.9 18.3 17.8 18.6 17.5 ...
##   ..$ MLC                     : num [1:272448] 0.819 0.191 -0.221 0.566 -0.584 ...
##   ..$ MCC                     : num [1:272448] 0 0 0 0 0 0 0 0 -0.0076 0 ...
##   ..$ MEC                     : num [1:272448] 18.1 18.1 18.1 18.1 18.1 ...
##  $ :'data.frame': 272448 obs. of  8 variables:
##   ..$ Interval                : chr [1:272448] "11/04/2017 00:05:00" "11/04/2017 00:05:00" "11/04/2017 00:05:00" "11/04/2017 00:05:00" ...
##   ..$ GMT.Interval            : chr [1:272448] "11/04/2017 05:05:00" "11/04/2017 05:05:00" "11/04/2017 05:05:00" "11/04/2017 05:05:00" ...
##   ..$ Settlement.Location.Name: chr [1:272448] "AEC" "AECC_CSWS" "AECC_ELKINS" "AECC_FITZHUGH" ...
##   ..$ PNODE.Name              : chr [1:272448] "SOUC" "CSWS_AECC_LA" "CSWSELKINSUNELKINS_RA" "CSWSFITZHUGHPLT1" ...
##   ..$ LMP                     : num [1:272448] 0.0107 4.4038 5.2691 0.0108 5.1795 ...
##   ..$ MLC                     : num [1:272448] 3e-04 2e-04 0e+00 4e-04 -1e-04 1e-04 -1e-04 0e+00 1e-04 3e-04 ...
##   ..$ MCC                     : num [1:272448] 0 4.39 5.26 0 5.17 ...
##   ..$ MEC                     : num [1:272448] 0.0104 0.0104 0.0104 0.0104 0.0104 0.0104 0.0104 0.0104 0.0105 0.0104 ...
##  $ :'data.frame': 283800 obs. of  8 variables:
##   ..$ Interval                : chr [1:283800] "11/05/2017 00:05:00" "11/05/2017 00:05:00" "11/05/2017 00:05:00" "11/05/2017 00:05:00" ...
##   ..$ GMT.Interval            : chr [1:283800] "11/05/2017 05:05:00" "11/05/2017 05:05:00" "11/05/2017 05:05:00" "11/05/2017 05:05:00" ...
##   ..$ Settlement.Location.Name: chr [1:283800] "AEC" "AECC_CSWS" "AECC_ELKINS" "AECC_FITZHUGH" ...
##   ..$ PNODE.Name              : chr [1:283800] "SOUC" "CSWS_AECC_LA" "CSWSELKINSUNELKINS_RA" "CSWSFITZHUGHPLT1" ...
##   ..$ LMP                     : num [1:283800] 12 14.7 18.4 12.1 18.6 ...
##   ..$ MLC                     : num [1:283800] 0.4667 0.3877 0.2521 0.5528 0.0704 ...
##   ..$ MCC                     : num [1:283800] 0.0008 2.8321 6.6661 0 7.0045 ...
##   ..$ MEC                     : num [1:283800] 11.5 11.5 11.5 11.5 11.5 ...
##  $ :'data.frame': 272448 obs. of  8 variables:
##   ..$ Interval                : chr [1:272448] "11/06/2017 00:05:00" "11/06/2017 00:05:00" "11/06/2017 00:05:00" "11/06/2017 00:05:00" ...
##   ..$ GMT.Interval            : chr [1:272448] "11/06/2017 06:05:00" "11/06/2017 06:05:00" "11/06/2017 06:05:00" "11/06/2017 06:05:00" ...
##   ..$ Settlement.Location.Name: chr [1:272448] "AEC" "AECC_CSWS" "AECC_ELKINS" "AECC_FITZHUGH" ...
##   ..$ PNODE.Name              : chr [1:272448] "SOUC" "CSWS_AECC_LA" "CSWSELKINSUNELKINS_RA" "CSWSFITZHUGHPLT1" ...
##   ..$ LMP                     : num [1:272448] 19.6 19.1 19.1 19.5 18.7 ...
##   ..$ MLC                     : num [1:272448] 0.0621 0.0153 0.0905 0.2946 -0.2689 ...
##   ..$ MCC                     : num [1:272448] 0.6728 0.2223 0.0854 0.282 0.0761 ...
##   ..$ MEC                     : num [1:272448] 18.9 18.9 18.9 18.9 18.9 ...
##  $ :'data.frame': 272448 obs. of  8 variables:
##   ..$ Interval                : chr [1:272448] "11/07/2017 00:05:00" "11/07/2017 00:05:00" "11/07/2017 00:05:00" "11/07/2017 00:05:00" ...
##   ..$ GMT.Interval            : chr [1:272448] "11/07/2017 06:05:00" "11/07/2017 06:05:00" "11/07/2017 06:05:00" "11/07/2017 06:05:00" ...
##   ..$ Settlement.Location.Name: chr [1:272448] "AEC" "AECC_CSWS" "AECC_ELKINS" "AECC_FITZHUGH" ...
##   ..$ PNODE.Name              : chr [1:272448] "SOUC" "CSWS_AECC_LA" "CSWSELKINSUNELKINS_RA" "CSWSFITZHUGHPLT1" ...
##   ..$ LMP                     : num [1:272448] 21.5 20.2 19.6 21.1 19.2 ...
##   ..$ MLC                     : num [1:272448] 0.232 -0.277 -0.62 0.344 -0.985 ...
##   ..$ MCC                     : num [1:272448] 0 -0.819 -1.145 -0.58 -1.156 ...
##   ..$ MEC                     : num [1:272448] 21.3 21.3 21.3 21.3 21.3 ...
##  $ :'data.frame': 272448 obs. of  8 variables:
##   ..$ Interval                : chr [1:272448] "11/08/2017 00:05:00" "11/08/2017 00:05:00" "11/08/2017 00:05:00" "11/08/2017 00:05:00" ...
##   ..$ GMT.Interval            : chr [1:272448] "11/08/2017 06:05:00" "11/08/2017 06:05:00" "11/08/2017 06:05:00" "11/08/2017 06:05:00" ...
##   ..$ Settlement.Location.Name: chr [1:272448] "AEC" "AECC_CSWS" "AECC_ELKINS" "AECC_FITZHUGH" ...
##   ..$ PNODE.Name              : chr [1:272448] "SOUC" "CSWS_AECC_LA" "CSWSELKINSUNELKINS_RA" "CSWSFITZHUGHPLT1" ...
##   ..$ LMP                     : num [1:272448] 19 19 18.9 19.4 18.6 ...
##   ..$ MLC                     : num [1:272448] 0.1562 0.1086 0.0215 0.465 -0.3251 ...
##   ..$ MCC                     : num [1:272448] 0 0 0 0 0 0 0 0 0 0 ...
##   ..$ MEC                     : num [1:272448] 18.9 18.9 18.9 18.9 18.9 ...

Having done all that and seeing the URLs it retrieves:

https://marketplace.spp.org/file-api/download/rtbm-lmp-by-location?path=/2017/11/By_Day/RTBM-LMP-DAILY-SL-20171108.csv

You can really not even bother with all ^^ and just sprintf() or glue the variable path components together for any given day of the year:

rtbm_lmp_by_location_by_day <- function(date) {
  date <- as.Date(date)
  y <- format(date, "%Y")
  m <- as.numeric(format(date, "%m"))
  ymd <- format(date, "%Y%m%d")
  sprintf("https://marketplace.spp.org/file-api/download/rtbm-lmp-by-location?path=/%s/%s/By_Day/RTBM-LMP-DAILY-SL-%s.csv",
          y, m, ymd) -> fil
  res <- httr::HEAD(fil)
  if (httr::status_code(res) != 200) {
    message("File not found")
    return(invisible(NULL))
  } else {
    message(sprintf("Downloading <%s>", fil))
    read.csv(fil, stringsAsFactors=FALSE)
  }
}

xdf <- rtbm_lmp_by_location_by_day("2017-11-08")
## Downloading <https://marketplace.spp.org/file-api/download/rtbm-lmp-by-location?path=/2017/11/By_Day/RTBM-LMP-DAILY-SL-20171108.csv>

str(xdf)
## 'data.frame': 272448 obs. of  8 variables:
##  $ Interval                : chr  "11/08/2017 00:05:00" "11/08/2017 00:05:00" "11/08/2017 00:05:00" "11/08/2017 00:05:00" ...
##  $ GMT.Interval            : chr  "11/08/2017 06:05:00" "11/08/2017 06:05:00" "11/08/2017 06:05:00" "11/08/2017 06:05:00" ...
##  $ Settlement.Location.Name: chr  "AEC" "AECC_CSWS" "AECC_ELKINS" "AECC_FITZHUGH" ...
##  $ PNODE.Name              : chr  "SOUC" "CSWS_AECC_LA" "CSWSELKINSUNELKINS_RA" "CSWSFITZHUGHPLT1" ...
##  $ LMP                     : num  19 19 18.9 19.4 18.6 ...
##  $ MLC                     : num  0.1562 0.1086 0.0215 0.465 -0.3251 ...
##  $ MCC                     : num  0 0 0 0 0 0 0 0 0 0 ...
##  $ MEC                     : num  18.9 18.9 18.9 18.9 18.9 ...

It shld be a straightforward process to figure out the patterns for the other categories.


来源: stackexchange

问:
Android - EditText to StringArray stored in xml
Ive been attempting to work out how to take the text from an edittext box and move it into a string array located in strings.xml.

Basically its a user form which the user fills in, onClick it adds the information to the database and is then viewable in a listview. The listview and everything works fine but i cant work out to put in information using edittext boxes.

Any hints or techniques would be very much appreciated.

Thanks

答:
I could be wrong (someone please correct me if I am), but I don't believe strings.xml is editable at runtime. Rather, it's a set of predefined resources that your app has access to, and it cannot be modified by the program--only read.

If you're looking to make this information available to your app for subsequent uses, you should look at using SharedPreferences: http://developer.android.com/guide/topics/data/data-storage.html#pref

ContentLicense: CC BY-SA 2.5


问:
C# intersect a line bettween 2 Vector3 point on a plane
I have a line going bettween two Vector3 points and I want to find when the line is intersected at a height along the Z axis.

I am trying to write a function to calculate the intersection point.

```<code>void Main()
{
    Vector3 A = new Vector3(2.0f,  2.0f, 2.0f);
    Vector3 B = new Vector3(7.0f, 10.0f, 6.0f);
    float Z = 3.0f;

    Vector3 C = getIntersectingPoint(A, B, Z);
    //C should be X=3.25, Y=4.0, Z=3.0
}
</code>```

But trying to figure out how to do the math to handle possible negative numbers correctly is really starting to confuse me.

This is what I have and the moment, but this isn't correct.

```<code>public static Vector3 getIntersectingPoint(Vector3 A, Vector3 B, float Z)
{
    // Assume z is bettween A and B and we don't need to validate
    // Get ratio of triangle hight, height Z divided by (Za to Zb)
    ("absolute value: " + Math.Abs(A.Z-B.Z)).Dump();
    ("z offset: " + (Math.Abs(Z-B.Z)<Math.Abs(A.Z-Z)?Math.Abs(Z-B.Z):Math.Abs(A.Z-Z))).Dump();
    float ratio = (Math.Abs(Z-B.Z)<Math.Abs(A.Z-Z)?Math.Abs(Z-B.Z):Math.Abs(A.Z-Z))/Math.Abs(A.Z-B.Z);
    ("ratio: " + ratio.ToString()).Dump();
    float difX = ratio*Math.Abs(A.X-B.X);//this still needs to be added to or taken from the zero point offset
    ("difX: " + difX.ToString()).Dump();
    float difY = ratio*Math.Abs(A.Y-B.Y);//this still needs to be added to or taken from the zero point offset
    ("difY: " + difY.ToString()).Dump();

    float X = difX + (A.X<B.X?A.X:B.X);
    ("X: " + X).Dump();
    float Y = difY + (A.Y<B.Y?A.Y:B.Y);
    ("Y: " + Y).Dump();
    return new Vector3(X,Y,Z);
}
</code>```

Does anyone know if there are any Math libraries that will already do this or examples that show how to do this that I can follow?

答:
You have the starting (2.0f) and ending (6.0f) Z coordinates. The Z distance between the two points is 4.0f. You want to know the X and Y coordinates at the point where Z is 3.0f.

Remember that Z changes linearly along the segment. The segment is 4 units long, The point you're interested in is 1 unit from the start, or 1/4 of the length of the segment.

The X distance of the entire segment is 7.0 - 2.0, or 5 units. 1/4 of 5 is 1.25, so the X coordinate at the intersection is 3.25.

The Y distance of the entire segment is 8. 1/4 of 8 is 2. So the Y coordinate of the intersection point is 6.0.

The intersection point is (3.25f, 6.0f, 3.0f).

How to compute:

```<code>// start is the starting point
// end is the ending point
// target is the point you're looking for.
// It's pre-filled with the Z coordinate.
zDist = Math.Abs(end.z - start.z);
zDiff = Math.Abs(target.z - start.z);
ratio = zDiff / zDist;

xDist = Math.Abs(end.x - start.x);
xDiff = xDist * ratio;
xSign = (start.x < end.x) ? 1 : -1;
target.x = start.x + (xDiff * xSign);

yDist = Math.Abs(end.y - start.y);
yDiff = yDist * ratio;
ySign = (start.y < end.y) ? 1 : -1;
target.y = start.y + (yDiff * ySign);
</code>```

Come to think of it, the whole sign thing shouldn't be necessary. Consider this, when end.x = 10 and start.x = 18:

```<code>xDist = end.x - start.x;      // xDist = -8
xDiff = xDist * ratio;        // xDiff = -2
target.x = start.x + xDiff;   // target.x = 18 + (-2) = 16
</code>```

Yeah, no need for sign silliness.

Also no need for the calls to Math.Abs when computing the ratio. We know that zDist and zDiff will both have the same sign, so ratio will always be positive.

ContentLicense: CC BY-SA 3.0

Body:
I have a line going bettween two Vector3 points and I want to find when the line is intersected at a height along the Z axis.

I am trying to write a function to calculate the intersection point.

void Main()
{
    Vector3 A = new Vector3(2.0f,  2.0f, 2.0f);
    Vector3 B = new Vector3(7.0f, 10.0f, 6.0f);
    float Z = 3.0f;

    Vector3 C = getIntersectingPoint(A, B, Z);
    //C should be X=3.25, Y=4.0, Z=3.0
}

But trying to figure out how to do the math to handle possible negative numbers correctly is really starting to confuse me.

This is what I have and the moment, but this isn't correct.

public static Vector3 getIntersectingPoint(Vector3 A, Vector3 B, float Z)
{
    // Assume z is bettween A and B and we don't need to validate
    // Get ratio of triangle hight, height Z divided by (Za to Zb)
    ("absolute value: " + Math.Abs(A.Z-B.Z)).Dump();
    ("z offset: " + (Math.Abs(Z-B.Z)<Math.Abs(A.Z-Z)?Math.Abs(Z-B.Z):Math.Abs(A.Z-Z))).Dump();
    float ratio = (Math.Abs(Z-B.Z)<Math.Abs(A.Z-Z)?Math.Abs(Z-B.Z):Math.Abs(A.Z-Z))/Math.Abs(A.Z-B.Z);
    ("ratio: " + ratio.ToString()).Dump();
    float difX = ratio*Math.Abs(A.X-B.X);//this still needs to be added to or taken from the zero point offset
    ("difX: " + difX.ToString()).Dump();
    float difY = ratio*Math.Abs(A.Y-B.Y);//this still needs to be added to or taken from the zero point offset
    ("difY: " + difY.ToString()).Dump();

    float X = difX + (A.X<B.X?A.X:B.X);
    ("X: " + X).Dump();
    float Y = difY + (A.Y<B.Y?A.Y:B.Y);
    ("Y: " + Y).Dump();
    return new Vector3(X,Y,Z);
}

Does anyone know if there are any Math libraries that will already do this or examples that show how to do this that I can follow?

Body:
You have the starting (2.0f) and ending (6.0f) Z coordinates. The Z distance between the two points is 4.0f. You want to know the X and Y coordinates at the point where Z is 3.0f.

Remember that Z changes linearly along the segment. The segment is 4 units long, The point you're interested in is 1 unit from the start, or 1/4 of the length of the segment.

The X distance of the entire segment is 7.0 - 2.0, or 5 units. 1/4 of 5 is 1.25, so the X coordinate at the intersection is 3.25.

The Y distance of the entire segment is 8. 1/4 of 8 is 2. So the Y coordinate of the intersection point is 6.0.

The intersection point is (3.25f, 6.0f, 3.0f).

How to compute:

// start is the starting point
// end is the ending point
// target is the point you're looking for.
// It's pre-filled with the Z coordinate.
zDist = Math.Abs(end.z - start.z);
zDiff = Math.Abs(target.z - start.z);
ratio = zDiff / zDist;

xDist = Math.Abs(end.x - start.x);
xDiff = xDist * ratio;
xSign = (start.x < end.x) ? 1 : -1;
target.x = start.x + (xDiff * xSign);

yDist = Math.Abs(end.y - start.y);
yDiff = yDist * ratio;
ySign = (start.y < end.y) ? 1 : -1;
target.y = start.y + (yDiff * ySign);

Come to think of it, the whole sign thing shouldn't be necessary. Consider this, when end.x = 10 and start.x = 18:

xDist = end.x - start.x;      // xDist = -8
xDiff = xDist * ratio;        // xDiff = -2
target.x = start.x + xDiff;   // target.x = 18 + (-2) = 16

Yeah, no need for sign silliness.

Also no need for the calls to Math.Abs when computing the ratio. We know that zDist and zDiff will both have the same sign, so ratio will always be positive.


问:
Run time initialisation of peewee database for different database backends
I'm trying to write a module that is (somewhat) database independent. I want to define my peewee models and then connect to the database at runtime using the init method of the database object.

When I pass a Sqlite connection string this works as expected, e.g.

```<code>>>> app.db.init('sqlite://mydb.sqlite')
</code>```

Connects to the database and everything works as expected. But when I try the same with a postgres connection string I get an error;

```<code>>>> app.db.init('postgresql://username:password@localhost/mydb')
...
peewee.OperationalError: FATAL:  database "postgresql://username:password@localhost/mydb" does not exist
</code>```

I can get the init method to connect if I use separate parameters;

```<code>>>> app.db.init('mydb', username='username', password='password')
</code>```

But this doesn't translate well between different database backends.

Can anyone point me in the right direction of getting init to work with connection URIs?

答:
I think I've worked out a way to do this. It's a bit clunky so if anyone has a better suggestion I'm all ears. I'm creating a connect object and then passing it's attributes to the db.init. Like this

```<code>>>> from playhouse.db_url import connect
>>> import models
>>> db = connect('postgresql://username:password@localhost/mydb')
>>> models.db.init(db.database, **db.connect_kwargs)
</code>```

This seems to work with any valid Peewee backend.

Body:
I'm trying to write a module that is (somewhat) database independent. I want to define my peewee models and then connect to the database at runtime using the init method of the database object.

When I pass a Sqlite connection string this works as expected, e.g.

>>> app.db.init('sqlite://mydb.sqlite')

Connects to the database and everything works as expected. But when I try the same with a postgres connection string I get an error;

>>> app.db.init('postgresql://username:password@localhost/mydb')
...
peewee.OperationalError: FATAL:  database "postgresql://username:password@localhost/mydb" does not exist

I can get the init method to connect if I use separate parameters;

>>> app.db.init('mydb', username='username', password='password')

But this doesn't translate well between different database backends.

Can anyone point me in the right direction of getting init to work with connection URIs?

Body:
I think I've worked out a way to do this. It's a bit clunky so if anyone has a better suggestion I'm all ears. I'm creating a connect object and then passing it's attributes to the db.init. Like this

>>> from playhouse.db_url import connect
>>> import models
>>> db = connect('postgresql://username:password@localhost/mydb')
>>> models.db.init(db.database, **db.connect_kwargs)

This seems to work with any valid Peewee backend.


问:
The keyboard pushes a div up & out of the screen
I'm using Ionic 3 to make a website which will be part of another native app in a webview so I don't user cordova or any native plugins.
I have a form with an embedded Google Map View above the elements and here is my HTML :

```<code><div  style="height: 40%; width: 100%">
  <div id="map_loader" *ngIf="showMapLoader">
    <div class="sk-wave">
      <div class="sk-rect sk-rect1"></div>
      <div class="sk-rect sk-rect2"></div>
      <div class="sk-rect sk-rect3"></div>
      <div class="sk-rect sk-rect4"></div>
      <div class="sk-rect sk-rect5"></div>
    </div>
  </div>
  <div #mapCanvas style="width: 100%; height: 100%;"></div>
</div>
<form (ngSubmit)="submit()" padding>
  <ion-list>
......
......
.....
  </ion-list>
</form>
</code>```

and here is my CSS :

```<code>  #map_loader {
    margin:auto;
    background-color: rgba(0, 0, 0, 0.5);
    width: 100%;
    height: 100%;
    z-index: 1000;
    position: absolute;
  }

  .scroll-content {
    top: 38%;
    position: absolute;
    margin-top: 32px;
  }
</code>```

Now once the user open the website on his phone and start filling the form the keyboard shifts the map out of the screen ( Up ) and it stays that way and a blank empty space shows bellow the form.

Am I doing it right? Is that happening because of my CSS? and what is the best way to make a div takes a specific percentage of the screen height? I tried ion-grid but it seems that it can't help me for this case.

答:
it's bug in ionic, once you focus on any input the keyboard will show up and will add padding-bottom for the scroll-content class to lift the for above the keyboard and it doesn't remove the padding-bottom after you close the keyboard.
I tried to check if I have any JS event on the mobile keyboard but we don't so my work around is to set a fixed padding-bottom for the scroll-content class to prevent changing it on the runtime.

```<code>.scroll-content {
    padding-bottom: 0 !important;
 }
</code>```

Body:
I'm using Ionic 3 to make a website which will be part of another native app in a webview so I don't user cordova or any native plugins.
I have a form with an embedded Google Map View above the elements and here is my HTML :

<form (ngSubmit)="submit()" padding>
  <ion-list>
......
......
.....
  </ion-list>
</form>

and here is my CSS :

  #map_loader {
    margin:auto;
    background-color: rgba(0, 0, 0, 0.5);
    width: 100%;
    height: 100%;
    z-index: 1000;
    position: absolute;
  }

  .scroll-content {
    top: 38%;
    position: absolute;
    margin-top: 32px;
  }

Now once the user open the website on his phone and start filling the form the keyboard shifts the map out of the screen ( Up ) and it stays that way and a blank empty space shows bellow the form.

Am I doing it right? Is that happening because of my CSS? and what is the best way to make a div takes a specific percentage of the screen height? I tried ion-grid but it seems that it can't help me for this case.

Body:
it's bug in ionic, once you focus on any input the keyboard will show up and will add padding-bottom for the scroll-content class to lift the for above the keyboard and it doesn't remove the padding-bottom after you close the keyboard.
I tried to check if I have any JS event on the mobile keyboard but we don't so my work around is to set a fixed padding-bottom for the scroll-content class to prevent changing it on the runtime.

.scroll-content {
    padding-bottom: 0 !important;
 }


问:
How to create an empty folder while creating a zip in gradle
i want to build the war file and include an empty folders like "classes" and "META-INF". I have the following code:

```<code>task buildWar(type: Zip){
    archiveName = 'myproject.war'
    includeEmptyDirs = true
    destinationDir = file("$targetDir/project")

    from("$root/grab/lib"){
        include "*.jar"
        into "WEB-INF/lib"
    }

}
</code>```

I need to create "classes" and "META-INF". How i can do it inside buildWar task?

答:
I use the following script to create a fat JAR, probably you could modify it to create WAR file:

```<code>//create a single Jar with all dependencies
task fatJar(type: Jar) {
  manifest {
    attributes 'Implementation-Title': 'Project Name',
            'Implementation-Version': version,
            'Main-Class': 'org.foo.Bar'
  }
  baseName = project.name + '-all'
  from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
  with jar
}
</code>```

The manifest part above will generate your META-INF subfolder (where the manifest sits).

The classes folder will be auto-created by Gradle, if the project has Java files.

Body:
i want to build the war file and include an empty folders like "classes" and "META-INF". I have the following code:

task buildWar(type: Zip){
    archiveName = 'myproject.war'
    includeEmptyDirs = true
    destinationDir = file("$targetDir/project")

    from("$root/grab/lib"){
        include "*.jar"
        into "WEB-INF/lib"
    }

}

I need to create "classes" and "META-INF". How i can do it inside buildWar task?

Body:
I use the following script to create a fat JAR, probably you could modify it to create WAR file:

//create a single Jar with all dependencies
task fatJar(type: Jar) {
  manifest {
    attributes 'Implementation-Title': 'Project Name',
            'Implementation-Version': version,
            'Main-Class': 'org.foo.Bar'
  }
  baseName = project.name + '-all'
  from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
  with jar
}

The manifest part above will generate your META-INF subfolder (where the manifest sits).

The classes folder will be auto-created by Gradle, if the project has Java files.


问:
Characters counting only in one textarea
I have many inputs and one textarea in my page. I want to count the characters from all
these inputs/textarea.

HTML:

```<code><textarea name="texto_envio" class="form-control txtArea" maxlength="160"></textarea>
<input type="text"maxlength=3" class="form-control txtArea" />
<input type="text"maxlength=3" class="form-control txtArea" />
<span class="caracteres">160</span> restantes<br>
</code>```

JS:

```<code>$(document).on("input keyup", ".txtArea", function () {
    var limite = 160;
    var caracteresDigitados = $(this).val().length;
    var caracteresRestantes = limite - caracteresDigitados;
    $(".caracteres").text(caracteresRestantes);
});
</code>```

Like...if I write "abc" in textarea and if I also write "abc" in both inputs, it will show "151 restantes".

I tried this code above but it only count the element that I am writing in. I write "abc" in textarea then span shows me "157 restantes". With "abc" written in textarea, I also write "abc" in one of the inputs. But the span shows me "157 restantes".

Span is reseting when I write in the other element.

What can I do to make it count every element (textarea and inputs)?

答:
You can enumerate all characters in .txtArea with .each function:

$('.txtArea').on("keyup", function() {
  var limite = 160;
  $('.txtArea').each(function() {
    limite -= $(this).val().length
    $(".caracteres").text(limite);
  })
});```
<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>
<textarea name="texto_envio" class="form-control txtArea" maxlength="160"></textarea>
<input type="text" maxlength=3 " class="form-control txtArea " />
<input type="text "maxlength=3" class="form-control txtArea" />
<span class="caracteres">160</span> restantes<br></code>```

Body:
I have many inputs and one textarea in my page. I want to count the characters from all
these inputs/textarea.

HTML:

<textarea name="texto_envio" class="form-control txtArea" maxlength="160"></textarea>
<input type="text"maxlength=3" class="form-control txtArea" />
<input type="text"maxlength=3" class="form-control txtArea" />
160 restantes

JS:

$(document).on("input keyup", ".txtArea", function () {
    var limite = 160;
    var caracteresDigitados = $(this).val().length;
    var caracteresRestantes = limite - caracteresDigitados;
    $(".caracteres").text(caracteresRestantes);
});

Like...if I write "abc" in textarea and if I also write "abc" in both inputs, it will show "151 restantes".

I tried this code above but it only count the element that I am writing in. I write "abc" in textarea then span shows me "157 restantes". With "abc" written in textarea, I also write "abc" in one of the inputs. But the span shows me "157 restantes".

Span is reseting when I write in the other element.

What can I do to make it count every element (textarea and inputs)?

Body:
You can enumerate all characters in .txtArea with .each function:

$('.txtArea').on("keyup", function() {
  var limite = 160;
  $('.txtArea').each(function() {
    limite -= $(this).val().length
    $(".caracteres").text(limite);
  })
});

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<textarea name="texto_envio" class="form-control txtArea" maxlength="160"></textarea>
<input type="text" maxlength=3 " class="form-control txtArea " />
<input type="text "maxlength=3" class="form-control txtArea" />
<span class="caracteres">160</span> restantes<br>


问:
Allow dashes on a field using jQuery validate plugin
I tried to add a rule for a specific field that only accepts letters, numbers, dashes and underscores but dashes is not included into the rule. Question is, how can I add the dashes to the characters using the below format.</p>

```<code>jQuery.validator.addMethod("custom-rule", function(value, element) {
        return this.optional(element) || /^\w+$/i.test(value);
    }, "Letters, numbers, dashes and underscores only please");
</code>```

答:
Add dashes along with word character in the regex using a character class.</p>

```<code>jQuery.validator.addMethod("custom-rule", function(value, element) {
    return this.optional(element) || /^[\w-]+$/i.test(value);
    // here add dash in character class-^^^^-----
}, "Letters, numbers, dashes and underscores only please");
</code>```

Body:
I tried to add a rule for a specific field that only accepts letters, numbers, dashes and underscores but dashes is not included into the rule. Question is, how can I add the dashes to the characters using the below format.

jQuery.validator.addMethod("custom-rule", function(value, element) {
        return this.optional(element) || /^\w+$/i.test(value);
    }, "Letters, numbers, dashes and underscores only please");

Body:
Add dashes along with word character in the regex using a character class.

jQuery.validator.addMethod("custom-rule", function(value, element) {
    return this.optional(element) || /^[\w-]+$/i.test(value);
    // here add dash in character class-^^^^-----
}, "Letters, numbers, dashes and underscores only please");


答:
For Count all char from all input/textarea fields.

HTML

```<code><textarea name="texto_envio"
class="form-control txtArea" maxlength="160"></textarea>
<input type="text" maxlength="3" class="form-control txtArea" />
<input type="text" maxlength="3" class="form-control txtArea" />
<span class="caracteres">160</span> restantes<br>
</code>```

Script

```<code>$('.txtArea').on("keyup",function () {
    var limite = 160;
    var caracteresDigitados =0;
    $('.txtArea').each(function(){
      caracteresDigitados += $(this).val().length;
    });
    $(".caracteres").text(limite - caracteresDigitados);
});
</code>```

Title: Characters counting only in one textarea

Body:
For Count all char from all input/textarea fields.

HTML

<textarea name="texto_envio"
class="form-control txtArea" maxlength="160"></textarea>
<input type="text" maxlength="3" class="form-control txtArea" />
<input type="text" maxlength="3" class="form-control txtArea" />
<span class="caracteres">160</span> restantes<br>

Script

$('.txtArea').on("keyup",function () {
    var limite = 160;
    var caracteresDigitados =0;
    $('.txtArea').each(function(){
      caracteresDigitados += $(this).val().length;
    });
    $(".caracteres").text(limite - caracteresDigitados);
});


问:
Error codes in Nearby Connections 2.0
I've been experimenting with the new Android Nearby Connections v2.0 API. Most of my devices can now talk to each other most of the time, but I also get a lot of error codes back when trying to connect. Checking status.getStatusCode() inside my program, I can see the following return codes:

STATUS_ALREADY_CONNECTED_TO_ENDPOINT (8003)

STATUS_BLUETOOTH_ERROR (8007)

STATUS_ENDPOINT_IO_ERROR (8012)

STATUS_ERROR (13)

I'm having a hard time making sense of these. The first error code seems self-explanatory, except that I see it in cases when I haven't hit the onConnectionResult callback with a "SUCCESS" return code on either side of the alleged connection. My current code is full of trace statements, and I'd see logging entries if those callbacks had been reached. So maybe the devices are connected at some lower level, but if so, the higher-level code doesn't always hear about it.

I'm guessing that STATUS_BLUETOOTH_ERROR indicates a Bluetooth error on the side that logs it, while STATUS_ENDPOINT_IO_ERROR indicates an error (probably involving Bluetooth) on the other end? Is it possible to get any more details?
The STATUS_ERROR (13) status that I see once in a while sounds like the sort of error code a programmer would use for those "WTF, we should never get here" moments, but without access to the source code, I can only guess.

Note that I see these errors between devices that talk to each other beautifully at other times, using the same code. Sometimes if the code retries enough times, it eventually gets a stable connection. Sometimes it connects and gets instantly disconnected from the other end. Sometimes I just get an endless stream of repeated error messages (STATUS_BLUETOOTH_ERROR and/or STATUS_ENDPOINT_IO_ERROR).

I'm using Nearby Connections with the connection strategy P2P_CLUSTER. These problems seem to happen most often when both sides do both advertising and discovery. However, I wrote two smaller programs that specialize in either advertising or discovery, and they sometimes get these errors too (but less often).

In the trace messages, I've also noticed lots of warning messages from Nearby Connections that look like this:

```<code>09-04 22:54:40.070 3866-3924/? W/NearbyConnections: Cannot deserialize BluetoothDeviceName: expecting min 16 raw bytes, got 6
</code>```

I'm guessing that this is because Nearby Connections uses its own short tokens (like ZGbx) instead of the device Bluetooth name? I'm not at all sure about that, though. And anyway, if these are Nearby Connections' own special tokens, then why would it be issuing warning messages about it?

答:
I just want to add that it may be necessary to have a short client name string when calling the API.

E.g., Nearby.Connections.requestConnection(googleApiClient, shortNameHere,....)

I had been generating my own client name with UUID.randomUUID().toString() and that seemed to cause the STATUS_BLUETOOTH_ERROR.
All I did was change the code sample to use a UUID name and to use P2P_CLUSTER and I got that error.

This was the solution for me regarding the STATUS_BLUETOOTH_ERROR.

Title: Error codes in Nearby Connections 2.0

Body:
I've been experimenting with the new Android Nearby Connections v2.0 API. Most of my devices can now talk to each other most of the time, but I also get a lot of error codes back when trying to connect. Checking status.getStatusCode() inside my program, I can see the following return codes:

STATUS_ALREADY_CONNECTED_TO_ENDPOINT (8003)

STATUS_BLUETOOTH_ERROR (8007)

STATUS_ENDPOINT_IO_ERROR (8012)

STATUS_ERROR (13)

I'm having a hard time making sense of these. The first error code seems self-explanatory, except that I see it in cases when I haven't hit the onConnectionResult callback with a "SUCCESS" return code on either side of the alleged connection. My current code is full of trace statements, and I'd see logging entries if those callbacks had been reached. So maybe the devices are connected at some lower level, but if so, the higher-level code doesn't always hear about it.

I'm guessing that STATUS_BLUETOOTH_ERROR indicates a Bluetooth error on the side that logs it, while STATUS_ENDPOINT_IO_ERROR indicates an error (probably involving Bluetooth) on the other end? Is it possible to get any more details?
The STATUS_ERROR (13) status that I see once in a while sounds like the sort of error code a programmer would use for those "WTF, we should never get here" moments, but without access to the source code, I can only guess.

Note that I see these errors between devices that talk to each other beautifully at other times, using the same code. Sometimes if the code retries enough times, it eventually gets a stable connection. Sometimes it connects and gets instantly disconnected from the other end. Sometimes I just get an endless stream of repeated error messages (STATUS_BLUETOOTH_ERROR and/or STATUS_ENDPOINT_IO_ERROR).

I'm using Nearby Connections with the connection strategy P2P_CLUSTER. These problems seem to happen most often when both sides do both advertising and discovery. However, I wrote two smaller programs that specialize in either advertising or discovery, and they sometimes get these errors too (but less often).

In the trace messages, I've also noticed lots of warning messages from Nearby Connections that look like this:

09-04 22:54:40.070 3866-3924/? W/NearbyConnections: Cannot deserialize BluetoothDeviceName: expecting min 16 raw bytes, got 6

I'm guessing that this is because Nearby Connections uses its own short tokens (like ZGbx) instead of the device Bluetooth name? I'm not at all sure about that, though. And anyway, if these are Nearby Connections' own special tokens, then why would it be issuing warning messages about it?


问:
Concatenate different values from a specific column to a same line
I Have a DataTable with a lot of Rows and Columns.

Some of these Rows have the Same "OrderId", actually these rows are almost the same, but I have a specific value in the "TagList" Column that I have to put in the previous row.

Making a unique Row with all the TagList values inside the TagList Column.

I'll give a example below:

Line 1:

ID: 1

Name: John

OrderId: 1500

TagList: AG75

Line2:

ID: 2

Name: John

OrderId: 1500

TagList: BG99

I wanna do it:
Line:
ID: 1
Name: Mark
OrderId: 1500
TagList: AG75, BG99

ie: Concatenate the TagList's values when they have the same OrderId.

答:
Guys, I did it, follow below if someone got the same problem:

```<code>using (DataTable dt = new DataTable())
                {
                    adapter.Fill(dt);

                    DataView dv = new DataView(dt);
                    String strAtual = String.Empty;

                    //Percorrer o DataTable
                    foreach (DataRowView row in dv)
                    {
                        if (strAtual.Equals(row.Row["OrderId"].ToString()))
                        {
                            string strTagNumb = row["TagList"].ToString();
                            CompareDelete(strTagNumb, strAtual, dv);

                            row.Delete();
                            continue;
                        }

                        if (!string.IsNullOrEmpty(row.Row["OrderId"].ToString()))
                            strAtual = row.Row["OrderId"].ToString();
                    }

                    intTotal = dv.Count;
                    gvSchedules.DataSource = dv;
                    gvSchedules.DataBind();

                }

   private void CompareDelete(string strTagNumb, string strAtual, DataView dt)
    {
        foreach (DataRowView row in dt)
        {
            if (row.Row["OrderId"].ToString().Equals(strAtual))
            {
                row.Row["TagList"] += string.Concat("</br>", strTagNumb);
                return;
            }
        }
    }
</code>```

Thanks folks!

Body:
Guys, I did it, follow below if someone got the same problem:

using (DataTable dt = new DataTable())
                {
                    adapter.Fill(dt);

                    DataView dv = new DataView(dt);
                    String strAtual = String.Empty;

                    //Percorrer o DataTable
                    foreach (DataRowView row in dv)
                    {
                        if (strAtual.Equals(row.Row["OrderId"].ToString()))
                        {
                            string strTagNumb = row["TagList"].ToString();
                            CompareDelete(strTagNumb, strAtual, dv);

                            row.Delete();
                            continue;
                        }

                        if (!string.IsNullOrEmpty(row.Row["OrderId"].ToString()))
                            strAtual = row.Row["OrderId"].ToString();
                    }

                    intTotal = dv.Count;
                    gvSchedules.DataSource = dv;
                    gvSchedules.DataBind();

                }

   private void CompareDelete(string strTagNumb, string strAtual, DataView dt)
    {
        foreach (DataRowView row in dt)
        {
            if (row.Row["OrderId"].ToString().Equals(strAtual))
            {
                row.Row["TagList"] += string.Concat("</br>", strTagNumb);
                return;
            }
        }
    }

Thanks folks!


答:
You simply need to loop through all input elements and use length to count the number of characters entered per input.

Secondly, I would recommend to use input event instead of keyup or keydown as that input takes care of everything (even copy-paste). Below is the updated snippet:

$(document).on('input', 'textarea, input', countChar);

function countChar() {
  var len = 0;
  $('input,textarea').each(function() {
    var enteredValue = $(this).val();
    len += enteredValue.length;
    $('#charCount').text(len);
  });
}```
<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>
<textarea></textarea>
<input type="text" />
<input type="text" />
<span id='charCount'></span></code>```

Body:
You simply need to loop through all input elements and use length to count the number of characters entered per input.

Secondly, I would recommend to use input event instead of keyup or keydown as that input takes care of everything (even copy-paste). Below is the updated snippet:

$(document).on('input', 'textarea, input', countChar);

function countChar() {
  var len = 0;
  $('input,textarea').each(function() {
    var enteredValue = $(this).val();
    len += enteredValue.length;
    $('#charCount').text(len);
  });
}

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<textarea></textarea>
<input type="text" />
<input type="text" />
<span id='charCount'></span>


问:
SAS: What's the optimal way to find the sum of a column by another column?
I want to find out the best way to perform a group-by in SAS so I can perform some benchmarks. The simplest two ways I can think of is Proc SQL and Proc means. Here is the example in proc sql

    proc sql noprint; /* took 6 mins */
    create table summ as select
            id,
            sum(val)
        from
            randint
        group by
            id
        ;
    quit;

I think there are ways to make this run fast

use sasfile command to load the data into memory first

create an index on id

Are there any other options I can use? Any SAS options I should turn on to make this run as fast as possible? I am not tied to proc sql nor proc means, so if there are faster ways then I would love to know about it!!!

My set up code is as below

```<code>options macrogen;
options obs=max sortsize=max source2 FULLSTIMER;
options minoperator SASTRACE=',,,d' SASTRACELOC=SASLOG;
options compress = binary NOSTSUFFIX;
options noxwait noxsync;
options LRECL=32767;

proc fcmp outlib=work.myfunc.sample;
    function RandBetween(min, max);
        return (min + floor((1 + max - min) * rand("uniform")));
    endsub;
run;

options cmplib=work.myfunc;

data RandInt;
    do i = 1 to 250000000;
        id = RandBetween(1, 2500000);
        val = rand("uniform");
        output;
    end;
    drop i;
run;
</code>```

My SAS comparison macros are as below

```<code>%macro sasbench(dosql = N); %macro _; %mend;
    %if &dosql. = Y %then %do;
        proc sql noprint; /* took 6 mins */
            create table summ as select
                id,
                sum(val)
            from
                randint
            group by
                id
            ;
        quit;
    %end;

    proc means data=randint  sum noprint;
        var val ;
        class id;
        output out = summmeans(drop=_type_ _freq_) sum = /autoname;
    run;
%mend;

%sasbench();
/**/
/*sasfile randint load;*/
/*%sasbench();*/
/*sasfile randint close;*/

proc datasets lib=work;
    modify randint;
    INDEX CREATE id / nomiss;
run;

%sasbench();
</code>```

答:
If you assume the data is sorted then this is another solution</p>

```<code>data sum_value_over_id_v2(keep=id total);
    set a.randint(keep=id val);
    by id;
    total + val;
    if last.id then do;
        output;
        total = 0;
    end;
    drop val;
run;
</code>```

Body:
I want to find out the best way to perform a group-by in SAS so I can perform some benchmarks. The simplest two ways I can think of is Proc SQL and Proc means. Here is the example in proc sql

    proc sql noprint; /* took 6 mins */
    create table summ as select
            id,
            sum(val)
        from
            randint
        group by
            id
        ;
    quit;

I think there are ways to make this run fast

use sasfile command to load the data into memory first

create an index on id

Are there any other options I can use? Any SAS options I should turn on to make this run as fast as possible? I am not tied to proc sql nor proc means, so if there are faster ways then I would love to know about it!!!

My set up code is as below

options macrogen;
options obs=max sortsize=max source2 FULLSTIMER;
options minoperator SASTRACE=',,,d' SASTRACELOC=SASLOG;
options compress = binary NOSTSUFFIX;
options noxwait noxsync;
options LRECL=32767;

proc fcmp outlib=work.myfunc.sample;
    function RandBetween(min, max);
        return (min + floor((1 + max - min) * rand("uniform")));
    endsub;
run;

options cmplib=work.myfunc;

data RandInt;
    do i = 1 to 250000000;
        id = RandBetween(1, 2500000);
        val = rand("uniform");
        output;
    end;
    drop i;
run;

My SAS comparison macros are as below

%macro sasbench(dosql = N); %macro _; %mend;
    %if &dosql. = Y %then %do;
        proc sql noprint; /* took 6 mins */
            create table summ as select
                id,
                sum(val)
            from
                randint
            group by
                id
            ;
        quit;
    %end;

    proc means data=randint  sum noprint;
        var val ;
        class id;
        output out = summmeans(drop=_type_ _freq_) sum = /autoname;
    run;
%mend;

%sasbench();
/**/
/*sasfile randint load;*/
/*%sasbench();*/
/*sasfile randint close;*/

proc datasets lib=work;
    modify randint;
    INDEX CREATE id / nomiss;
run;

%sasbench();

Body:
If you assume the data is sorted then this is another solution

data sum_value_over_id_v2(keep=id total);
    set a.randint(keep=id val);
    by id;
    total + val;
    if last.id then do;
        output;
        total = 0;
    end;
    drop val;
run;


问:
CodeIgniter join table
This is my output // As you can see the Name is not the exact name

And I found a code to solve this problem but I'm not really sure about which coding should I have to use. Can you please help?

This is a set of function coding:

```<code><?php

$rn= "0001123456";
$rn2= "A123456";
$dob = "1986-10-25";
$dreg = "1986-10-26";

echo "<br/>".$rn;
echo "<br/>".numberToAlpha($rn);
echo "<br/>".alphaToNumber($rn2);
echo "<br/>cur_age : ".calculateCurrentAge($dob);
echo "<br/>reg_age : ".calculateRegisterAge($dob, $dreg);
/*** End Contoh Penggunaan ***/

function numberToAlpha($rn)
{
  if (strcmp('0000', substr($rn,0,4)) == 0) {
    $rn = 'A'.substr($rn, 4, 6);
  }else{
    $rn = 'B'.substr($rn, 4, 6);
  }

  return $rn;

}

function alphaToNumber($rn)
{
  if (strcmp('A', substr($rn,0,1)) == 0) {
    $rn = '0000'.substr($rn, 1, 6);
  }else{
    $rn = '0001'.substr($rn, 1, 6);
  }

  return $rn;
}

function calculateCurrentAge($dob)
{
    $from = DateTime::createFromFormat('Y-m-d', $dob);

    $to = new DateTime('today +1 day');

    $age = $from->diff($to);

    return $age->format('%y years, %m months, %d days');
}

function calculateRegisterAge($dob, $dreg)
{
    $from = DateTime::createFromFormat('Y-m-d', $dob);
    $to = DateTime::createFromFormat('Y-m-d', $dreg);
    $to = $to->modify('+1 day');

    $age = $from->diff($to);

    return $age->format('%y years, %m months, %d days');
}
</code>```

Can you tell me if I want to change the Name to a proper Name which coding should I use and where to add these coding?

This is my controllers 'Search.php'：

```<code><?php

class Search extends CI_Controller {

    public function __construct()
    {
        parent::__construct();

        $this->load->helper('form');

        $this->load->model('Search_model');
    }

    public function index()
    {
        $this->load->view('search_form');
    }

    public function execute_search()
    {
        // Retrieve the posted search term.
        $search_term = $this->input->post('search');

        // Use a model to retrieve the results.
        $data['results'] = $this->Search_model->get_results($search_term);

        // Pass the results to the view.
        $this->load->view('search_results',$data);
    }
}
</code>```

This is model 'Search_model.php':

```<code><?php

class Search_model extends CI_Model {

    public function get_results($search_term='default')
    {
        // Use the Active Record class for safer queries.
        $this->db->select('rn,nama,tarikhlahir,jantina,agama,bangsa');
        $this->db->from('pesakit');
        $this->db->like('rn',$search_term);
        $this->db->limit(100);

        // Execute the query.
        $query = $this->db->get();

        // Return the results.
        return $query->result_array();
    }
}
</code>```

This is views for search 'search_form.php':

```<code><?php
    echo form_open('search/execute_search');

    echo form_input(array('name'=>'search'));

    echo form_submit('search_submit','Submit');

?>
</code>```

This is results views 'search_results.php'：

```<code><div>
    <?php
        // List up all results.
        foreach ($results as $val)
        {
            echo 'RN : '; echo $val['rn']; echo "<br/>";
            echo 'Name : '; echo $val['nama']; echo "<br/>";
            echo 'Date.of.Birth : '; echo $val['tarikhlahir']; echo "<br/>";
            echo 'Gender : '; echo $val['jantina']; echo "<br/>";
            echo 'Race : '; echo $val['bangsa']; echo "<br/>";
            echo 'Religion : '; echo $val['agama'];
        }
    ?>
</div>
</code>```

答:
You might echo it in the view page.</p>

```<code><div>
    <?php
        // List up all results.
        foreach ($results as $val)
        {
            echo $val['jantina']; echo ',';
            echo $val['bangsa']; echo ',';
            echo $val['agama'];
        }
    ?>
</div>
</code>```

ContentLicense: CC BY-SA 4.0

Title: CodeIgniter join table

Body:
This is my output // As you can see the Name is not the exact name

And I found a code to solve this problem but I'm not really sure about which coding should I have to use. Can you please help?

This is a set of function coding:

<?php

$rn= "0001123456";
$rn2= "A123456";
$dob = "1986-10-25";
$dreg = "1986-10-26";

echo "
".$rn;
echo "
".numberToAlpha($rn);
echo "
".alphaToNumber($rn2);
echo "
cur_age : ".calculateCurrentAge($dob);
echo "
reg_age : ".calculateRegisterAge($dob, $dreg);
/*** End Contoh Penggunaan ***/

function numberToAlpha($rn)
{
  if (strcmp('0000', substr($rn,0,4)) == 0) {
    $rn = 'A'.substr($rn, 4, 6);
  }else{
    $rn = 'B'.substr($rn, 4, 6);
  }

  return $rn;

}

function alphaToNumber($rn)
{
  if (strcmp('A', substr($rn,0,1)) == 0) {
    $rn = '0000'.substr($rn, 1, 6);
  }else{
    $rn = '0001'.substr($rn, 1, 6);
  }

  return $rn;
}

function calculateCurrentAge($dob)
{
    $from = DateTime::createFromFormat('Y-m-d', $dob);

    $to = new DateTime('today +1 day');

    $age = $from->diff($to);

    return $age->format('%y years, %m months, %d days');
}

function calculateRegisterAge($dob, $dreg)
{
    $from = DateTime::createFromFormat('Y-m-d', $dob);
    $to = DateTime::createFromFormat('Y-m-d', $dreg);
    $to = $to->modify('+1 day');

    $age = $from->diff($to);

    return $age->format('%y years, %m months, %d days');
}

Can you tell me if I want to change the Name to a proper Name which coding should I use and where to add these coding?

This is my controllers 'Search.php'：

<?php

class Search extends CI_Controller {

    public function __construct()
    {
        parent::__construct();

        $this->load->helper('form');

        $this->load->model('Search_model');
    }

    public function index()
    {
        $this->load->view('search_form');
    }

    public function execute_search()
    {
        // Retrieve the posted search term.
        $search_term = $this->input->post('search');

        // Use a model to retrieve the results.
        $data['results'] = $this->Search_model->get_results($search_term);

        // Pass the results to the view.
        $this->load->view('search_results',$data);
    }
}

This is model 'Search_model.php':

<?php

class Search_model extends CI_Model {

    public function get_results($search_term='default')
    {
        // Use the Active Record class for safer queries.
        $this->db->select('rn,nama,tarikhlahir,jantina,agama,bangsa');
        $this->db->from('pesakit');
        $this->db->like('rn',$search_term);
        $this->db->limit(100);

        // Execute the query.
        $query = $this->db->get();

        // Return the results.
        return $query->result_array();
    }
}

This is views for search 'search_form.php':

<?php
    echo form_open('search/execute_search');

    echo form_input(array('name'=>'search'));

    echo form_submit('search_submit','Submit');

?>

This is results views 'search_results.php'：

    <?php
        // List up all results.
        foreach ($results as $val)
        {
            echo 'RN : '; echo $val['rn']; echo "
";
            echo 'Name : '; echo $val['nama']; echo "
";
            echo 'Date.of.Birth : '; echo $val['tarikhlahir']; echo "
";
            echo 'Gender : '; echo $val['jantina']; echo "
";
            echo 'Race : '; echo $val['bangsa']; echo "
";
            echo 'Religion : '; echo $val['agama'];
        }
    ?>

Body:
You might echo it in the view page.

<div>
    <?php
        // List up all results.
        foreach ($results as $val)
        {
            echo $val['jantina']; echo ',';
            echo $val['bangsa']; echo ',';
            echo $val['agama'];
        }
    ?>
</div>


问:
WPF DataGridTextColumn doesn't scroll properly on long multiline text
I have WPF datagrid databinded to an object List<>. The issue is one of the DataGridTextColumn cells have a long multi-line text and the vertical scroll bar doesn't let me scroll through the content of the specific cell instead I can only scroll to the next cell. Have anyone encountered this issue? The code look something like below:

```<code><DataGridTextColumn Header="Value" Binding="{Binding Value}" Width="*">
      <DataGridTextColumn.ElementStyle>
          <Style TargetType="TextBlock">
             <Setter Property="TextWrapping" Value="Wrap" />
          </Style>
      </DataGridTextColumn.ElementStyle>
      <DataGridTextColumn.EditingElementStyle>
          <Style TargetType="TextBox">
            <Setter Property="TextWrapping" Value="Wrap" />
            <Setter Property="AcceptsReturn" Value="true" />
          </Style>
      </DataGridTextColumn.EditingElementStyle>
</DataGridTextColumn>
</code>```

答:
I got my workaround which is to use dataTemplate. The dataTemplate then contain the TextBox control with the attribute ScrollViewer.CanContentScroll and ScrollViewer.VerticalScrollBarVisibility set.</p>

```<code><DataGridTemplateColumn Header="Value" Width="*" IsReadOnly="True">
     <DataGridTemplateColumn.CellTemplate>
         <DataTemplate>
            <TextBox Text="{Binding Value}" AcceptsReturn="True" TextWrapping="Wrap" Height="150" ScrollViewer.VerticalScrollBarVisibility="Auto" ScrollViewer.CanContentScroll="True"></TextBox>
         </DataTemplate>
    </DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</code>```

Body:
I have WPF datagrid databinded to an object List<>. The issue is one of the DataGridTextColumn cells have a long multi-line text and the vertical scroll bar doesn't let me scroll through the content of the specific cell instead I can only scroll to the next cell. Have anyone encountered this issue? The code look something like below:

<DataGridTextColumn Header="Value" Binding="{Binding Value}" Width="*">
      <DataGridTextColumn.ElementStyle>

      </DataGridTextColumn.ElementStyle>
      <DataGridTextColumn.EditingElementStyle>

      </DataGridTextColumn.EditingElementStyle>
</DataGridTextColumn>

Body:
I got my workaround which is to use dataTemplate. The dataTemplate then contain the TextBox control with the attribute ScrollViewer.CanContentScroll and ScrollViewer.VerticalScrollBarVisibility set.

<DataGridTemplateColumn Header="Value" Width="*" IsReadOnly="True">
     <DataGridTemplateColumn.CellTemplate>
         <DataTemplate>
            <TextBox Text="{Binding Value}" AcceptsReturn="True" TextWrapping="Wrap" Height="150" ScrollViewer.VerticalScrollBarVisibility="Auto" ScrollViewer.CanContentScroll="True"></TextBox>
         </DataTemplate>
    </DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>


问:
Manually resending an AWS EC2 spot instance request after its termination, with data persistance
In Amazon Web Services \ EC2, I have a spot instance request that was run and manually terminated (by me). Now, I would like to run the same instance again - without needing to go through the process of creating a new instance (I mean, the process where I choose the AMI, the instant type, configurations, security group, etc.). When using non-stop instances, this is easy, as I can manually terminate or start the instance as many time as I want (and my saved data is persisted between terminations). But with the spot instance, I don't see how this can be done, since after it was terminated, the spot requests page in the EC2 management console shows that the request is closed and I don't see how to resend the same request again.

I know that I can choose a spot request to be persistent, but I understand that this would automatically resend the request when it is terminated, whereas I would want to continue to have manual control over when the request is sent.

To summarize, I'd want to be able to have the following workflow:

Create a spot instance request.

Run the spot instance (when the spot price is smaller than my bidding price).

Have some data saved in the instance.

Terminate the instance (either manually or due to the bid price threshold).

Manually, at my chosen time, resend a request to run the same instance, such that when it is opened, I can still see the data from before.

Return to 2.

How can this be done?

答:
The short answer is an emphatic yes. Absolutely.

Your instance "workflow" you described is really the instance life-cycle . That life-cycle is the normal life-cycle of any well behaved app server in the cloud, even if you are relying on spot instances for your computing. You control all aspects of the instance lifecycle: launch, provisioning, scaling,and termination.

Using a modified version of this CloudFormation template for a Jenkins server
with automatic backup and recovery, I have a number of auto-scaling fleets that  do exactly what you describe (NB I use on-demand instances. But the same strategy applies for spot instances. NB2 I say fleet below, but this can a fleet of 1 instance only)

Here is the quick overview (or the long answer):

Use  CloudFormation (optional, but  recommended) to define/launch an autoscaling group and launch configuration to launch your fleet of 1 (or more) instances.  Spot instances are directly supported in auto scaling. See Launching Spot Instances in Your Auto Scaling Group

Use the auto scaling policy, and your spot bid parameters/duration, to control the time and cost that want to pay for your instances, for the computing power you need. For Jenkins, I autoscale to have 1 healthy instance in any of the AZs in my VPC. Auto-scaling policies are very flexible. For manual termination, suspend ASG Launch process.  See Suspending and Resuming Auto Scaling Processes

On instance launch, use UserData scripting, to configure your software, install backup and restore scripts, configure your instance, and load any instance data from the last backup. Use a dedicated S3 bucket to backup instance data. In my case, I archive the entire Jenkins work-space and configuration data in a zipped tar file. You would want to backup as frequently as needed for your data set.

On any auto relaunch of a new instance, the instance is configured to check S3 data back bucket, and restore the latest one.  It immediately comes in to service with all the data from last backup. As noted in step 3, you have manual backup and restore scripts, so you can login to the instance and do these operations as needed.

Using these techniques you can build an instance fleet of on-demand or spot instances, with integrated backup and auto recovery.


问:
Freezing headers/columns CSS
This is my web template. I want to freeze the header part and also the "#" and "Rank" columns. Vertical scrolling should scroll through the rows only and horizontal scrolling should scroll through Header3 onwards.

```<code>        |     #    |   Rank  | Header3 | Header4 | Header5 | Header6 |
  []    |    #1    |  Rank1  |
  []    |    #2    |  Rank2  |
  []    |    #3    |  Rank3  |
  []    |    #4    |  Rank4  |
  []    |    #5    |  Rank5  |
  []    |    #6    |  Rank6  |
</code>```

I would think there should be separate  tags with different css styles. One of which the headers css style should contain position:fixed.

```<code><div class="form-horizontal table-responsive table-masterinput">
    <table class="table table-hover table-bordered table-striped" id="whatever">
        <thead>
            <tr>
                <th></th>
                <th class="text-center">#</th>
                <th class="text-center">Rank</th>
                <th class="text-center">Header3</th>
                <th class="text-center">Header4</th>
                <th class="text-center">Header5</th>
                <th class="text-center">Header6</th>
            </tr>
        </thead>
        <tbody>
            @{
                var index = 1;
                if (Model != null && Model.Any())
                {
                    foreach (var items in Model)
                    {
                        total += 1;

                        <tr class="checkCountData" id=@("item" + index)>
                            <td>
                                <input type="checkbox" name="@items.Id" id="@items.Id" />
                            </td>
                            <td>
                                <label data-Id="@items.Id" style="width: 100px; text-align: center" class="inputRank" name="inputRank">@items.RANK_CODE</label>
                            </td>
                            <td>Item3</td>
                            <td>Item4</td>
                            <td>Item5</td>
                            <td>Item6</td>
                        </tr>

                        index++;
                    }
                }
            }
        </tbody>
    </table>
</code>```

This is my css:

```<code>.table-masterinput {
    overflow-x: auto;
    height: auto;
    bottom: 0px;
    top: 300px;
    right: 0px;
    left: 180px;
    position: fixed;
}
</code>```

Can someone please help?

答:
try this with jquery and css or try this fiddle check here

$(document).ready(function() {
  $('tbody').scroll(function(e) { //detect a scroll event on the tbody
   /*
    Setting the thead left value to the negative valule of tbody.scrollLeft will make it track the movement
    of the tbody element. Setting an elements left value to that of the tbody.scrollLeft left makes it maintain    it's relative position at the left of the table.
    */
    $('thead').css("left", -$("tbody").scrollLeft()); //fix the thead relative to the body scrolling
    $('thead th:nth-child(1), thead th:nth-child(2)').css("left", $("tbody").scrollLeft()); //fix the first cell of the header
    $('tbody td:nth-child(1), tbody td:nth-child(2)').css("left", $("tbody").scrollLeft()); //fix the first column of tdbody
  });
});```
<pre class="snippet-code-css lang-css prettyprint-override"><code>table {
  position: relative;
  width: 700px;
  background-color: #aaa;
  overflow: hidden;
  border-collapse: collapse;
}

/*thead*/
thead {
  position: relative;
  display: block; /*seperates the header from the body allowing it to be positioned*/
  width: 700px;
  overflow: visible;
}

thead th {
  background-color: #99a;
  min-width: 120px;
  height: 32px;
  border: 1px solid #222;
}

thead th:nth-child(1) {/*first cell in the header*/
  position: relative;
  display: block; /*seperates the first cell in the header from the header*/
  background-color: #88b;
}

thead th:nth-child(2) {/*first cell in the header*/
  position: relative;
  background-color: #88b;
}

/*tbody*/
tbody {
  position: relative;
  display: block; /*seperates the tbody from the header*/
  width: 700px;
  height: 239px;
  overflow: scroll;
}

tbody td {
  background-color: #bbc;
  min-width: 120px;
  border: 1px solid #222;
}

tbody tr td:nth-child(1) {  /*the first cell in each tr*/
  position: relative;
  display: block; /*seperates the first column from the tbody*/
  height: 40px;
  background-color: #99a;
}
tbody tr td:nth-child(2) {  /*the first cell in each tr*/
  position: relative;
  height: 40px;
  background-color: #99a;
}</code>```

        #
        Rank
        Header1
        Header2
        Header3
        Header4
        Header5
        Header6

        #1
        Rank1
        Cheshire
        52
        Brewer
        £47,000
        Married
        2

         #2
        Rank2
        Cumbria
        34
        Shepherdess
        £28,000
        Single
        0

         #3
        Rank3
        Wiltshire
        57
        Musician
        £124,000
        Married
        4

         #4
        Rank4
        Worchestershire
        48
        Naturalist
        £65,000
        Married
        2

         #5
        Rank5
        Hertfordshire
        67
        Pharmasist
        Retired
        Married
        3

         #6
        Rank6
        Lothian
        36
        Vigilante
        £86,000
        Single
        Unknown

         #7
        Rank7
        Bedfordshire
        43
        Housewife
        N/A
        Married
        1

         #8
        Rank8
        New York
        55
        Policewoman
        $36,000
        Single
        1

         #9
        Rank9
        Lincolnshire
        45
        Landowner
        Lots
        Married
        6

         #10
        Rank10
        Cheshire
        352
        Arcanist
        A pile of gems
        Single
        0

```

Title: Freezing headers/columns CSS

Body:
This is my web template. I want to freeze the header part and also the "#" and "Rank" columns. Vertical scrolling should scroll through the rows only and horizontal scrolling should scroll through Header3 onwards.

        |     #    |   Rank  | Header3 | Header4 | Header5 | Header6 |
  []    |    #1    |  Rank1  |
  []    |    #2    |  Rank2  |
  []    |    #3    |  Rank3  |
  []    |    #4    |  Rank4  |
  []    |    #5    |  Rank5  |
  []    |    #6    |  Rank6  |

I would think there should be separate  tags with different css styles. One of which the headers css style should contain position:fixed.

                #
                Rank
                Header3
                Header4
                Header5
                Header6

            @{
                var index = 1;
                if (Model != null && Model.Any())
                {
                    foreach (var items in Model)
                    {
                        total += 1;

                                <input type="checkbox" name="@items.Id" id="@items.Id" />

                                @items.RANK_CODE

                            Item3
                            Item4
                            Item5
                            Item6

                        index++;
                    }
                }
            }

This is my css:

.table-masterinput {
    overflow-x: auto;
    height: auto;
    bottom: 0px;
    top: 300px;
    right: 0px;
    left: 180px;
    position: fixed;
}

Can someone please help?

Body:
try this with jquery and css or try this fiddle check here

$(document).ready(function() {
  $('tbody').scroll(function(e) { //detect a scroll event on the tbody
   /*
    Setting the thead left value to the negative valule of tbody.scrollLeft will make it track the movement
    of the tbody element. Setting an elements left value to that of the tbody.scrollLeft left makes it maintain    it's relative position at the left of the table.
    */
    $('thead').css("left", -$("tbody").scrollLeft()); //fix the thead relative to the body scrolling
    $('thead th:nth-child(1), thead th:nth-child(2)').css("left", $("tbody").scrollLeft()); //fix the first cell of the header
    $('tbody td:nth-child(1), tbody td:nth-child(2)').css("left", $("tbody").scrollLeft()); //fix the first column of tdbody
  });
});

table {
  position: relative;
  width: 700px;
  background-color: #aaa;
  overflow: hidden;
  border-collapse: collapse;
}

/*thead*/
thead {
  position: relative;
  display: block; /*seperates the header from the body allowing it to be positioned*/
  width: 700px;
  overflow: visible;
}

thead th {
  background-color: #99a;
  min-width: 120px;
  height: 32px;
  border: 1px solid #222;
}

thead th:nth-child(1) {/*first cell in the header*/
  position: relative;
  display: block; /*seperates the first cell in the header from the header*/
  background-color: #88b;
}

thead th:nth-child(2) {/*first cell in the header*/
  position: relative;
  background-color: #88b;
}

/*tbody*/
tbody {
  position: relative;
  display: block; /*seperates the tbody from the header*/
  width: 700px;
  height: 239px;
  overflow: scroll;
}

tbody td {
  background-color: #bbc;
  min-width: 120px;
  border: 1px solid #222;
}

tbody tr td:nth-child(1) {  /*the first cell in each tr*/
  position: relative;
  display: block; /*seperates the first column from the tbody*/
  height: 40px;
  background-color: #99a;
}
tbody tr td:nth-child(2) {  /*the first cell in each tr*/
  position: relative;
  height: 40px;
  background-color: #99a;
}

<html lang="en">
<head>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
</head>
<body>
  <table>
    <thead>
      <tr>
        <th>#</th>
        <th>Rank</th>
        <th>Header1</th>
        <th>Header2</th>
        <th>Header3</th>
        <th>Header4</th>
        <th>Header5</th>
        <th>Header6</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td>#1</td>
        <td>Rank1</td>
        <td>Cheshire</td>
        <td>52</td>
        <td>Brewer</td>
        <td>£47,000</td>
        <td>Married</td>
        <td>2</td>
      </tr>
      <tr>
         <td>#2</td>
        <td>Rank2</td>
        <td>Cumbria</td>
        <td>34</td>
        <td>Shepherdess</td>
        <td>£28,000</td>
        <td>Single</td>
        <td>0</td>
      </tr>
      <tr>
         <td>#3</td>
        <td>Rank3</td>
        <td>Wiltshire</td>
        <td>57</td>
        <td>Musician</td>
        <td>£124,000</td>
        <td>Married</td>
        <td>4</td>
      </tr>
      <tr>
         <td>#4</td>
        <td>Rank4</td>
        <td>Worchestershire</td>
        <td>48</td>
        <td>Naturalist</td>
        <td>£65,000</td>
        <td>Married</td>
        <td>2</td>
      </tr>
      <tr>
         <td>#5</td>
        <td>Rank5</td>
        <td>Hertfordshire</td>
        <td>67</td>
        <td>Pharmasist</td>
        <td>Retired</td>
        <td>Married</td>
        <td>3</td>
      </tr>
      <tr>
         <td>#6</td>
        <td>Rank6</td>
        <td>Lothian </td>
        <td>36</td>
        <td>Vigilante</td>
        <td>£86,000</td>
        <td>Single</td>
        <td>Unknown</td>
      </tr>
      <tr>
         <td>#7</td>
        <td>Rank7</td>
        <td>Bedfordshire</td>
        <td>43</td>
        <td>Housewife</td>
        <td>N/A</td>
        <td>Married</td>
        <td>1</td>
      </tr>
      <tr>
         <td>#8</td>
        <td>Rank8</td>
        <td>New York</td>
        <td>55</td>
        <td>Policewoman</td>
        <td>$36,000</td>
        <td>Single</td>
        <td>1</td>
      </tr>
      <tr>
         <td>#9</td>
        <td>Rank9</td>
        <td>Lincolnshire</td>
        <td>45</td>
        <td>Landowner</td>
        <td>Lots</td>
        <td>Married</td>
        <td>6</td>
      </tr>
      <tr>
         <td>#10</td>
        <td>Rank10</td>
        <td>Cheshire</td>
        <td>352</td>
        <td>Arcanist</td>
        <td>A pile of gems</td>
        <td>Single</td>
        <td>0</td>
      </tr>
    </tbody>
  </table>
</body>

</html>


答:
Try this Query, Hope this helps you:</p>

```<code>SELECT TR.Room_Name
    ,MAX(CASE WHEN P.Type_ID=1 THEN Price END)type_I
    ,MAX(CASE WHEN P.Type_ID=2 THEN Price END)type_II
    ,MAX(CASE WHEN P.Type_ID=3 THEN Price END)type_III
    ,MAX(CASE WHEN P.Type_ID=4 THEN Price END)type_IV
FROM TABLE_PRICE P
INNER JOIN TABLE_ROOM TR ON TR.Room_ID=P.Room_ID
INNER JOIN TABLE_TYPE TT ON TT.Type_ID=P.Type_ID
GROUP BY TR.Room_Name
</code>```

Title: How to combine multiple rows into one row

Body:
i want to combine multiple rows into one row.
the table type is dynamic

Table Room

room_id | room_name
-------------------
1       | room_A
2       | room_B
3       | room_C

Table Type

type_id | type_name
-------------------
1       | type_I
2       | type_II
3       | type_II
4       | type_IV

table Price

price_id | room_id | type_id | price
------------------------------------
1        |    1    |    1    | 100
2        |    1    |    2    | 150
3        |    1    |    3    | 200
4        |    1    |    4    | 250
5        |    2    |    1    | 100
6        |    2    |    2    | 200
7        |    2    |    3    | 300
8        |    2    |    4    | 400
9        |    3    |    1    | 150
10       |    3    |    2    | 250
11       |    3    |    3    | 350
12       |    3    |    4    | 450

what i want is something like this

       |                   price
room   |---------------------------------------
       | type_I | type_II | type_III | type_IV
-----------------------------------------------
room_A |   100  |   150   |   200    |   250
room_B |   100  |   200   |   300    |   400
room_C |   150  |   250   |   350    |   450

Body:
Try this Query, Hope this helps you:

SELECT TR.Room_Name
    ,MAX(CASE WHEN P.Type_ID=1 THEN Price END)type_I
    ,MAX(CASE WHEN P.Type_ID=2 THEN Price END)type_II
    ,MAX(CASE WHEN P.Type_ID=3 THEN Price END)type_III
    ,MAX(CASE WHEN P.Type_ID=4 THEN Price END)type_IV
FROM TABLE_PRICE P
INNER JOIN TABLE_ROOM TR ON TR.Room_ID=P.Room_ID
INNER JOIN TABLE_TYPE TT ON TT.Type_ID=P.Type_ID
GROUP BY TR.Room_Name


问:
Getting "task is currently locked" error for SharePoint Workflow created with SharePoint Designer
I am creating a simple workflow using SharePoint Designer that triggers when a user uploads a new Document to a library. This workflow assigns a task to multiple users and then waits until those tasks are complete. Once they are complete it then assigns another task to different users and then waits until those tasks are complete. It repeats this multiple times.

This works great, the problem is that there is no Due Date on the tasks created and they would like a reminder email. Following the Microsoft Documentation I create a secondary workflow on the Task library and set a Due Date on the tasks based off of the Title and send out the reminder.

When I attempt to complete the assigned tasks, it lets me complete the task for one of the users, but after that I receive a "This task is currently locked by a running workflow and cannot be edited" message.

The sharepoint site is part of the Microsoft hosted services, so I have no controll over patches or hotfixes. I believe that it is only a WSS site, not MOSS.

I am new to SharePoint, so any fixes, workarounds, advice, etc. would be appreciated.

答:
This blog by Wouter might clarify things for you...

http://blogs.code-counsel.net/Wouter/Lists/Posts/Post.aspx?List=c04a88a9-d138-4ac3-a2bb-b95c9fdd114e&ID=118

Also, if you are using SP 2007 make sure you have at least installed SP2.