diff --git a/.codebeatsettings b/.codebeatsettings index f921ed8..9fe4c72 100644 --- a/.codebeatsettings +++ b/.codebeatsettings @@ -1,6 +1,6 @@ { "GOLANG": { - "ABC":[15, 25, 50, 70], + "ABC":[25, 35, 50, 70], "BLOCK_NESTING":[5, 6, 7, 8], "CYCLO":[20, 30, 45, 60], "TOO_MANY_IVARS": [15, 18, 20, 25], diff --git a/.travis.yml b/.travis.yml index 87fcf17..057cc9e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,15 +1,15 @@ language: go go: - - "1.8" + - "1.8.7" - "1.9" - "1.10" - "1.11" - "tip" os: - - linux - osx + - linux - windows sudo: false @@ -19,19 +19,6 @@ branches: - master - develop -services: - - memcache - - redis-server - -before_install: - # TRAVIS_OS_NAME - linux and osx - - echo $TRAVIS_OS_NAME - - | - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then - brew update && brew install memcached redis && brew services start redis && brew services start memcached - fi - - redis-server --daemonize yes - - redis-cli info install: # Setting environments variables @@ -39,17 +26,13 @@ install: - export REVEL_BRANCH="develop" - 'if [[ "$TRAVIS_BRANCH" == "master" ]]; then export REVEL_BRANCH="master"; fi' - 'echo "Travis branch: $TRAVIS_BRANCH, Revel dependency branch: $REVEL_BRANCH"' - - git clone -b $REVEL_BRANCH git://github.com/revel/modules ../modules/ - - git clone -b $REVEL_BRANCH git://github.com/revel/revel ../revel/ - - git clone -b $REVEL_BRANCH git://github.com/revel/config ../config/ - - git clone -b $REVEL_BRANCH git://github.com/revel/cron ../cron/ - - git clone -b $REVEL_BRANCH git://github.com/revel/examples ../examples/ - - go get -v github.com/revel/revel/... - - go get -v github.com/revel/cmd/revel + - go get -t -v github.com/revel/cmd/revel - go get -u github.com/golang/dep/cmd/dep - + - echo $GOPATH + - echo $PATH + - pwd script: - - go test -v github.com/revel/cmd/... + - go test -v github.com/revel/cmd/revel/... # Ensure the new-app flow works (plus the other commands). - revel version @@ -65,21 +48,19 @@ script: - revel new -a my/testapp2 - revel test -a my/testapp2 - revel clean -a my/testapp2 - - revel build -a my/testapp2 -t build/testapp - - revel build -a my/testapp2 -t build/testapp -m prod + - revel build -a my/testapp2 -t build/testapp2 + - revel build -a my/testapp2 -t build/testapp2 -m prod - revel package -a my/testapp2 - revel package -a my/testapp2 -m prod - - revel new -a my/testapp3 -V - - revel test -a my/testapp3 - - revel clean -a my/testapp3 - - revel build -a my/testapp3 -t build/testapp - - revel build -a my/testapp3 -t build/testapp -m prod + - revel new -v -a my/testapp3 -V + - revel test -v -a my/testapp3 + - revel clean -v -a my/testapp3 + - revel build -a my/testapp3 -t build/testapp3 + - revel build -a my/testapp3 -t build/testapp3 -m prod - revel package -a my/testapp3 - revel package -a my/testapp3 -m prod matrix: allow_failures: - go: tip - - go: 1.6 - os: osx diff --git a/harness/app.go b/harness/app.go index 2765918..05cc315 100644 --- a/harness/app.go +++ b/harness/app.go @@ -61,28 +61,30 @@ func NewAppCmd(binPath string, port int, runMode string, paths *model.RevelConta // Start the app server, and wait until it is ready to serve requests. func (cmd AppCmd) Start(c *model.CommandConfig) error { - listeningWriter := &startupListeningWriter{os.Stdout, make(chan bool),c} + listeningWriter := &startupListeningWriter{os.Stdout, make(chan bool), c} cmd.Stdout = listeningWriter - utils.Logger.Info("Exec app:", "path", cmd.Path, "args", cmd.Args) + utils.Logger.Info("Exec app:", "path", cmd.Path, "args", cmd.Args, "dir", cmd.Dir, "env", cmd.Env) + utils.CmdInit(cmd.Cmd, c.AppPath) if err := cmd.Cmd.Start(); err != nil { utils.Logger.Fatal("Error running:", "error", err) } select { case exitState := <-cmd.waitChan(): + println("Revel proxy is listening, point your browser to :", c.Run.Port) return errors.New("revel/harness: app died reason: " + exitState) case <-time.After(60 * time.Second): + println("Revel proxy is listening, point your browser to :", c.Run.Port) utils.Logger.Error("Killing revel server process did not respond after wait timeout.", "processid", cmd.Process.Pid) cmd.Kill() return errors.New("revel/harness: app timed out") case <-listeningWriter.notifyReady: + println("Revel proxy is listening, point your browser to :", c.Run.Port) return nil } - // TODO remove this unreachable code and document it - panic("Impossible") } // Run the app server inline. Never returns. @@ -111,7 +113,7 @@ func (cmd AppCmd) waitChan() <-chan string { _ = cmd.Wait() state := cmd.ProcessState exitStatus := " unknown " - if state!=nil { + if state != nil { exitStatus = state.String() } @@ -126,7 +128,7 @@ func (cmd AppCmd) waitChan() <-chan string { type startupListeningWriter struct { dest io.Writer notifyReady chan bool - c *model.CommandConfig + c *model.CommandConfig } func (w *startupListeningWriter) Write(p []byte) (int, error) { diff --git a/harness/build.go b/harness/build.go index 65299ed..c2c4228 100644 --- a/harness/build.go +++ b/harness/build.go @@ -36,12 +36,12 @@ func (c ByString) Less(i, j int) bool { return c[i].String() < c[j].String() } // 2. Run the appropriate "go build" command. // Requires that revel.Init has been called previously. // Returns the path to the built binary, and an error if there was a problem building it. -func Build(c *model.CommandConfig, paths *model.RevelContainer) (app *App, compileError *utils.Error) { +func Build(c *model.CommandConfig, paths *model.RevelContainer) (_ *App, err error) { // First, clear the generated files (to avoid them messing with ProcessSource). cleanSource(paths, "tmp", "routes") - sourceInfo, compileError := parser.ProcessSource(paths) - if compileError != nil { + sourceInfo, err := parser.ProcessSource(paths) + if err != nil { return } @@ -68,9 +68,15 @@ func Build(c *model.CommandConfig, paths *model.RevelContainer) (app *App, compi // without being the main thread cleanSource(paths, "tmp", "routes") - genSource(paths, "tmp", "main.go", RevelMainTemplate, templateArgs) - genSource(paths, filepath.Join("tmp", "run"), "run.go", RevelRunTemplate, templateArgs) - genSource(paths, "routes", "routes.go", RevelRoutesTemplate, templateArgs) + if err = genSource(paths, "tmp", "main.go", RevelMainTemplate, templateArgs); err != nil { + return + } + if err = genSource(paths, filepath.Join("tmp", "run"), "run.go", RevelRunTemplate, templateArgs); err != nil { + return + } + if err = genSource(paths, "routes", "routes.go", RevelRoutesTemplate, templateArgs); err != nil { + return + } // Read build config. buildTags := paths.Config.StringDefault("build.tags", "") @@ -102,23 +108,9 @@ func Build(c *model.CommandConfig, paths *model.RevelContainer) (app *App, compi } } - var depPath string - if useVendor { - utils.Logger.Info("Vendor folder detected, scanning for deps in path") - depPath, err = exec.LookPath("dep") - if err != nil { - // Do not halt build unless a new package needs to be imported - utils.Logger.Warn("Build: `dep` executable not found in PATH, but vendor folder detected." + - "Packages can only be added automatically to the vendor folder using the `dep` tool. " + - "You can install the `dep` tool by doing a `go get -u github.com/golang/dep/cmd/dep`") - } - } else { - utils.Logger.Info("No vendor folder detected, not using dependency manager to import files") - } - pkg, err := build.Default.Import(paths.ImportPath, "", build.FindOnly) if err != nil { - utils.Logger.Fatal("Failure importing", "path", paths.ImportPath) + return } // Binary path is a combination of $GOBIN/revel.d directory, app's import path and its name. @@ -191,6 +183,7 @@ func Build(c *model.CommandConfig, paths *model.RevelContainer) (app *App, compi buildCmd.Env = append(os.Environ(), "GOPATH="+gopath, ) + utils.CmdInit(buildCmd, c.AppPath) utils.Logger.Info("Exec:", "args", buildCmd.Args) output, err := buildCmd.CombinedOutput() @@ -220,32 +213,9 @@ func Build(c *model.CommandConfig, paths *model.RevelContainer) (app *App, compi return nil, newCompileError(paths, output) } gotten[pkgName] = struct{}{} - - // Execute "go get " - // Or dep `dep ensure -add ` if it is there - var getCmd *exec.Cmd - if useVendor { - if depPath == "" { - utils.Logger.Warn("Build: Vendor folder found, but the `dep` tool was not found, " + - "if you use a different vendoring (package management) tool please add the following packages by hand, " + - "or install the `dep` tool into your gopath by doing a `go get -u github.com/golang/dep/cmd/dep`. " + - "For more information and usage of the tool please see http://github.com/golang/dep") - for _, pkg := range matches { - utils.Logger.Warn("Missing package", "package", pkg[1]) - } - } - getCmd = exec.Command(depPath, "ensure", "-add", pkgName) - getCmd.Dir = paths.AppPath - - } else { - getCmd = exec.Command(goPath, "get", pkgName) - } - utils.Logger.Info("Exec:", "args", getCmd.Args) - getOutput, err := getCmd.CombinedOutput() - if err != nil { - utils.Logger.Error("Build failed", "message", stOutput, "error", err) - utils.Logger.Error("Failed to fetch the output", "getOutput", string(getOutput)) - return nil, newCompileError(paths, output) + if err := c.PackageResolver(pkgName); err != nil { + utils.Logger.Error("Unable to resolve package", "package", pkgName, "error", err) + return nil, newCompileError(paths, []byte(err.Error())) } } @@ -336,12 +306,9 @@ func cleanDir(paths *model.RevelContainer, dir string) { // genSource renders the given template to produce source code, which it writes // to the given directory and file. -func genSource(paths *model.RevelContainer, dir, filename, templateSource string, args map[string]interface{}) { +func genSource(paths *model.RevelContainer, dir, filename, templateSource string, args map[string]interface{}) error { - err := utils.MustGenerateTemplate(filepath.Join(paths.AppPath, dir, filename), templateSource, args) - if err != nil { - utils.Logger.Fatal("Failed to generate template for source file", "error", err) - } + return utils.GenerateTemplate(filepath.Join(paths.AppPath, dir, filename), templateSource, args) } // Looks through all the method args and returns a set of unique import paths @@ -433,7 +400,8 @@ func newCompileError(paths *model.RevelContainer, output []byte) *utils.Error { // Extract the paths from the gopaths, and search for file there first gopaths := filepath.SplitList(build.Default.GOPATH) for _, gp := range gopaths { - newPath := filepath.Join(gp, relFilename) + newPath := filepath.Join(gp,"src", paths.ImportPath, relFilename) + println(newPath) if utils.Exists(newPath) { return newPath } @@ -443,6 +411,7 @@ func newCompileError(paths *model.RevelContainer, output []byte) *utils.Error { return newPath } + // Read the source for the offending file. var ( relFilename = string(errorMatch[1]) // e.g. "src/revel/sample/app/controllers/app.go" @@ -467,7 +436,7 @@ func newCompileError(paths *model.RevelContainer, output []byte) *utils.Error { fileStr, err := utils.ReadLines(absFilename) if err != nil { compileError.MetaError = absFilename + ": " + err.Error() - utils.Logger.Error("Unable to readlines "+compileError.MetaError, "error", err) + utils.Logger.Info("Unable to readlines "+compileError.MetaError, "error", err) return compileError } diff --git a/harness/harness.go b/harness/harness.go index 63f8d97..1b00776 100644 --- a/harness/harness.go +++ b/harness/harness.go @@ -31,9 +31,9 @@ import ( "github.com/revel/cmd/model" "github.com/revel/cmd/utils" "github.com/revel/cmd/watcher" - "sync" "html/template" "io/ioutil" + "sync" ) var ( @@ -63,31 +63,31 @@ func (h *Harness) renderError(iw http.ResponseWriter, ir *http.Request, err erro // 1) Application/views/errors // 2) revel_home/views/errors // 3) views/errors - if err==nil { + if err == nil { utils.Logger.Panic("Caller passed in a nil error") } templateSet := template.New("__root__") - seekViewOnPath:=func(view string) (path string) { + seekViewOnPath := func(view string) (path string) { path = filepath.Join(h.paths.ViewsPath, "errors", view) if !utils.Exists(path) { path = filepath.Join(h.paths.RevelPath, "templates", "errors", view) } - data,err := ioutil.ReadFile(path) - if err!=nil { + data, err := ioutil.ReadFile(path) + if err != nil { utils.Logger.Error("Unable to read template file", path) } - _,err = templateSet.New("errors/"+view).Parse(string(data)) - if err!=nil { + _, err = templateSet.New("errors/" + view).Parse(string(data)) + if err != nil { utils.Logger.Error("Unable to parse template file", path) } return } - target := []string{seekViewOnPath("500.html"),seekViewOnPath("500-dev.html")} + target := []string{seekViewOnPath("500.html"), seekViewOnPath("500-dev.html")} if !utils.Exists(target[0]) { fmt.Fprintf(iw, "Target template not found not found %s
\n", target[0]) fmt.Fprintf(iw, "An error ocurred %s", err.Error()) - return + return } var revelError *utils.Error switch e := err.(type) { @@ -108,16 +108,11 @@ func (h *Harness) renderError(iw http.ResponseWriter, ir *http.Request, err erro viewArgs["DevMode"] = h.paths.DevMode viewArgs["Error"] = revelError - - // Render the template from the file - err = templateSet.ExecuteTemplate(iw,"errors/500.html",viewArgs) - if err!=nil { - utils.Logger.Error("Failed to execute","error",err) + err = templateSet.ExecuteTemplate(iw, "errors/500.html", viewArgs) + if err != nil { + utils.Logger.Error("Failed to execute", "error", err) } - fmt.Println("template ",templateSet.Templates()[0].Name(), templateSet.Templates()[1].Name()) - //utils.MustRenderTemplateToStream(iw,target, viewArgs) - } // ServeHTTP handles all requests. @@ -192,7 +187,6 @@ func NewHarness(c *model.CommandConfig, paths *model.RevelContainer, runMode str useProxy: !noProxy, config: c, runMode: runMode, - } if paths.HTTPSsl { @@ -219,9 +213,17 @@ func (h *Harness) Refresh() (err *utils.Error) { } utils.Logger.Info("Rebuild Called") - h.app, err = Build(h.config, h.paths) - if err != nil { - utils.Logger.Error("Build detected an error", "error", err) + var newErr error + h.app, newErr = Build(h.config, h.paths) + if newErr != nil { + utils.Logger.Error("Build detected an error", "error", newErr) + if castErr, ok := newErr.(*utils.Error); ok { + return castErr + } + err = &utils.Error{ + Title: "App failed to start up", + Description: err.Error(), + } return } @@ -269,7 +271,7 @@ func (h *Harness) Run() { if h.useProxy { go func() { // Check the port to start on a random port - if h.paths.HTTPPort==0 { + if h.paths.HTTPPort == 0 { h.paths.HTTPPort = getFreePort() } addr := fmt.Sprintf("%s:%d", h.paths.HTTPAddr, h.paths.HTTPPort) diff --git a/logger/doc.go b/logger/doc.go index 4392734..7cd8296 100644 --- a/logger/doc.go +++ b/logger/doc.go @@ -1,4 +1,3 @@ - /* Package logger contains filters and handles for the logging utilities in Revel. These facilities all currently use the logging library called log15 at @@ -7,5 +6,5 @@ Wrappers for the handlers are written here to provide a kind of isolation layer for Revel in case sometime in the future we would like to switch to another source to implement logging - */ +*/ package logger diff --git a/logger/logger.go b/logger/logger.go index a0417f1..8474d00 100644 --- a/logger/logger.go +++ b/logger/logger.go @@ -121,6 +121,7 @@ func SetDefaultLog(fromLog MultiLogger) { func (rl *RevelLogger) Debugf(msg string, param ...interface{}) { rl.Debug(fmt.Sprintf(msg, param...)) } + // Formatted info call func (rl *RevelLogger) Infof(msg string, param ...interface{}) { rl.Info(fmt.Sprintf(msg, param...)) diff --git a/logger/utils.go b/logger/utils.go index 3a98b8d..6d5dc87 100644 --- a/logger/utils.go +++ b/logger/utils.go @@ -1,9 +1,9 @@ package logger import ( - "gopkg.in/stack.v0" "github.com/revel/config" "github.com/revel/log15" + "gopkg.in/stack.v0" "log" "os" "path/filepath" @@ -43,15 +43,14 @@ func GetLogger(name string, logger MultiLogger) (l *log.Logger) { // Get all handlers based on the Config (if available) func InitializeFromConfig(basePath string, config *config.Context) (c *CompositeMultiHandler) { // If running in test mode suppress anything that is not an error - if config!=nil && config.BoolDefault("testModeFlag",false) { - config.SetOption("log.info.output","none") - config.SetOption("log.debug.output","none") - config.SetOption("log.warn.output","none") - config.SetOption("log.error.output","stderr") - config.SetOption("log.crit.output","stderr") + if config != nil && config.BoolDefault("testModeFlag", false) { + config.SetOption("log.info.output", "off") + config.SetOption("log.debug.output", "off") + config.SetOption("log.warn.output", "off") + config.SetOption("log.error.output", "stderr") + config.SetOption("log.crit.output", "stderr") } - // If the configuration has an all option we can skip some c, _ = NewCompositeMultiHandler() diff --git a/model/command_config.go b/model/command_config.go index e7f6ae6..3de36f9 100644 --- a/model/command_config.go +++ b/model/command_config.go @@ -2,11 +2,14 @@ package model // The constants import ( + "fmt" + "github.com/revel/cmd/logger" + "github.com/revel/cmd/utils" "go/build" "os" + "os/exec" "path/filepath" "strings" - "github.com/revel/cmd/utils" ) const ( @@ -25,58 +28,58 @@ type ( // The Command config for the line input CommandConfig struct { - Index COMMAND // The index - Verbose bool `short:"v" long:"debug" description:"If set the logger is set to verbose"` // True if debug is active - HistoricMode bool `long:"historic-run-mode" description:"If set the runmode is passed a string not json"` // True if debug is active - ImportPath string // The import path (converted from various commands) - GoPath string // The GoPath - GoCmd string // The full path to the go executable - SrcRoot string // The source root - AppPath string // The application path - AppName string // The applicaiton name - BasePath string // The base path - SkeletonPath string // The skeleton path - BuildFlags []string `short:"X" long:"build-flags" description:"These flags will be used when building the application. May be specified multiple times, only applicable for Build, Run, Package, Test commands"` + Index COMMAND // The index + Verbose []bool `short:"v" long:"debug" description:"If set the logger is set to verbose"` // True if debug is active + HistoricMode bool `long:"historic-run-mode" description:"If set the runmode is passed a string not json"` // True if debug is active + ImportPath string // The import path (relative to a GOPATH) + GoPath string // The GoPath + GoCmd string // The full path to the go executable + SrcRoot string // The source root + AppPath string // The application path (absolute) + AppName string // The application name + PackageResolver func(pkgName string) error // a packge resolver for the config + BuildFlags []string `short:"X" long:"build-flags" description:"These flags will be used when building the application. May be specified multiple times, only applicable for Build, Run, Package, Test commands"` // The new command New struct { - ImportPath string `short:"a" long:"application-path" description:"Path to applicaiton folder" required:"true"` - Skeleton string `short:"s" long:"skeleton" description:"Path to skeleton folder (Must exist on GO PATH)" required:"false"` - Vendored bool `short:"V" long:"vendor" description:"True if project should contain a vendor folder to be initialized. Creates the vendor folder and the 'Gopkg.toml' file in the root"` - Run bool `short:"r" long:"run" description:"True if you want to run the application right away"` + ImportPath string `short:"a" long:"application-path" description:"Path to application folder" required:"false"` + SkeletonPath string `short:"s" long:"skeleton" description:"Path to skeleton folder (Must exist on GO PATH)" required:"false"` + Vendored bool `short:"V" long:"vendor" description:"True if project should contain a vendor folder to be initialized. Creates the vendor folder and the 'Gopkg.toml' file in the root"` + Run bool `short:"r" long:"run" description:"True if you want to run the application right away"` } `command:"new"` // The build command Build struct { - TargetPath string `short:"t" long:"target-path" description:"Path to target folder. Folder will be completely deleted if it exists" required:"true"` - ImportPath string `short:"a" long:"application-path" description:"Path to applicaiton folder" required:"true"` + TargetPath string `short:"t" long:"target-path" description:"Path to target folder. Folder will be completely deleted if it exists" required:"false"` + ImportPath string `short:"a" long:"application-path" description:"Path to application folder" required:"false"` Mode string `short:"m" long:"run-mode" description:"The mode to run the application in"` CopySource bool `short:"s" long:"include-source" description:"Copy the source code as well"` } `command:"build"` // The run command Run struct { - ImportPath string `short:"a" long:"application-path" description:"Path to applicaiton folder" required:"true"` + ImportPath string `short:"a" long:"application-path" description:"Path to application folder" required:"false"` Mode string `short:"m" long:"run-mode" description:"The mode to run the application in"` - Port string `short:"p" long:"port" description:"The port to listen"` + Port int `short:"p" long:"port" default:"-1" description:"The port to listen" ` NoProxy bool `short:"n" long:"no-proxy" description:"True if proxy server should not be started. This will only update the main and routes files on change"` } `command:"run"` // The package command Package struct { + TargetPath string `short:"t" long:"target-path" description:"Full path and filename of target package to deploy" required:"false"` Mode string `short:"m" long:"run-mode" description:"The mode to run the application in"` - ImportPath string `short:"a" long:"application-path" description:"Path to applicaiton folder" required:"true"` + ImportPath string `short:"a" long:"application-path" description:"Path to application folder" required:"false"` CopySource bool `short:"s" long:"include-source" description:"Copy the source code as well"` } `command:"package"` // The clean command Clean struct { - ImportPath string `short:"a" long:"application-path" description:"Path to applicaiton folder" required:"true"` + ImportPath string `short:"a" long:"application-path" description:"Path to application folder" required:"false"` } `command:"clean"` // The test command Test struct { Mode string `short:"m" long:"run-mode" description:"The mode to run the application in"` - ImportPath string `short:"a" long:"application-path" description:"Path to applicaiton folder" required:"true"` + ImportPath string `short:"a" long:"application-path" description:"Path to application folder" required:"false"` Function string `short:"f" long:"suite-function" description:"The suite.function"` } `command:"test"` // The version command Version struct { - ImportPath string `short:"a" long:"application-path" description:"Path to applicaiton folder" required:"false"` + ImportPath string `short:"a" long:"application-path" description:"Path to application folder" required:"false"` } `command:"version"` } ) @@ -115,13 +118,14 @@ func (c *CommandConfig) UpdateImportPath() bool { currentPath, _ = filepath.Abs(importPath) } + if err == nil { for _, path := range strings.Split(build.Default.GOPATH, string(filepath.ListSeparator)) { utils.Logger.Infof("Checking import path %s with %s", currentPath, path) - if strings.HasPrefix(currentPath, path) { - importPath = currentPath[len(path) + 1:] + if strings.HasPrefix(currentPath, path) && len(currentPath) > len(path)+1 { + importPath = currentPath[len(path)+1:] // Remove the source from the path if it is there - if len(importPath)>4 && strings.ToLower(importPath[0:4]) == "src/" { + if len(importPath) > 4 && strings.ToLower(importPath[0:4]) == "src/" { importPath = importPath[4:] } else if importPath == "src" { importPath = "" @@ -133,6 +137,122 @@ func (c *CommandConfig) UpdateImportPath() bool { } c.ImportPath = importPath - utils.Logger.Info("Returned import path", "path", importPath, "buildpath",build.Default.GOPATH) + utils.Logger.Info("Returned import path", "path", importPath, "buildpath", build.Default.GOPATH) return (len(importPath) > 0 || !required) } + +// Used to initialize the package resolver +func (c *CommandConfig) InitPackageResolver() { + useVendor := utils.DirExists(filepath.Join(c.AppPath, "vendor")) + if c.Index == NEW && c.New.Vendored { + useVendor = true + } + utils.Logger.Info("InitPackageResolver", "useVendor", useVendor, "path", c.AppPath) + + var ( + depPath string + err error + ) + + if useVendor { + utils.Logger.Info("Vendor folder detected, scanning for deps in path") + depPath, err = exec.LookPath("dep") + if err != nil { + // Do not halt build unless a new package needs to be imported + utils.Logger.Fatal("Build: `dep` executable not found in PATH, but vendor folder detected." + + "Packages can only be added automatically to the vendor folder using the `dep` tool. " + + "You can install the `dep` tool by doing a `go get -u github.com/golang/dep/cmd/dep`") + } + } + + // This should get called when needed + c.PackageResolver = func(pkgName string) error { + //useVendor := utils.DirExists(filepath.Join(c.AppPath, "vendor")) + + var getCmd *exec.Cmd + utils.Logger.Info("Request for package ", "package", pkgName, "use vendor", useVendor) + if useVendor { + utils.Logger.Info("Using dependency manager to import package", "package", pkgName) + + if depPath == "" { + utils.Logger.Error("Build: Vendor folder found, but the `dep` tool was not found, " + + "if you use a different vendoring (package management) tool please add the following packages by hand, " + + "or install the `dep` tool into your gopath by doing a `go get -u github.com/golang/dep/cmd/dep`. " + + "For more information and usage of the tool please see http://github.com/golang/dep") + utils.Logger.Error("Missing package", "package", pkgName) + return fmt.Errorf("Missing package %s", pkgName) + } + getCmd = exec.Command(depPath, "ensure", "-add", pkgName) + } else { + utils.Logger.Info("No vendor folder detected, not using dependency manager to import package", "package", pkgName) + getCmd = exec.Command(c.GoCmd, "get", pkgName) + } + + utils.CmdInit(getCmd, c.AppPath) + utils.Logger.Info("Go get command ", "exec", getCmd.Path, "dir", getCmd.Dir, "args", getCmd.Args, "env", getCmd.Env, "package", pkgName) + output, err := getCmd.CombinedOutput() + if err != nil { + fmt.Printf("Error stack %v\n", logger.NewCallStack()) + utils.Logger.Error("Failed to import package", "error", err, "gopath", build.Default.GOPATH, "GO-ROOT", build.Default.GOROOT, "output", string(output)) + } + return err + } +} + +// lookup and set Go related variables +func (c *CommandConfig) InitGoPaths() { + // lookup go path + c.GoPath = build.Default.GOPATH + if c.GoPath == "" { + utils.Logger.Fatal("Abort: GOPATH environment variable is not set. " + + "Please refer to http://golang.org/doc/code.html to configure your Go environment.") + } + + // check for go executable + var err error + c.GoCmd, err = exec.LookPath("go") + if err != nil { + utils.Logger.Fatal("Go executable not found in PATH.") + } + + // revel/revel#1004 choose go path relative to current working directory + + // What we want to do is to add the import to the end of the + // gopath, and discover which import exists - If none exist this is an error except in the case + // where we are dealing with new which is a special case where we will attempt to target the working directory first + workingDir, _ := os.Getwd() + goPathList := filepath.SplitList(c.GoPath) + bestpath := "" + for _, path := range goPathList { + if c.Index == NEW { + // If the GOPATH is part of the working dir this is the most likely target + if strings.HasPrefix(workingDir, path) { + bestpath = path + } + } else { + if utils.Exists(filepath.Join(path, "src", c.ImportPath)) { + c.SrcRoot = path + break + } + } + } + + if len(c.SrcRoot)==0 && len(bestpath) > 0 { + c.SrcRoot = bestpath + } + utils.Logger.Info("Source root", "path", c.SrcRoot, "cwd", workingDir, "gopath", c.GoPath) + + // If source root is empty and this isn't a version then skip it + if len(c.SrcRoot) == 0 { + if c.Index != VERSION { + utils.Logger.Fatal("Abort: could not create a Revel application outside of GOPATH.") + } + return + } + + // set go src path + c.SrcRoot = filepath.Join(c.SrcRoot, "src") + + c.AppPath = filepath.Join(c.SrcRoot, filepath.FromSlash(c.ImportPath)) + utils.Logger.Info("Set application path", "path", c.AppPath) +} diff --git a/model/embedded_type_name.go b/model/embedded_type_name.go index 6a67056..f6d6172 100644 --- a/model/embedded_type_name.go +++ b/model/embedded_type_name.go @@ -8,4 +8,4 @@ type EmbeddedTypeName struct { // Convert the type to a properly formatted import line func (s *EmbeddedTypeName) String() string { return s.ImportPath + "." + s.StructName -} \ No newline at end of file +} diff --git a/model/event.go b/model/event.go new file mode 100644 index 0000000..7032443 --- /dev/null +++ b/model/event.go @@ -0,0 +1,62 @@ +package model + +type ( + // The event type + Event int + // The event response + EventResponse int + // The handler signature + EventHandler func(typeOf Event, value interface{}) (responseOf EventResponse) + RevelCallback interface { + FireEvent(key Event, value interface{}) (response EventResponse) + PackageResolver(pkgName string) error + } +) + +const ( + // Event type when templates are going to be refreshed (receivers are registered template engines added to the template.engine conf option) + TEMPLATE_REFRESH_REQUESTED Event = iota + // Event type when templates are refreshed (receivers are registered template engines added to the template.engine conf option) + TEMPLATE_REFRESH_COMPLETED + // Event type before all module loads, events thrown to handlers added to AddInitEventHandler + + // Event type before all module loads, events thrown to handlers added to AddInitEventHandler + REVEL_BEFORE_MODULES_LOADED + // Event type before module loads, events thrown to handlers added to AddInitEventHandler + REVEL_BEFORE_MODULE_LOADED + // Event type after module loads, events thrown to handlers added to AddInitEventHandler + REVEL_AFTER_MODULE_LOADED + // Event type after all module loads, events thrown to handlers added to AddInitEventHandler + REVEL_AFTER_MODULES_LOADED + + // Event type before server engine is initialized, receivers are active server engine and handlers added to AddInitEventHandler + ENGINE_BEFORE_INITIALIZED + // Event type before server engine is started, receivers are active server engine and handlers added to AddInitEventHandler + ENGINE_STARTED + // Event type after server engine is stopped, receivers are active server engine and handlers added to AddInitEventHandler + ENGINE_SHUTDOWN + + // Called before routes are refreshed + ROUTE_REFRESH_REQUESTED + // Called after routes have been refreshed + ROUTE_REFRESH_COMPLETED + + // Fired when a panic is caught during the startup process + REVEL_FAILURE +) + +var initEventList = []EventHandler{} // Event handler list for receiving events + +// Fires system events from revel +func RaiseEvent(key Event, value interface{}) (response EventResponse) { + for _, handler := range initEventList { + response |= handler(key, value) + } + return +} + +// Add event handler to listen for all system events +func AddInitEventHandler(handler EventHandler) { + initEventList = append(initEventList, handler) + return +} diff --git a/model/event_test.go b/model/event_test.go new file mode 100644 index 0000000..e3f063c --- /dev/null +++ b/model/event_test.go @@ -0,0 +1,24 @@ +package model_test + +import ( + "github.com/revel/revel" + "github.com/stretchr/testify/assert" + "testing" +) + +// Test that the event handler can be attached and it dispatches the event received +func TestEventHandler(t *testing.T) { + counter := 0 + newListener := func(typeOf revel.Event, value interface{}) (responseOf revel.EventResponse) { + if typeOf == revel.REVEL_FAILURE { + counter++ + } + return + } + // Attach the same handlder twice so we expect to see the response twice as well + revel.AddInitEventHandler(newListener) + revel.AddInitEventHandler(newListener) + revel.RaiseEvent(revel.REVEL_AFTER_MODULES_LOADED, nil) + revel.RaiseEvent(revel.REVEL_FAILURE, nil) + assert.Equal(t, counter, 2, "Expected event handler to have been called") +} diff --git a/model/method.go b/model/method.go index 5652a8c..ea5357d 100644 --- a/model/method.go +++ b/model/method.go @@ -1,6 +1,5 @@ package model - // methodCall describes a call to c.Render(..) // It documents the argument names used, in order to propagate them to RenderArgs. type MethodCall struct { @@ -22,4 +21,3 @@ type MethodArg struct { TypeExpr TypeExpr // The name of the type, e.g. "int", "*pkg.UserType" ImportPath string // If the arg is of an imported type, this is the import path. } - diff --git a/model/revel_container.go b/model/revel_container.go index 88583fa..64ad4f3 100644 --- a/model/revel_container.go +++ b/model/revel_container.go @@ -6,92 +6,96 @@ import ( "github.com/revel/config" "go/build" - "os" + "errors" + "fmt" "path/filepath" "sort" "strings" ) -const ( - // Event type when templates are going to be refreshed (receivers are registered template engines added to the template.engine conf option) - TEMPLATE_REFRESH_REQUESTED = iota - // Event type when templates are refreshed (receivers are registered template engines added to the template.engine conf option) - TEMPLATE_REFRESH_COMPLETED - // Event type before all module loads, events thrown to handlers added to AddInitEventHandler - // Event type before all module loads, events thrown to handlers added to AddInitEventHandler - REVEL_BEFORE_MODULES_LOADED - // Event type called when a new module is found - REVEL_BEFORE_MODULE_LOADED - // Event type called when after a new module is found - REVEL_AFTER_MODULE_LOADED - // Event type after all module loads, events thrown to handlers added to AddInitEventHandler - REVEL_AFTER_MODULES_LOADED - - // Event type before server engine is initialized, receivers are active server engine and handlers added to AddInitEventHandler - ENGINE_BEFORE_INITIALIZED - // Event type before server engine is started, receivers are active server engine and handlers added to AddInitEventHandler - ENGINE_STARTED - // Event type after server engine is stopped, receivers are active server engine and handlers added to AddInitEventHandler - ENGINE_SHUTDOWN - - // Called before routes are refreshed - ROUTE_REFRESH_REQUESTED - // Called after routes have been refreshed - ROUTE_REFRESH_COMPLETED -) type ( // The container object for describing all Revels variables RevelContainer struct { - ImportPath string // The import path - SourcePath string // The full source path - RunMode string // The current run mode - RevelPath string // The path to the Revel source code - BasePath string // The base path to the application - AppPath string // The application path (BasePath + "/app" - ViewsPath string // The application views path - CodePaths []string // All the code paths - TemplatePaths []string // All the template paths - ConfPaths []string // All the configuration paths - Config *config.Context // The global config object - Packaged bool // True if packaged - DevMode bool // True if running in dev mode - HTTPPort int // The http port - HTTPAddr string // The http address - HTTPSsl bool // True if running https - HTTPSslCert string // The SSL certificate - HTTPSslKey string // The SSL key - AppName string // The application name - AppRoot string // The application root from the config `app.root` - CookiePrefix string // The cookie prefix - CookieDomain string // The cookie domain - CookieSecure bool // True if cookie is secure - SecretStr string // The secret string - MimeConfig *config.Context // The mime configuration + BuildPaths struct { + Revel string + } + Paths struct { + Import string + Source string + Base string + App string + Views string + Code []string + Template []string + Config []string + } + PackageInfo struct { + Config config.Context + Packaged bool + DevMode bool + Vendor bool + } + Application struct { + Name string + Root string + } + + ImportPath string // The import path + SourcePath string // The full source path + RunMode string // The current run mode + RevelPath string // The path to the Revel source code + BasePath string // The base path to the application + AppPath string // The application path (BasePath + "/app") + ViewsPath string // The application views path + CodePaths []string // All the code paths + TemplatePaths []string // All the template paths + ConfPaths []string // All the configuration paths + Config *config.Context // The global config object + Packaged bool // True if packaged + DevMode bool // True if running in dev mode + HTTPPort int // The http port + HTTPAddr string // The http address + HTTPSsl bool // True if running https + HTTPSslCert string // The SSL certificate + HTTPSslKey string // The SSL key + AppName string // The application name + AppRoot string // The application root from the config `app.root` + CookiePrefix string // The cookie prefix + CookieDomain string // The cookie domain + CookieSecure bool // True if cookie is secure + SecretStr string // The secret string + MimeConfig *config.Context // The mime configuration ModulePathMap map[string]string // The module path map } - RevelCallback interface { - FireEvent(key int, value interface{}) (response int) + WrappedRevelCallback struct { + FireEventFunction func(key Event, value interface{}) (response EventResponse) + ImportFunction func(pkgName string) error } - doNothingRevelCallback struct { - - } - ) -// Simple callback to pass to the RevelCallback that does nothing -var DoNothingRevelCallback = RevelCallback(&doNothingRevelCallback{}) +// Simple Wrapped RevelCallback +func NewWrappedRevelCallback(fe func(key Event, value interface{}) (response EventResponse), ie func(pkgName string) error) RevelCallback { + return &WrappedRevelCallback{fe, ie} +} -func (_ *doNothingRevelCallback) FireEvent(key int, value interface{}) (response int) { +// Function to implement the FireEvent +func (w *WrappedRevelCallback) FireEvent(key Event, value interface{}) (response EventResponse) { + if w.FireEventFunction != nil { + response = w.FireEventFunction(key, value) + } return } +func (w *WrappedRevelCallback) PackageResolver(pkgName string) error { + return w.ImportFunction(pkgName) +} // RevelImportPath Revel framework import path var RevelImportPath = "github.com/revel/revel" // This function returns a container object describing the revel application // eventually this type of function will replace the global variables. -func NewRevelPaths(mode, importPath, srcPath string, callback RevelCallback) (rp *RevelContainer) { +func NewRevelPaths(mode, importPath, srcPath string, callback RevelCallback) (rp *RevelContainer, err error) { rp = &RevelContainer{ModulePathMap: map[string]string{}} // Ignore trailing slashes. rp.ImportPath = strings.TrimRight(importPath, "/") @@ -101,17 +105,20 @@ func NewRevelPaths(mode, importPath, srcPath string, callback RevelCallback) (rp // If the SourcePath is not specified, find it using build.Import. var revelSourcePath string // may be different from the app source path if rp.SourcePath == "" { - revelSourcePath, rp.SourcePath = findSrcPaths(importPath) + rp.SourcePath, revelSourcePath, err = utils.FindSrcPaths(importPath, RevelImportPath, callback.PackageResolver) + if err != nil { + return + } } else { // If the SourcePath was specified, assume both Revel and the app are within it. rp.SourcePath = filepath.Clean(rp.SourcePath) revelSourcePath = rp.SourcePath - } // Setup paths for application rp.RevelPath = filepath.Join(revelSourcePath, filepath.FromSlash(RevelImportPath)) rp.BasePath = filepath.Join(rp.SourcePath, filepath.FromSlash(importPath)) + rp.PackageInfo.Vendor = utils.Exists(filepath.Join(rp.BasePath, "vendor")) rp.AppPath = filepath.Join(rp.BasePath, "app") rp.ViewsPath = filepath.Join(rp.AppPath, "views") @@ -133,11 +140,9 @@ func NewRevelPaths(mode, importPath, srcPath string, callback RevelCallback) (rp }, rp.ConfPaths...) - var err error rp.Config, err = config.LoadContext("app.conf", rp.ConfPaths) if err != nil { - utils.Logger.Fatal("Unable to load configuartion file ","error", err) - os.Exit(1) + return rp, fmt.Errorf("Unable to load configuartion file %s", err) } // Ensure that the selected runmode appears in app.conf. @@ -146,7 +151,7 @@ func NewRevelPaths(mode, importPath, srcPath string, callback RevelCallback) (rp mode = config.DefaultSection } if !rp.Config.HasSection(mode) { - utils.Logger.Fatal("app.conf: No mode found:","run-mode", mode) + return rp, fmt.Errorf("app.conf: No mode found: %s %s", "run-mode", mode) } rp.Config.SetSection(mode) @@ -159,10 +164,10 @@ func NewRevelPaths(mode, importPath, srcPath string, callback RevelCallback) (rp rp.HTTPSslKey = rp.Config.StringDefault("http.sslkey", "") if rp.HTTPSsl { if rp.HTTPSslCert == "" { - utils.Logger.Fatal("No http.sslcert provided.") + return rp, errors.New("No http.sslcert provided.") } if rp.HTTPSslKey == "" { - utils.Logger.Fatal("No http.sslkey provided.") + return rp, errors.New("No http.sslkey provided.") } } // @@ -173,21 +178,23 @@ func NewRevelPaths(mode, importPath, srcPath string, callback RevelCallback) (rp rp.CookieSecure = rp.Config.BoolDefault("cookie.secure", rp.HTTPSsl) rp.SecretStr = rp.Config.StringDefault("app.secret", "") - callback.FireEvent(REVEL_BEFORE_MODULES_LOADED, nil) - rp.loadModules(callback) + if err := rp.loadModules(callback); err != nil { + return rp, err + } + callback.FireEvent(REVEL_AFTER_MODULES_LOADED, nil) return } // LoadMimeConfig load mime-types.conf on init. -func (rp *RevelContainer) LoadMimeConfig() { - var err error +func (rp *RevelContainer) LoadMimeConfig() (err error) { rp.MimeConfig, err = config.LoadContext("mime-types.conf", rp.ConfPaths) if err != nil { - utils.Logger.Fatal("Failed to load mime type config:", "error", err) + return fmt.Errorf("Failed to load mime type config: %s %s", "error", err) } + return } // Loads modules based on the configuration setup. @@ -195,7 +202,7 @@ func (rp *RevelContainer) LoadMimeConfig() { // for each module loaded. The callback will receive the RevelContainer, name, moduleImportPath and modulePath // It will automatically add in the code paths for the module to the // container object -func (rp *RevelContainer) loadModules(callback RevelCallback) { +func (rp *RevelContainer) loadModules(callback RevelCallback) (err error) { keys := []string{} for _, key := range rp.Config.Options("module.") { keys = append(keys, key) @@ -211,7 +218,12 @@ func (rp *RevelContainer) loadModules(callback RevelCallback) { modulePath, err := rp.ResolveImportPath(moduleImportPath) if err != nil { - utils.Logger.Error("Failed to load module. Import of path failed", "modulePath", moduleImportPath, "error", err) + utils.Logger.Info("Missing module ", "module", moduleImportPath, "error",err) + callback.PackageResolver(moduleImportPath) + modulePath, err = rp.ResolveImportPath(moduleImportPath) + if err != nil { + return fmt.Errorf("Failed to load module. Import of path failed %s:%s %s:%s ", "modulePath", moduleImportPath, "error", err) + } } // Drop anything between module.???. name := key[len("module."):] @@ -222,6 +234,7 @@ func (rp *RevelContainer) loadModules(callback RevelCallback) { rp.addModulePaths(name, moduleImportPath, modulePath) callback.FireEvent(REVEL_AFTER_MODULE_LOADED, []interface{}{rp, name, moduleImportPath, modulePath}) } + return } // Adds a module paths to the container object @@ -252,43 +265,12 @@ func (rp *RevelContainer) ResolveImportPath(importPath string) (string, error) { return filepath.Join(rp.SourcePath, importPath), nil } - modPkg, err := build.Import(importPath, rp.RevelPath, build.FindOnly) + modPkg, err := build.Import(importPath, rp.AppPath, build.FindOnly) if err != nil { return "", err } + if rp.PackageInfo.Vendor && !strings.HasPrefix(modPkg.Dir,rp.BasePath) { + return "", fmt.Errorf("Module %s was found outside of path %s.",importPath, modPkg.Dir) + } return modPkg.Dir, nil } - -// Find the full source dir for the import path, uses the build.Default.GOPATH to search for the directory -func findSrcPaths(importPath string) (revelSourcePath, appSourcePath string) { - var ( - gopaths = filepath.SplitList(build.Default.GOPATH) - goroot = build.Default.GOROOT - ) - - if len(gopaths) == 0 { - utils.Logger.Fatalf("GOPATH environment variable is not set. " + - "Please refer to http://golang.org/doc/code.html to configure your Go environment.") - } - - if utils.ContainsString(gopaths, goroot) { - utils.Logger.Fatalf("GOPATH (%s) must not include your GOROOT (%s). "+ - "Please refer to http://golang.org/doc/code.html to configure your Go environment.", - gopaths, goroot) - - } - - appPkg, err := build.Import(importPath, "", build.FindOnly) - if err != nil { - utils.Logger.Fatal("Failed to import "+importPath+" with error:", "error", err) - } - - revelPkg, err := build.Import(RevelImportPath, appPkg.Dir, build.FindOnly) - if err != nil { - utils.Logger.Fatal("Failed to find Revel with error:", "error", err) - } - - revelSourcePath, appSourcePath = revelPkg.Dir[:len(revelPkg.Dir)-len(RevelImportPath)], appPkg.SrcRoot - return -} - diff --git a/model/type_info.go b/model/type_info.go index 5489992..97fb6bb 100644 --- a/model/type_info.go +++ b/model/type_info.go @@ -2,10 +2,10 @@ package model // TypeInfo summarizes information about a struct type in the app source code. type TypeInfo struct { - StructName string // e.g. "Application" - ImportPath string // e.g. "github.com/revel/examples/chat/app/controllers" - PackageName string // e.g. "controllers" - MethodSpecs []*MethodSpec // Method specifications, the action functions + StructName string // e.g. "Application" + ImportPath string // e.g. "github.com/revel/examples/chat/app/controllers" + PackageName string // e.g. "controllers" + MethodSpecs []*MethodSpec // Method specifications, the action functions EmbeddedTypes []*EmbeddedTypeName // Used internally to identify controllers that indirectly embed *revel.Controller. } @@ -13,4 +13,3 @@ type TypeInfo struct { func (s *TypeInfo) String() string { return s.ImportPath + "." + s.StructName } - diff --git a/parser/appends.go b/parser/appends.go new file mode 100644 index 0000000..2990795 --- /dev/null +++ b/parser/appends.go @@ -0,0 +1,223 @@ +package parser + +import ( + "go/ast" + "github.com/revel/cmd/utils" + "github.com/revel/cmd/model" + "go/token" +) + +// If this Decl is a struct type definition, it is summarized and added to specs. +// Else, specs is returned unchanged. +func appendStruct(fileName string, specs []*model.TypeInfo, pkgImportPath string, pkg *ast.Package, decl ast.Decl, imports map[string]string, fset *token.FileSet) []*model.TypeInfo { + // Filter out non-Struct type declarations. + spec, found := getStructTypeDecl(decl, fset) + if !found { + return specs + } + + structType := spec.Type.(*ast.StructType) + + // At this point we know it's a type declaration for a struct. + // Fill in the rest of the info by diving into the fields. + // Add it provisionally to the Controller list -- it's later filtered using field info. + controllerSpec := &model.TypeInfo{ + StructName: spec.Name.Name, + ImportPath: pkgImportPath, + PackageName: pkg.Name, + } + + for _, field := range structType.Fields.List { + // If field.Names is set, it's not an embedded type. + if field.Names != nil { + continue + } + + // A direct "sub-type" has an ast.Field as either: + // Ident { "AppController" } + // SelectorExpr { "rev", "Controller" } + // Additionally, that can be wrapped by StarExprs. + fieldType := field.Type + pkgName, typeName := func() (string, string) { + // Drill through any StarExprs. + for { + if starExpr, ok := fieldType.(*ast.StarExpr); ok { + fieldType = starExpr.X + continue + } + break + } + + // If the embedded type is in the same package, it's an Ident. + if ident, ok := fieldType.(*ast.Ident); ok { + return "", ident.Name + } + + if selectorExpr, ok := fieldType.(*ast.SelectorExpr); ok { + if pkgIdent, ok := selectorExpr.X.(*ast.Ident); ok { + return pkgIdent.Name, selectorExpr.Sel.Name + } + } + return "", "" + }() + + // If a typename wasn't found, skip it. + if typeName == "" { + continue + } + + // Find the import path for this type. + // If it was referenced without a package name, use the current package import path. + // Else, look up the package's import path by name. + var importPath string + if pkgName == "" { + importPath = pkgImportPath + } else { + var ok bool + if importPath, ok = imports[pkgName]; !ok { + utils.Logger.Error("Error: Failed to find import path for ", "package", pkgName, "type", typeName) + continue + } + } + + controllerSpec.EmbeddedTypes = append(controllerSpec.EmbeddedTypes, &model.EmbeddedTypeName{ + ImportPath: importPath, + StructName: typeName, + }) + } + + return append(specs, controllerSpec) +} + +// If decl is a Method declaration, it is summarized and added to the array +// underneath its receiver type. +// e.g. "Login" => {MethodSpec, MethodSpec, ..} +func appendAction(fset *token.FileSet, mm methodMap, decl ast.Decl, pkgImportPath, pkgName string, imports map[string]string) { + // Func declaration? + funcDecl, ok := decl.(*ast.FuncDecl) + if !ok { + return + } + + // Have a receiver? + if funcDecl.Recv == nil { + return + } + + // Is it public? + if !funcDecl.Name.IsExported() { + return + } + + // Does it return a Result? + if funcDecl.Type.Results == nil || len(funcDecl.Type.Results.List) != 1 { + return + } + selExpr, ok := funcDecl.Type.Results.List[0].Type.(*ast.SelectorExpr) + if !ok { + return + } + if selExpr.Sel.Name != "Result" { + return + } + if pkgIdent, ok := selExpr.X.(*ast.Ident); !ok || imports[pkgIdent.Name] != model.RevelImportPath { + return + } + + method := &model.MethodSpec{ + Name: funcDecl.Name.Name, + } + + // Add a description of the arguments to the method. + for _, field := range funcDecl.Type.Params.List { + for _, name := range field.Names { + var importPath string + typeExpr := model.NewTypeExprFromAst(pkgName, field.Type) + if !typeExpr.Valid { + utils.Logger.Warn("Warn: Didn't understand argument '%s' of action %s. Ignoring.", name, getFuncName(funcDecl)) + return // We didn't understand one of the args. Ignore this action. + } + // Local object + if typeExpr.PkgName == pkgName { + importPath = pkgImportPath + } else if typeExpr.PkgName != "" { + var ok bool + if importPath, ok = imports[typeExpr.PkgName]; !ok { + utils.Logger.Fatalf("Failed to find import for arg of type: %s , %s", typeExpr.PkgName, typeExpr.TypeName("")) + } + } + method.Args = append(method.Args, &model.MethodArg{ + Name: name.Name, + TypeExpr: typeExpr, + ImportPath: importPath, + }) + } + } + + // Add a description of the calls to Render from the method. + // Inspect every node (e.g. always return true). + method.RenderCalls = []*model.MethodCall{} + ast.Inspect(funcDecl.Body, func(node ast.Node) bool { + // Is it a function call? + callExpr, ok := node.(*ast.CallExpr) + if !ok { + return true + } + + // Is it calling (*Controller).Render? + selExpr, ok := callExpr.Fun.(*ast.SelectorExpr) + if !ok { + return true + } + + // The type of the receiver is not easily available, so just store every + // call to any method called Render. + if selExpr.Sel.Name != "Render" { + return true + } + + // Add this call's args to the renderArgs. + pos := fset.Position(callExpr.Lparen) + methodCall := &model.MethodCall{ + Line: pos.Line, + Names: []string{}, + } + for _, arg := range callExpr.Args { + argIdent, ok := arg.(*ast.Ident) + if !ok { + continue + } + methodCall.Names = append(methodCall.Names, argIdent.Name) + } + method.RenderCalls = append(method.RenderCalls, methodCall) + return true + }) + + var recvTypeName string + var recvType = funcDecl.Recv.List[0].Type + if recvStarType, ok := recvType.(*ast.StarExpr); ok { + recvTypeName = recvStarType.X.(*ast.Ident).Name + } else { + recvTypeName = recvType.(*ast.Ident).Name + } + + mm[recvTypeName] = append(mm[recvTypeName], method) +} + +// Combine the 2 source info models into one +func appendSourceInfo(srcInfo1, srcInfo2 *model.SourceInfo) *model.SourceInfo { + if srcInfo1 == nil { + return srcInfo2 + } + + srcInfo1.StructSpecs = append(srcInfo1.StructSpecs, srcInfo2.StructSpecs...) + srcInfo1.InitImportPaths = append(srcInfo1.InitImportPaths, srcInfo2.InitImportPaths...) + for k, v := range srcInfo2.ValidationKeys { + if _, ok := srcInfo1.ValidationKeys[k]; ok { + utils.Logger.Warn("Warn: Key conflict when scanning validation calls:", "key", k) + continue + } + srcInfo1.ValidationKeys[k] = v + } + return srcInfo1 +} diff --git a/parser/imports.go b/parser/imports.go new file mode 100644 index 0000000..d0edd15 --- /dev/null +++ b/parser/imports.go @@ -0,0 +1,82 @@ +package parser + +import ( + "github.com/revel/cmd/utils" + "go/ast" + "go/build" + "go/token" + "path/filepath" + "strings" +) + +// Add imports to the map from the source dir +func addImports(imports map[string]string, decl ast.Decl, srcDir string) { + genDecl, ok := decl.(*ast.GenDecl) + if !ok { + return + } + + if genDecl.Tok != token.IMPORT { + return + } + + for _, spec := range genDecl.Specs { + importSpec := spec.(*ast.ImportSpec) + var pkgAlias string + if importSpec.Name != nil { + pkgAlias = importSpec.Name.Name + if pkgAlias == "_" { + continue + } + } + quotedPath := importSpec.Path.Value // e.g. "\"sample/app/models\"" + fullPath := quotedPath[1 : len(quotedPath)-1] // Remove the quotes + + // If the package was not aliased (common case), we have to import it + // to see what the package name is. + // TODO: Can improve performance here a lot: + // 1. Do not import everything over and over again. Keep a cache. + // 2. Exempt the standard library; their directories always match the package name. + // 3. Can use build.FindOnly and then use parser.ParseDir with mode PackageClauseOnly + if pkgAlias == "" { + utils.Logger.Debug("Reading from build", "path", fullPath, "srcPath", srcDir, "gopath", build.Default.GOPATH) + pkg, err := build.Import(fullPath, srcDir, 0) + if err != nil { + // We expect this to happen for apps using reverse routing (since we + // have not yet generated the routes). Don't log that. + if !strings.HasSuffix(fullPath, "/app/routes") { + utils.Logger.Error("Could not find import:", "path", fullPath, "srcPath", srcDir, "error", err) + } + continue + } else { + utils.Logger.Debug("Found package in dir", "dir", pkg.Dir, "name", pkg.ImportPath) + } + pkgAlias = pkg.Name + } + + imports[pkgAlias] = fullPath + } +} + +// Returns a valid import string from the path +// using the build.Defaul.GOPATH to determine the root +func importPathFromPath(root string) string { + if vendorIdx := strings.Index(root, "/vendor/"); vendorIdx != -1 { + return filepath.ToSlash(root[vendorIdx+8:]) + } + for _, gopath := range filepath.SplitList(build.Default.GOPATH) { + srcPath := filepath.Join(gopath, "src") + if strings.HasPrefix(root, srcPath) { + return filepath.ToSlash(root[len(srcPath)+1:]) + } + } + + srcPath := filepath.Join(build.Default.GOROOT, "src", "pkg") + if strings.HasPrefix(root, srcPath) { + utils.Logger.Warn("Code path should be in GOPATH, but is in GOROOT:", "path", root) + return filepath.ToSlash(root[len(srcPath)+1:]) + } + + utils.Logger.Error("Unexpected! Code path is not in GOPATH:", "path", root) + return "" +} diff --git a/parser/reflect.go b/parser/reflect.go index e143e2c..98caa06 100644 --- a/parser/reflect.go +++ b/parser/reflect.go @@ -9,7 +9,6 @@ package parser import ( "go/ast" - "go/build" "go/parser" "go/scanner" "go/token" @@ -21,6 +20,13 @@ import ( "github.com/revel/cmd/utils" ) +// A container used to support the reflection package +type processContainer struct { + root, rootImportPath string // The paths + paths *model.RevelContainer // The Revel paths + srcInfo *model.SourceInfo // The source information container +} + // Maps a controller simple name (e.g. "Login") to the methods for which it is a // receiver. type methodMap map[string][]*model.MethodSpec @@ -28,130 +34,116 @@ type methodMap map[string][]*model.MethodSpec // ProcessSource parses the app controllers directory and // returns a list of the controller types found. // Otherwise CompileError if the parsing fails. -func ProcessSource(paths *model.RevelContainer) (*model.SourceInfo, *utils.Error) { - var ( - srcInfo *model.SourceInfo - compileError *utils.Error - ) - +func ProcessSource(paths *model.RevelContainer) (_ *model.SourceInfo, compileError error) { + pc := &processContainer{paths: paths} for _, root := range paths.CodePaths { rootImportPath := importPathFromPath(root) if rootImportPath == "" { utils.Logger.Info("Skipping empty code path", "path", root) continue } + pc.root, pc.rootImportPath = root, rootImportPath // Start walking the directory tree. - _ = utils.Walk(root, func(path string, info os.FileInfo, err error) error { - if err != nil { - utils.Logger.Error("Error scanning app source:", "error", err) - return nil - } - - if !info.IsDir() || info.Name() == "tmp" { - return nil - } - - // Get the import path of the package. - pkgImportPath := rootImportPath - if root != path { - pkgImportPath = rootImportPath + "/" + filepath.ToSlash(path[len(root)+1:]) - } - - // Parse files within the path. - var pkgs map[string]*ast.Package - fset := token.NewFileSet() - pkgs, err = parser.ParseDir(fset, path, func(f os.FileInfo) bool { - return !f.IsDir() && !strings.HasPrefix(f.Name(), ".") && strings.HasSuffix(f.Name(), ".go") - }, 0) - if err != nil { - if errList, ok := err.(scanner.ErrorList); ok { - var pos = errList[0].Pos - compileError = &utils.Error{ - SourceType: ".go source", - Title: "Go Compilation Error", - Path: pos.Filename, - Description: errList[0].Msg, - Line: pos.Line, - Column: pos.Column, - SourceLines: utils.MustReadLines(pos.Filename), - } - - errorLink := paths.Config.StringDefault("error.link", "") - - if errorLink != "" { - compileError.SetLink(errorLink) - } - - return compileError - } - - // This is exception, err already checked above. Here just a print - ast.Print(nil, err) - utils.Logger.Fatal("Failed to parse dir", "error", err) - } - - // Skip "main" packages. - delete(pkgs, "main") - - // Ignore packages that end with _test - // These cannot be included in source code that is not generated specifically as a test - for i := range pkgs { - if len(i) > 6 { - if string(i[len(i)-5:]) == "_test" { - delete(pkgs, i) - } - } - } - - // If there is no code in this directory, skip it. - if len(pkgs) == 0 { - return nil - } - - // There should be only one package in this directory. - if len(pkgs) > 1 { - for i := range pkgs { - println("Found package ", i) - } - utils.Logger.Fatal("Most unexpected! Multiple packages in a single directory:", "packages", pkgs) - } - - - var pkg *ast.Package - for _, v := range pkgs { - pkg = v - } - - if pkg != nil { - srcInfo = appendSourceInfo(srcInfo, processPackage(fset, pkgImportPath, path, pkg)) - } else { - utils.Logger.Info("Ignoring package, because it contained no packages", "path", path) - } - return nil - }) + compileError = utils.Walk(root, pc.processPath) } - return srcInfo, compileError + return pc.srcInfo, compileError } -func appendSourceInfo(srcInfo1, srcInfo2 *model.SourceInfo) *model.SourceInfo { - if srcInfo1 == nil { - return srcInfo2 +// Called during the "walk process" +func (pc *processContainer) processPath(path string, info os.FileInfo, err error) error { + if err != nil { + utils.Logger.Error("Error scanning app source:", "error", err) + return nil } - srcInfo1.StructSpecs = append(srcInfo1.StructSpecs, srcInfo2.StructSpecs...) - srcInfo1.InitImportPaths = append(srcInfo1.InitImportPaths, srcInfo2.InitImportPaths...) - for k, v := range srcInfo2.ValidationKeys { - if _, ok := srcInfo1.ValidationKeys[k]; ok { - utils.Logger.Warn("Warn: Key conflict when scanning validation calls:", "key", k) - continue + if !info.IsDir() || info.Name() == "tmp" { + return nil + } + + // Get the import path of the package. + pkgImportPath := pc.rootImportPath + if pc.root != path { + pkgImportPath = pc.rootImportPath + "/" + filepath.ToSlash(path[len(pc.root)+1:]) + } + + // Parse files within the path. + var pkgs map[string]*ast.Package + fset := token.NewFileSet() + pkgs, err = parser.ParseDir( + fset, + path, + func(f os.FileInfo) bool { + return !f.IsDir() && !strings.HasPrefix(f.Name(), ".") && strings.HasSuffix(f.Name(), ".go") + }, + 0) + + if err != nil { + if errList, ok := err.(scanner.ErrorList); ok { + var pos = errList[0].Pos + newError := &utils.Error{ + SourceType: ".go source", + Title: "Go Compilation Error", + Path: pos.Filename, + Description: errList[0].Msg, + Line: pos.Line, + Column: pos.Column, + SourceLines: utils.MustReadLines(pos.Filename), + } + + errorLink := pc.paths.Config.StringDefault("error.link", "") + if errorLink != "" { + newError.SetLink(errorLink) + } + return newError } - srcInfo1.ValidationKeys[k] = v + + // This is exception, err already checked above. Here just a print + ast.Print(nil, err) + utils.Logger.Fatal("Failed to parse dir", "error", err) } - return srcInfo1 + + // Skip "main" packages. + delete(pkgs, "main") + + // Ignore packages that end with _test + // These cannot be included in source code that is not generated specifically as a test + for i := range pkgs { + if len(i) > 6 { + if string(i[len(i)-5:]) == "_test" { + delete(pkgs, i) + } + } + } + + // If there is no code in this directory, skip it. + if len(pkgs) == 0 { + return nil + } + + // There should be only one package in this directory. + if len(pkgs) > 1 { + for i := range pkgs { + println("Found package ", i) + } + utils.Logger.Fatal("Most unexpected! Multiple packages in a single directory:", "packages", pkgs) + } + + var pkg *ast.Package + for _, v := range pkgs { + pkg = v + } + + if pkg != nil { + pc.srcInfo = appendSourceInfo(pc.srcInfo, processPackage(fset, pkgImportPath, path, pkg)) + } else { + utils.Logger.Info("Ignoring package, because it contained no packages", "path", path) + } + return nil } +// Process a single package within a file func processPackage(fset *token.FileSet, pkgImportPath, pkgPath string, pkg *ast.Package) *model.SourceInfo { var ( structSpecs []*model.TypeInfo @@ -228,355 +220,6 @@ func getFuncName(funcDecl *ast.FuncDecl) string { return prefix + funcDecl.Name.Name } -func addImports(imports map[string]string, decl ast.Decl, srcDir string) { - genDecl, ok := decl.(*ast.GenDecl) - if !ok { - return - } - - if genDecl.Tok != token.IMPORT { - return - } - - for _, spec := range genDecl.Specs { - importSpec := spec.(*ast.ImportSpec) - var pkgAlias string - if importSpec.Name != nil { - pkgAlias = importSpec.Name.Name - if pkgAlias == "_" { - continue - } - } - quotedPath := importSpec.Path.Value // e.g. "\"sample/app/models\"" - fullPath := quotedPath[1 : len(quotedPath)-1] // Remove the quotes - - // If the package was not aliased (common case), we have to import it - // to see what the package name is. - // TODO: Can improve performance here a lot: - // 1. Do not import everything over and over again. Keep a cache. - // 2. Exempt the standard library; their directories always match the package name. - // 3. Can use build.FindOnly and then use parser.ParseDir with mode PackageClauseOnly - if pkgAlias == "" { - pkg, err := build.Import(fullPath, srcDir, 0) - if err != nil { - // We expect this to happen for apps using reverse routing (since we - // have not yet generated the routes). Don't log that. - if !strings.HasSuffix(fullPath, "/app/routes") { - utils.Logger.Info("Debug: Could not find import:", "path", fullPath) - } - continue - } - pkgAlias = pkg.Name - } - - imports[pkgAlias] = fullPath - } -} - -// If this Decl is a struct type definition, it is summarized and added to specs. -// Else, specs is returned unchanged. -func appendStruct(fileName string, specs []*model.TypeInfo, pkgImportPath string, pkg *ast.Package, decl ast.Decl, imports map[string]string, fset *token.FileSet) []*model.TypeInfo { - // Filter out non-Struct type declarations. - spec, found := getStructTypeDecl(decl, fset) - if !found { - return specs - } - - structType := spec.Type.(*ast.StructType) - - // At this point we know it's a type declaration for a struct. - // Fill in the rest of the info by diving into the fields. - // Add it provisionally to the Controller list -- it's later filtered using field info. - controllerSpec := &model.TypeInfo{ - StructName: spec.Name.Name, - ImportPath: pkgImportPath, - PackageName: pkg.Name, - } - - for _, field := range structType.Fields.List { - // If field.Names is set, it's not an embedded type. - if field.Names != nil { - continue - } - - // A direct "sub-type" has an ast.Field as either: - // Ident { "AppController" } - // SelectorExpr { "rev", "Controller" } - // Additionally, that can be wrapped by StarExprs. - fieldType := field.Type - pkgName, typeName := func() (string, string) { - // Drill through any StarExprs. - for { - if starExpr, ok := fieldType.(*ast.StarExpr); ok { - fieldType = starExpr.X - continue - } - break - } - - // If the embedded type is in the same package, it's an Ident. - if ident, ok := fieldType.(*ast.Ident); ok { - return "", ident.Name - } - - if selectorExpr, ok := fieldType.(*ast.SelectorExpr); ok { - if pkgIdent, ok := selectorExpr.X.(*ast.Ident); ok { - return pkgIdent.Name, selectorExpr.Sel.Name - } - } - return "", "" - }() - - // If a typename wasn't found, skip it. - if typeName == "" { - continue - } - - // Find the import path for this type. - // If it was referenced without a package name, use the current package import path. - // Else, look up the package's import path by name. - var importPath string - if pkgName == "" { - importPath = pkgImportPath - } else { - var ok bool - if importPath, ok = imports[pkgName]; !ok { - utils.Logger.Error("Error: Failed to find import path for ", "package", pkgName, "type", typeName) - continue - } - } - - controllerSpec.EmbeddedTypes = append(controllerSpec.EmbeddedTypes, &model.EmbeddedTypeName{ - ImportPath: importPath, - StructName: typeName, - }) - } - - return append(specs, controllerSpec) -} - -// If decl is a Method declaration, it is summarized and added to the array -// underneath its receiver type. -// e.g. "Login" => {MethodSpec, MethodSpec, ..} -func appendAction(fset *token.FileSet, mm methodMap, decl ast.Decl, pkgImportPath, pkgName string, imports map[string]string) { - // Func declaration? - funcDecl, ok := decl.(*ast.FuncDecl) - if !ok { - return - } - - // Have a receiver? - if funcDecl.Recv == nil { - return - } - - // Is it public? - if !funcDecl.Name.IsExported() { - return - } - - // Does it return a Result? - if funcDecl.Type.Results == nil || len(funcDecl.Type.Results.List) != 1 { - return - } - selExpr, ok := funcDecl.Type.Results.List[0].Type.(*ast.SelectorExpr) - if !ok { - return - } - if selExpr.Sel.Name != "Result" { - return - } - if pkgIdent, ok := selExpr.X.(*ast.Ident); !ok || imports[pkgIdent.Name] != model.RevelImportPath { - return - } - - method := &model.MethodSpec{ - Name: funcDecl.Name.Name, - } - - // Add a description of the arguments to the method. - for _, field := range funcDecl.Type.Params.List { - for _, name := range field.Names { - var importPath string - typeExpr := model.NewTypeExprFromAst(pkgName, field.Type) - if !typeExpr.Valid { - utils.Logger.Warn("Warn: Didn't understand argument '%s' of action %s. Ignoring.", name, getFuncName(funcDecl)) - return // We didn't understand one of the args. Ignore this action. - } - // Local object - if typeExpr.PkgName == pkgName { - importPath = pkgImportPath - } else if typeExpr.PkgName != "" { - var ok bool - if importPath, ok = imports[typeExpr.PkgName]; !ok { - utils.Logger.Fatalf("Failed to find import for arg of type: %s , %s", typeExpr.PkgName, typeExpr.TypeName("")) - } - } - method.Args = append(method.Args, &model.MethodArg{ - Name: name.Name, - TypeExpr: typeExpr, - ImportPath: importPath, - }) - } - } - - // Add a description of the calls to Render from the method. - // Inspect every node (e.g. always return true). - method.RenderCalls = []*model.MethodCall{} - ast.Inspect(funcDecl.Body, func(node ast.Node) bool { - // Is it a function call? - callExpr, ok := node.(*ast.CallExpr) - if !ok { - return true - } - - // Is it calling (*Controller).Render? - selExpr, ok := callExpr.Fun.(*ast.SelectorExpr) - if !ok { - return true - } - - // The type of the receiver is not easily available, so just store every - // call to any method called Render. - if selExpr.Sel.Name != "Render" { - return true - } - - // Add this call's args to the renderArgs. - pos := fset.Position(callExpr.Lparen) - methodCall := &model.MethodCall{ - Line: pos.Line, - Names: []string{}, - } - for _, arg := range callExpr.Args { - argIdent, ok := arg.(*ast.Ident) - if !ok { - continue - } - methodCall.Names = append(methodCall.Names, argIdent.Name) - } - method.RenderCalls = append(method.RenderCalls, methodCall) - return true - }) - - var recvTypeName string - var recvType = funcDecl.Recv.List[0].Type - if recvStarType, ok := recvType.(*ast.StarExpr); ok { - recvTypeName = recvStarType.X.(*ast.Ident).Name - } else { - recvTypeName = recvType.(*ast.Ident).Name - } - - mm[recvTypeName] = append(mm[recvTypeName], method) -} - -// Scan app source code for calls to X.Y(), where X is of type *Validation. -// -// Recognize these scenarios: -// - "Y" = "Validation" and is a member of the receiver. -// (The common case for inline validation) -// - "X" is passed in to the func as a parameter. -// (For structs implementing Validated) -// -// The line number to which a validation call is attributed is that of the -// surrounding ExprStmt. This is so that it matches what runtime.Callers() -// reports. -// -// The end result is that we can set the default validation key for each call to -// be the same as the local variable. -func GetValidationKeys(fname string, fset *token.FileSet, funcDecl *ast.FuncDecl, imports map[string]string) map[int]string { - var ( - lineKeys = make(map[int]string) - - // Check the func parameters and the receiver's members for the *revel.Validation type. - validationParam = getValidationParameter(funcDecl, imports) - ) - - ast.Inspect(funcDecl.Body, func(node ast.Node) bool { - // e.g. c.Validation.Required(arg) or v.Required(arg) - callExpr, ok := node.(*ast.CallExpr) - if !ok { - return true - } - - // e.g. c.Validation.Required or v.Required - funcSelector, ok := callExpr.Fun.(*ast.SelectorExpr) - if !ok { - return true - } - - switch x := funcSelector.X.(type) { - case *ast.SelectorExpr: // e.g. c.Validation - if x.Sel.Name != "Validation" { - return true - } - - case *ast.Ident: // e.g. v - if validationParam == nil || x.Obj != validationParam { - return true - } - - default: - return true - } - - if len(callExpr.Args) == 0 { - return true - } - - // Given the validation expression, extract the key. - key := callExpr.Args[0] - switch expr := key.(type) { - case *ast.BinaryExpr: - // If the argument is a binary expression, take the first expression. - // (e.g. c.Validation.Required(myName != "")) - key = expr.X - case *ast.UnaryExpr: - // If the argument is a unary expression, drill in. - // (e.g. c.Validation.Required(!myBool) - key = expr.X - case *ast.BasicLit: - // If it's a literal, skip it. - return true - } - - if typeExpr := model.NewTypeExprFromAst("", key); typeExpr.Valid { - lineKeys[fset.Position(callExpr.End()).Line] = typeExpr.TypeName("") - } else { - utils.Logger.Error("Error: Failed to generate key for field validation. Make sure the field name is valid.", "file", fname, - "line", fset.Position(callExpr.End()).Line, "function", funcDecl.Name.String()) - } - return true - }) - - return lineKeys -} - -// Check to see if there is a *revel.Validation as an argument. -func getValidationParameter(funcDecl *ast.FuncDecl, imports map[string]string) *ast.Object { - for _, field := range funcDecl.Type.Params.List { - starExpr, ok := field.Type.(*ast.StarExpr) // e.g. *revel.Validation - if !ok { - continue - } - - selExpr, ok := starExpr.X.(*ast.SelectorExpr) // e.g. revel.Validation - if !ok { - continue - } - - xIdent, ok := selExpr.X.(*ast.Ident) // e.g. rev - if !ok { - continue - } - - if selExpr.Sel.Name == "Validation" && imports[xIdent.Name] == model.RevelImportPath { - return field.Names[0].Obj - } - } - return nil -} - // getStructTypeDecl checks if the given decl is a type declaration for a // struct. If so, the TypeSpec is returned. func getStructTypeDecl(decl ast.Decl, fset *token.FileSet) (spec *ast.TypeSpec, found bool) { @@ -599,24 +242,3 @@ func getStructTypeDecl(decl ast.Decl, fset *token.FileSet) (spec *ast.TypeSpec, return } - -func importPathFromPath(root string) string { - if vendorIdx := strings.Index(root, "/vendor/"); vendorIdx != -1 { - return filepath.ToSlash(root[vendorIdx+8:]) - } - for _, gopath := range filepath.SplitList(build.Default.GOPATH) { - srcPath := filepath.Join(gopath, "src") - if strings.HasPrefix(root, srcPath) { - return filepath.ToSlash(root[len(srcPath)+1:]) - } - } - - srcPath := filepath.Join(build.Default.GOROOT, "src", "pkg") - if strings.HasPrefix(root, srcPath) { - utils.Logger.Warn("Code path should be in GOPATH, but is in GOROOT:", "path", root) - return filepath.ToSlash(root[len(srcPath)+1:]) - } - - utils.Logger.Error("Unexpected! Code path is not in GOPATH:", "path", root) - return "" -} diff --git a/parser/validation.go b/parser/validation.go new file mode 100644 index 0000000..018fdda --- /dev/null +++ b/parser/validation.go @@ -0,0 +1,115 @@ +package parser + +import ( + "github.com/revel/cmd/model" + "github.com/revel/cmd/utils" + "go/ast" + "go/token" +) + +// Scan app source code for calls to X.Y(), where X is of type *Validation. +// +// Recognize these scenarios: +// - "Y" = "Validation" and is a member of the receiver. +// (The common case for inline validation) +// - "X" is passed in to the func as a parameter. +// (For structs implementing Validated) +// +// The line number to which a validation call is attributed is that of the +// surrounding ExprStmt. This is so that it matches what runtime.Callers() +// reports. +// +// The end result is that we can set the default validation key for each call to +// be the same as the local variable. +func GetValidationKeys(fname string, fset *token.FileSet, funcDecl *ast.FuncDecl, imports map[string]string) map[int]string { + var ( + lineKeys = make(map[int]string) + + // Check the func parameters and the receiver's members for the *revel.Validation type. + validationParam = getValidationParameter(funcDecl, imports) + ) + + ast.Inspect(funcDecl.Body, func(node ast.Node) bool { + // e.g. c.Validation.Required(arg) or v.Required(arg) + callExpr, ok := node.(*ast.CallExpr) + if !ok { + return true + } + + // e.g. c.Validation.Required or v.Required + funcSelector, ok := callExpr.Fun.(*ast.SelectorExpr) + if !ok { + return true + } + + switch x := funcSelector.X.(type) { + case *ast.SelectorExpr: // e.g. c.Validation + if x.Sel.Name != "Validation" { + return true + } + + case *ast.Ident: // e.g. v + if validationParam == nil || x.Obj != validationParam { + return true + } + + default: + return true + } + + if len(callExpr.Args) == 0 { + return true + } + + // Given the validation expression, extract the key. + key := callExpr.Args[0] + switch expr := key.(type) { + case *ast.BinaryExpr: + // If the argument is a binary expression, take the first expression. + // (e.g. c.Validation.Required(myName != "")) + key = expr.X + case *ast.UnaryExpr: + // If the argument is a unary expression, drill in. + // (e.g. c.Validation.Required(!myBool) + key = expr.X + case *ast.BasicLit: + // If it's a literal, skip it. + return true + } + + if typeExpr := model.NewTypeExprFromAst("", key); typeExpr.Valid { + lineKeys[fset.Position(callExpr.End()).Line] = typeExpr.TypeName("") + } else { + utils.Logger.Error("Error: Failed to generate key for field validation. Make sure the field name is valid.", "file", fname, + "line", fset.Position(callExpr.End()).Line, "function", funcDecl.Name.String()) + } + return true + }) + + return lineKeys +} + +// Check to see if there is a *revel.Validation as an argument. +func getValidationParameter(funcDecl *ast.FuncDecl, imports map[string]string) *ast.Object { + for _, field := range funcDecl.Type.Params.List { + starExpr, ok := field.Type.(*ast.StarExpr) // e.g. *revel.Validation + if !ok { + continue + } + + selExpr, ok := starExpr.X.(*ast.SelectorExpr) // e.g. revel.Validation + if !ok { + continue + } + + xIdent, ok := selExpr.X.(*ast.Ident) // e.g. rev + if !ok { + continue + } + + if selExpr.Sel.Name == "Validation" && imports[xIdent.Name] == model.RevelImportPath { + return field.Names[0].Obj + } + } + return nil +} diff --git a/revel/build.go b/revel/build.go index c9a7387..e7e8126 100644 --- a/revel/build.go +++ b/revel/build.go @@ -17,7 +17,7 @@ import ( ) var cmdBuild = &Command{ - UsageLine: "build -i [import path] -t [target path] -r [run mode]", + UsageLine: "revel build [-r [run mode]] [import path] [target path] ", Short: "build a Revel application (e.g. for deployment)", Long: ` Build the Revel web application named by the given import path. @@ -25,7 +25,7 @@ This allows it to be deployed and run on a machine that lacks a Go installation. For example: - revel build -a github.com/revel/examples/chat -t /tmp/chat + revel build github.com/revel/examples/chat /tmp/chat `, } @@ -38,10 +38,12 @@ func init() { // The update config updates the configuration command so that it can run func updateBuildConfig(c *model.CommandConfig, args []string) bool { c.Index = model.BUILD + // If arguments were passed in then there must be two if len(args) < 2 { fmt.Fprintf(os.Stderr, "%s\n%s", cmdBuild.UsageLine, cmdBuild.Long) return false } + c.Build.ImportPath = args[0] c.Build.TargetPath = args[1] if len(args) > 2 { @@ -51,75 +53,101 @@ func updateBuildConfig(c *model.CommandConfig, args []string) bool { } // The main entry point to build application from command line -func buildApp(c *model.CommandConfig) { +func buildApp(c *model.CommandConfig) (err error) { appImportPath, destPath, mode := c.ImportPath, c.Build.TargetPath, DefaultRunMode if len(c.Build.Mode) > 0 { mode = c.Build.Mode } // Convert target to absolute path - destPath, _ = filepath.Abs(destPath) + c.Build.TargetPath, _ = filepath.Abs(destPath) + c.Build.Mode = mode - revel_paths := model.NewRevelPaths(mode, appImportPath, "", model.DoNothingRevelCallback) - - // First, verify that it is either already empty or looks like a previous - // build (to avoid clobbering anything) - if utils.Exists(destPath) && !utils.Empty(destPath) && !utils.Exists(filepath.Join(destPath, "run.sh")) { - utils.Logger.Errorf("Abort: %s exists and does not look like a build directory.", destPath) + revel_paths, err := model.NewRevelPaths(mode, appImportPath, "", model.NewWrappedRevelCallback(nil, c.PackageResolver)) + if err != nil { return } - if err := os.RemoveAll(destPath); err != nil && !os.IsNotExist(err) { - utils.Logger.Error("Remove all error", "error", err) - return - } + buildSafetyCheck(destPath) - if err := os.MkdirAll(destPath, 0777); err != nil { - utils.Logger.Error("makedir error", "error", err) - return + // Ensure the application can be built, this generates the main file + app, err := harness.Build(c, revel_paths) + if err != nil { + return err } - - app, reverr := harness.Build(c, revel_paths) - if reverr != nil { - utils.Logger.Error("Failed to build application", "error", reverr) - return - } - + // Copy files // Included are: // - run scripts // - binary // - revel // - app + packageFolders, err := buildCopyFiles(c, app, revel_paths) + if err != nil { + return + } + err = buildCopyModules(c, revel_paths, packageFolders) + if err != nil { + return + } + err = buildWriteScripts(c, app) + if err != nil { + return + } + return +} + +// Copy the files to the target +func buildCopyFiles(c *model.CommandConfig, app *harness.App, revel_paths *model.RevelContainer) (packageFolders []string, err error) { + appImportPath, destPath := c.ImportPath, c.Build.TargetPath + // Revel and the app are in a directory structure mirroring import path srcPath := filepath.Join(destPath, "src") destBinaryPath := filepath.Join(destPath, filepath.Base(app.BinaryPath)) tmpRevelPath := filepath.Join(srcPath, filepath.FromSlash(model.RevelImportPath)) - utils.MustCopyFile(destBinaryPath, app.BinaryPath) + if err = utils.CopyFile(destBinaryPath, app.BinaryPath); err != nil { + return + } utils.MustChmod(destBinaryPath, 0755) // Copy the templates from the revel - _ = utils.MustCopyDir(filepath.Join(tmpRevelPath, "conf"), filepath.Join(revel_paths.RevelPath, "conf"), nil) - _ = utils.MustCopyDir(filepath.Join(tmpRevelPath, "templates"), filepath.Join(revel_paths.RevelPath, "templates"), nil) + if err = utils.CopyDir(filepath.Join(tmpRevelPath, "conf"), filepath.Join(revel_paths.RevelPath, "conf"), nil); err != nil { + return + } + if err = utils.CopyDir(filepath.Join(tmpRevelPath, "templates"), filepath.Join(revel_paths.RevelPath, "templates"), nil); err != nil { + return + } // Get the folders to be packaged - packageFolders := strings.Split(revel_paths.Config.StringDefault("package.folders", "conf,public,app/views"), ",") - for i,p:=range packageFolders { + packageFolders = strings.Split(revel_paths.Config.StringDefault("package.folders", "conf,public,app/views"), ",") + for i, p := range packageFolders { // Clean spaces, reformat slash to filesystem - packageFolders[i]=filepath.FromSlash(strings.TrimSpace(p)) + packageFolders[i] = filepath.FromSlash(strings.TrimSpace(p)) } if c.Build.CopySource { - _ = utils.MustCopyDir(filepath.Join(srcPath, filepath.FromSlash(appImportPath)), revel_paths.BasePath, nil) + err = utils.CopyDir(filepath.Join(srcPath, filepath.FromSlash(appImportPath)), revel_paths.BasePath, nil) + if err != nil { + return + } } else { for _, folder := range packageFolders { - _ = utils.MustCopyDir( + err = utils.CopyDir( filepath.Join(srcPath, filepath.FromSlash(appImportPath), folder), filepath.Join(revel_paths.BasePath, folder), nil) + if err != nil { + return + } } } + return +} + +// Based on the section copy over the build modules +func buildCopyModules(c *model.CommandConfig, revel_paths *model.RevelContainer, packageFolders []string) (err error) { + destPath := filepath.Join(c.Build.TargetPath, "src") // Find all the modules used and copy them over. config := revel_paths.Config.Raw() modulePaths := make(map[string]string) // import path => filesystem path @@ -151,40 +179,76 @@ func buildApp(c *model.CommandConfig) { // Copy the the paths for each of the modules for importPath, fsPath := range modulePaths { - utils.Logger.Info("Copy files ", "to", filepath.Join(srcPath, importPath), "from", fsPath) + utils.Logger.Info("Copy files ", "to", filepath.Join(destPath, importPath), "from", fsPath) if c.Build.CopySource { - _ = utils.MustCopyDir(filepath.Join(srcPath, importPath), fsPath, nil) + err = utils.CopyDir(filepath.Join(destPath, importPath), fsPath, nil) + if err != nil { + return + } } else { for _, folder := range packageFolders { - _ = utils.MustCopyDir( - filepath.Join(srcPath, importPath, folder), + err = utils.CopyDir( + filepath.Join(destPath, importPath, folder), filepath.Join(fsPath, folder), nil) + if err != nil { + return + } } } - // } + return +} + +// Write the run scripts for the build +func buildWriteScripts(c *model.CommandConfig, app *harness.App) (err error) { tmplData := map[string]interface{}{ "BinName": filepath.Base(app.BinaryPath), - "ImportPath": appImportPath, - "Mode": mode, + "ImportPath": c.Build.ImportPath, + "Mode": c.Build.Mode, } - utils.MustGenerateTemplate( - filepath.Join(destPath, "run.sh"), + err = utils.GenerateTemplate( + filepath.Join(c.Build.TargetPath, "run.sh"), PACKAGE_RUN_SH, tmplData, ) - utils.MustChmod(filepath.Join(destPath, "run.sh"), 0755) - utils.MustGenerateTemplate( - filepath.Join(destPath, "run.bat"), + if err != nil { + return + } + utils.MustChmod(filepath.Join(c.Build.TargetPath, "run.sh"), 0755) + err = utils.GenerateTemplate( + filepath.Join(c.Build.TargetPath, "run.bat"), PACKAGE_RUN_BAT, tmplData, ) + if err != nil { + return + } - fmt.Println("Your application has been built in:", destPath) + fmt.Println("Your application has been built in:", c.Build.TargetPath) + return +} + +// Checks to see if the target folder exists and can be created +func buildSafetyCheck(destPath string) error { + + // First, verify that it is either already empty or looks like a previous + // build (to avoid clobbering anything) + if utils.Exists(destPath) && !utils.Empty(destPath) && !utils.Exists(filepath.Join(destPath, "run.sh")) { + return utils.NewBuildError("Abort: %s exists and does not look like a build directory.", "path", destPath) + } + + if err := os.RemoveAll(destPath); err != nil && !os.IsNotExist(err) { + return utils.NewBuildIfError(err, "Remove all error", "path", destPath) + } + + if err := os.MkdirAll(destPath, 0777); err != nil { + return utils.NewBuildIfError(err, "MkDir all error", "path", destPath) + } + return nil } const PACKAGE_RUN_SH = `#!/bin/sh diff --git a/revel/build_test.go b/revel/build_test.go new file mode 100644 index 0000000..b139066 --- /dev/null +++ b/revel/build_test.go @@ -0,0 +1,34 @@ +package main_test + +import ( + "github.com/revel/cmd/model" + "github.com/revel/cmd/revel" + "github.com/revel/cmd/utils" + "github.com/stretchr/testify/assert" + "os" + "path/filepath" + "testing" +) + +// test the commands +func TestBuild(t *testing.T) { + a := assert.New(t) + gopath := setup("revel-test-build", a) + + t.Run("Build", func(t *testing.T) { + a := assert.New(t) + c := newApp("build-test", model.NEW, nil, a) + main.Commands[model.NEW].RunWith(c) + c.Index = model.BUILD + c.Build.TargetPath = filepath.Join(gopath, "build-test", "target") + c.Build.ImportPath = c.ImportPath + a.Nil(main.Commands[model.BUILD].RunWith(c), "Failed to run build-test") + a.True(utils.Exists(filepath.Join(gopath, "build-test", "target"))) + }) + + if !t.Failed() { + if err := os.RemoveAll(gopath); err != nil { + a.Fail("Failed to remove test path") + } + } +} diff --git a/revel/clean.go b/revel/clean.go index a4aa9e1..6a210f3 100644 --- a/revel/clean.go +++ b/revel/clean.go @@ -14,14 +14,14 @@ import ( ) var cmdClean = &Command{ - UsageLine: "clean -i [import path]", + UsageLine: "clean [import path]", Short: "clean a Revel application's temp files", Long: ` Clean the Revel web application named by the given import path. For example: - revel clean -a github.com/revel/examples/chat + revel clean github.com/revel/examples/chat It removes the app/tmp and app/routes directory. @@ -46,7 +46,7 @@ func updateCleanConfig(c *model.CommandConfig, args []string) bool { } // Clean the source directory of generated files -func cleanApp(c *model.CommandConfig) { +func cleanApp(c *model.CommandConfig) (err error) { appPkg, err := build.Import(c.ImportPath, "", build.FindOnly) if err != nil { utils.Logger.Fatal("Abort: Failed to find import path:", "error", err) @@ -65,4 +65,5 @@ func cleanApp(c *model.CommandConfig) { return } } + return err } diff --git a/revel/clean_test.go b/revel/clean_test.go new file mode 100644 index 0000000..50dae6d --- /dev/null +++ b/revel/clean_test.go @@ -0,0 +1,37 @@ +package main_test + +import ( + "github.com/revel/cmd/model" + "github.com/revel/cmd/revel" + "github.com/revel/cmd/utils" + "github.com/stretchr/testify/assert" + "os" + "path/filepath" + "testing" +) + +// test the commands +func TestClean(t *testing.T) { + a := assert.New(t) + gopath := setup("revel-test-clean", a) + + + t.Run("Clean", func(t *testing.T) { + a := assert.New(t) + c := newApp("clean-test", model.NEW, nil, a) + main.Commands[model.NEW].RunWith(c) + c.Index = model.TEST + main.Commands[model.TEST].RunWith(c) + a.True(utils.Exists(filepath.Join(gopath, "src", "clean-test", "app", "tmp", "main.go")), + "Missing main from path "+filepath.Join(gopath, "src", "clean-test", "app", "tmp", "main.go")) + c.Clean.ImportPath = c.ImportPath + a.Nil(main.Commands[model.CLEAN].RunWith(c), "Failed to run clean-test") + a.False(utils.Exists(filepath.Join(gopath, "src", "clean-test", "app", "tmp", "main.go")), + "Did not remove main from path "+filepath.Join(gopath, "src", "clean-test", "app", "tmp", "main.go")) + }) + if !t.Failed() { + if err := os.RemoveAll(gopath); err != nil { + a.Fail("Failed to remove test path") + } + } +} diff --git a/revel/command_test.go b/revel/command_test.go new file mode 100644 index 0000000..cf1dcf8 --- /dev/null +++ b/revel/command_test.go @@ -0,0 +1,74 @@ +package main_test + +import ( + "github.com/revel/cmd/logger" + "github.com/revel/cmd/model" + "github.com/revel/cmd/utils" + "github.com/stretchr/testify/assert" + "go/build" + "os" + "path/filepath" +) + +// Test that the event handler can be attached and it dispatches the event received +func setup(suffix string, a *assert.Assertions) (string) { + temp := os.TempDir() + wd, _ := os.Getwd() + utils.InitLogger(wd, logger.LvlInfo) + gopath := filepath.Join(temp, "revel-test",suffix) + if utils.Exists(gopath) { + utils.Logger.Info("Removing test path", "path", gopath) + if err := os.RemoveAll(gopath); err != nil { + a.Fail("Failed to remove test path") + } + } + err := os.MkdirAll(gopath, os.ModePerm) + a.Nil(err, "Failed to create gopath "+gopath) + + // So this is the issue, on the mac when folders are created in a temp folder they are returned like + // /var/folders/nz/vv4_9tw56nv9k3tkvyszvwg80000gn/T/revel-test/revel-test-build + // But if you change into that directory and read the current folder it is + // /private/var/folders/nz/vv4_9tw56nv9k3tkvyszvwg80000gn/T/revel-test/revel-test-build + // So to make this work on darwin this code was added + os.Chdir(gopath) + newwd, _ := os.Getwd() + gopath = newwd + defaultBuild := build.Default + defaultBuild.GOPATH = gopath + build.Default = defaultBuild + utils.Logger.Info("Setup stats", "original wd", wd, "new wd", newwd, "gopath",gopath, "gopath exists", utils.DirExists(gopath), "wd exists", utils.DirExists(newwd)) + + return gopath +} + +// Create a new app for the name +func newApp(name string, command model.COMMAND, precall func(c *model.CommandConfig), a *assert.Assertions) *model.CommandConfig { + c := &model.CommandConfig{} + switch command { + case model.NEW: + c.New.ImportPath = name + case model.BUILD: + c.Build.ImportPath = name + case model.TEST: + c.Test.ImportPath = name + case model.PACKAGE: + c.Package.ImportPath = name + case model.VERSION: + c.Version.ImportPath = name + case model.CLEAN: + c.Clean.ImportPath = name + default: + a.Fail("Unknown command ", command) + } + + c.Index = command + if precall != nil { + precall(c) + } + if !c.UpdateImportPath() { + a.Fail("Unable to update import path") + } + c.InitGoPaths() + c.InitPackageResolver() + return c +} diff --git a/revel/new.go b/revel/new.go index 15116fd..96e4fdd 100644 --- a/revel/new.go +++ b/revel/new.go @@ -5,7 +5,6 @@ package main import ( - "bytes" "fmt" "go/build" "math/rand" @@ -16,6 +15,7 @@ import ( "github.com/revel/cmd/model" "github.com/revel/cmd/utils" + "net/url" ) var cmdNew = &Command{ @@ -51,83 +51,105 @@ func updateNewConfig(c *model.CommandConfig, args []string) bool { return false } c.New.ImportPath = args[0] - if len(args)>1 { - c.New.Skeleton = args[1] + if len(args) > 1 { + c.New.SkeletonPath = args[1] } return true } // Call to create a new application -func newApp(c *model.CommandConfig) { - // check for proper args by count - c.SkeletonPath = c.New.Skeleton - - // Check for an existing folder so we dont clober it - c.AppPath = filepath.Join(c.SrcRoot, filepath.FromSlash(c.ImportPath)) - _, err := build.Import(c.ImportPath, "", build.FindOnly) - if err==nil || !utils.Empty(c.AppPath) { - utils.Logger.Fatal("Abort: Import path already exists.","path", c.ImportPath) +func newApp(c *model.CommandConfig) (err error) { + // Check for an existing folder so we don't clobber it + _, err = build.Import(c.ImportPath, "", build.FindOnly) + if err == nil || !utils.Empty(c.AppPath) { + return utils.NewBuildError("Abort: Import path already exists.", "path", c.ImportPath) + } + if err := os.MkdirAll(c.AppPath, os.ModePerm); err != nil { + return utils.NewBuildError("Abort: Unable to create app path.", "path", c.AppPath) } if c.New.Vendored { - depPath, err := exec.LookPath("dep") - if err != nil { - // Do not halt build unless a new package needs to be imported - utils.Logger.Fatal("New: `dep` executable not found in PATH, but vendor folder requested." + - "You must install the dep tool before creating a vendored project. " + - "You can install the `dep` tool by doing a `go get -u github.com/golang/dep/cmd/dep`") - } - vendorPath := filepath.Join(c.ImportPath,"vendor") - if !utils.DirExists(vendorPath) { - err := os.MkdirAll(vendorPath,os.ModePerm) - utils.PanicOnError(err, "Failed to create " + vendorPath) - } - // In order for dep to run there needs to be a source file in the folder - tempPath := filepath.Join(c.ImportPath,"tmp") - if !utils.DirExists(tempPath) { - err := os.MkdirAll(tempPath,os.ModePerm) - utils.PanicOnError(err, "Failed to create " + vendorPath) - err = utils.MustGenerateTemplate(filepath.Join(tempPath,"main.go"), NEW_MAIN_FILE, nil) - utils.PanicOnError(err, "Failed to create main file " + vendorPath) + utils.Logger.Info("Creating a new vendor app") + vendorPath := filepath.Join(c.AppPath, "vendor") + if !utils.DirExists(vendorPath) { + + if err := os.MkdirAll(vendorPath, os.ModePerm); err != nil { + return utils.NewBuildError("Failed to create "+vendorPath, "error", err) + } } - packageFile := filepath.Join(c.ImportPath,"Gopkg.toml") + + // In order for dep to run there needs to be a source file in the folder + tempPath := filepath.Join(c.AppPath, "tmp") + utils.Logger.Info("Checking for temp folder for source code", "path", tempPath) + if !utils.DirExists(tempPath) { + if err := os.MkdirAll(tempPath, os.ModePerm); err != nil { + return utils.NewBuildIfError(err, "Failed to create "+vendorPath) + } + + if err = utils.GenerateTemplate(filepath.Join(tempPath, "main.go"), NEW_MAIN_FILE, nil); err != nil { + return utils.NewBuildIfError(err, "Failed to create main file "+vendorPath) + } + } + + // Create a package template file if it does not exist + packageFile := filepath.Join(c.AppPath, "Gopkg.toml") + utils.Logger.Info("Checking for Gopkg.toml", "path", packageFile) if !utils.Exists(packageFile) { - utils.MustGenerateTemplate(packageFile,VENDOR_GOPKG,nil) + utils.Logger.Info("Generating Gopkg.toml", "path", packageFile) + if err := utils.GenerateTemplate(packageFile, VENDOR_GOPKG, nil); err != nil { + return utils.NewBuildIfError(err, "Failed to generate template") + } } else { utils.Logger.Info("Package file exists in skeleto, skipping adding") } - getCmd := exec.Command(depPath, "ensure", "-v") - getCmd.Dir = c.ImportPath + getCmd := exec.Command("dep", "ensure", "-v") + utils.CmdInit(getCmd, c.AppPath) + utils.Logger.Info("Exec:", "args", getCmd.Args) + getOutput, err := getCmd.CombinedOutput() + if err != nil { + return utils.NewBuildIfError(err, string(getOutput)) + } + } + + // checking and setting application + + if err = setApplicationPath(c); err != nil { + return err + } + + // checking and setting skeleton + if err=setSkeletonPath(c);err!=nil { + return + } + + // copy files to new app directory + if err = copyNewAppFiles(c);err != nil { + return + } + + // Rerun the dep tool if vendored + if c.New.Vendored { + getCmd := exec.Command("dep", "ensure", "-v") + utils.CmdInit(getCmd, c.AppPath) utils.Logger.Info("Exec:", "args", getCmd.Args) - getCmd.Dir = c.ImportPath getOutput, err := getCmd.CombinedOutput() if err != nil { utils.Logger.Fatal(string(getOutput)) } } - - // checking and setting application - setApplicationPath(c) - - // checking and setting skeleton - setSkeletonPath(c) - - // copy files to new app directory - copyNewAppFiles(c) - - // goodbye world - fmt.Fprintln(os.Stdout, "Your application is ready:\n ", c.AppPath) + fmt.Fprintln(os.Stdout, "Your application has been created in:\n ", c.AppPath) // Check to see if it should be run right off if c.New.Run { runApp(c) } else { fmt.Fprintln(os.Stdout, "\nYou can run it with:\n revel run -a ", c.ImportPath) } + return } // Used to generate a new secret key @@ -143,7 +165,7 @@ func generateSecret() string { } // Sets the applicaiton path -func setApplicationPath(c *model.CommandConfig) { +func setApplicationPath(c *model.CommandConfig) (err error) { // revel/revel#1014 validate relative path, we cannot use built-in functions // since Go import path is valid relative path too. @@ -153,95 +175,111 @@ func setApplicationPath(c *model.CommandConfig) { c.ImportPath) } - // If we are running a vendored version of Revel we do not need to check for it. if !c.New.Vendored { - var err error _, err = build.Import(model.RevelImportPath, "", build.FindOnly) if err != nil { - // Go get the revel project - getCmd := exec.Command(c.GoCmd, "get", model.RevelImportPath) - utils.Logger.Info("Exec:" + c.GoCmd, "args", getCmd.Args) - getOutput, err := getCmd.CombinedOutput() + //// Go get the revel project + err = c.PackageResolver(model.RevelImportPath) if err != nil { - utils.Logger.Fatal("Failed to fetch revel " + model.RevelImportPath, "getOutput", string(getOutput)) + return utils.NewBuildIfError(err, "Failed to fetch revel "+model.RevelImportPath) } } } c.AppName = filepath.Base(c.AppPath) - c.BasePath = filepath.ToSlash(filepath.Dir(c.ImportPath)) - if c.BasePath == "." { - // we need to remove the a single '.' when - // the app is in the $GOROOT/src directory - c.BasePath = "" - } else { - // we need to append a '/' when the app is - // is a subdirectory such as $GOROOT/src/path/to/revelapp - c.BasePath += "/" - } + //if c.BasePath == "." { + // // we need to remove the a single '.' when + // // the app is in the $GOROOT/src directory + // c.BasePath = "" + //} else { + // // we need to append a '/' when the app is + // // is a subdirectory such as $GOROOT/src/path/to/revelapp + // c.BasePath += "/" + //} + + return nil } // Set the skeleton path -func setSkeletonPath(c *model.CommandConfig) { - var err error - if len(c.SkeletonPath) > 0 { // user specified - - _, err = build.Import(c.SkeletonPath, "", build.FindOnly) - if err != nil { - // Execute "go get " - getCmd := exec.Command(c.GoCmd, "get", "-d", c.SkeletonPath) - fmt.Println("Exec:", getCmd.Args) - getOutput, err := getCmd.CombinedOutput() - - // check getOutput for no buildible string - bpos := bytes.Index(getOutput, []byte("no buildable Go source files in")) - if err != nil && bpos == -1 { - utils.Logger.Fatalf("Abort: Could not find or 'go get' Skeleton source code: %s\n%s\n", getOutput, c.SkeletonPath) - } - } - // use the - c.SkeletonPath = filepath.Join(c.SrcRoot, c.SkeletonPath) - - } else { - // use the revel default - revelCmdPkg, err := build.Import(RevelCmdImportPath, "", build.FindOnly) - if err != nil { - if err != nil { - // Go get the revel project - getCmd := exec.Command(c.GoCmd, "get", RevelCmdImportPath + "/revel") - utils.Logger.Info("Exec:" + c.GoCmd, "args", getCmd.Args) - getOutput, err := getCmd.CombinedOutput() - if err != nil { - utils.Logger.Fatal("Failed to fetch revel cmd " + RevelCmdImportPath, "getOutput", string(getOutput)) - } - revelCmdPkg, err = build.Import(RevelCmdImportPath, "", build.FindOnly) - if err!= nil { - utils.Logger.Fatal("Failed to find source of revel cmd " + RevelCmdImportPath, "getOutput", string(getOutput), "error",err, "dir", revelCmdPkg.Dir) - } - } - } - - c.SkeletonPath = filepath.Join(revelCmdPkg.Dir, "revel", "skeleton") +func setSkeletonPath(c *model.CommandConfig) (err error) { + if len(c.New.SkeletonPath) == 0 { + c.New.SkeletonPath = "git://" + RevelSkeletonsImportPath + ":basic/bootstrap4" } + + // First check to see the protocol of the string + if sp, err := url.Parse(c.New.SkeletonPath); err == nil { + utils.Logger.Info("Detected skeleton path", "path", sp) + + switch strings.ToLower(sp.Scheme) { + // TODO Add support for https, http, ftp, file + case "git": + if err := newLoadFromGit(c, sp); err != nil { + return err + } + //case "": + + //if err := newLoadFromGo(c, sp); err != nil { + // return err + //} + default: + utils.Logger.Fatal("Unsupported skeleton schema ", "path", c.New.SkeletonPath) + + } + // TODO check to see if the path needs to be extracted + } else { + utils.Logger.Fatal("Invalid skeleton path format", "path", c.New.SkeletonPath) + } + return } -func copyNewAppFiles(c *model.CommandConfig) { - var err error - err = os.MkdirAll(c.AppPath, 0777) - utils.PanicOnError(err, "Failed to create directory "+c.AppPath) +// Load skeleton from git +func newLoadFromGit(c *model.CommandConfig, sp *url.URL) (err error) { + // This method indicates we need to fetch from a repository using git + // Execute "git clone get " + targetPath := filepath.Join(os.TempDir(), "revel", "skeleton") + os.RemoveAll(targetPath) + pathpart := strings.Split(sp.Path, ":") + getCmd := exec.Command("git", "clone", sp.Scheme+"://"+sp.Host+pathpart[0], targetPath) + utils.Logger.Info("Exec:", "args", getCmd.Args) + getOutput, err := getCmd.CombinedOutput() + if err != nil { + utils.Logger.Fatalf("Abort: could not clone the Skeleton source code: \n%s\n%s\n", getOutput, c.New.SkeletonPath) + } + outputPath := targetPath + if len(pathpart) > 1 { + outputPath = filepath.Join(targetPath, filepath.Join(strings.Split(pathpart[1], string('/'))...)) + } + outputPath, _ = filepath.Abs(outputPath) + if !strings.HasPrefix(outputPath, targetPath) { + utils.Logger.Fatal("Unusual target path outside root path", "target", outputPath, "root", targetPath) + } - _ = utils.MustCopyDir(c.AppPath, c.SkeletonPath, map[string]interface{}{ + c.New.SkeletonPath = outputPath + return +} + +func copyNewAppFiles(c *model.CommandConfig) (err error) { + err = os.MkdirAll(c.AppPath, 0777) + if err != nil { + return utils.NewBuildIfError(err, "MKDIR failed") + } + + err = utils.CopyDir(c.AppPath, c.New.SkeletonPath, map[string]interface{}{ // app.conf "AppName": c.AppName, - "BasePath": c.BasePath, + "BasePath": c.AppPath, "Secret": generateSecret(), }) + if err != nil { + fmt.Printf("err %v", err) + return utils.NewBuildIfError(err, "Copy Dir failed") + } // Dotfiles are skipped by mustCopyDir, so we have to explicitly copy the .gitignore. gitignore := ".gitignore" - utils.MustCopyFile(filepath.Join(c.AppPath, gitignore), filepath.Join(c.SkeletonPath, gitignore)) + return utils.CopyFile(filepath.Join(c.AppPath, gitignore), filepath.Join(c.New.SkeletonPath, gitignore)) } @@ -299,4 +337,4 @@ required = ["github.com/revel/cmd/revel"] NEW_MAIN_FILE = `package main ` -) \ No newline at end of file +) diff --git a/revel/new_test.go b/revel/new_test.go new file mode 100644 index 0000000..c1d3bca --- /dev/null +++ b/revel/new_test.go @@ -0,0 +1,101 @@ +package main_test + +import ( + "github.com/revel/cmd/model" + "github.com/revel/cmd/revel" + "github.com/revel/cmd/utils" + "github.com/stretchr/testify/assert" + "io/ioutil" + "os" + "path/filepath" + "testing" +) + +// test the commands +func TestNew(t *testing.T) { + a := assert.New(t) + gopath := setup("revel-test-new", a) + + t.Run("New", func(t *testing.T) { + a := assert.New(t) + c := newApp("new-test", model.NEW, nil, a) + a.Nil(main.Commands[model.NEW].RunWith(c), "New failed") + }) + t.Run("Path", func(t *testing.T) { + a := assert.New(t) + c := newApp("new/test/a", model.NEW, nil, a) + a.Nil(main.Commands[model.NEW].RunWith(c), "New path failed") + }) + t.Run("Path-Duplicate", func(t *testing.T) { + a := assert.New(t) + c := newApp("new/test/b", model.NEW, nil, a) + a.Nil(main.Commands[model.NEW].RunWith(c), "New path failed") + c = newApp("new/test/b", model.NEW, nil, a) + a.NotNil(main.Commands[model.NEW].RunWith(c), "Duplicate path Did Not failed") + }) + t.Run("Skeleton-Git", func(t *testing.T) { + a := assert.New(t) + c := newApp("new/test/c/1", model.NEW, nil, a) + c.New.SkeletonPath = "git://github.com/revel/skeletons:basicnsadnsak" + a.NotNil(main.Commands[model.NEW].RunWith(c), "Expected Failed to run with new") + // We need to pick a different path + c = newApp("new/test/c/2", model.NEW, nil, a) + c.New.SkeletonPath = "git://github.com/revel/skeletons:basic/bootstrap4" + a.Nil(main.Commands[model.NEW].RunWith(c), "Failed to run with new skeleton git") + }) + if !t.Failed() { + if err := os.RemoveAll(gopath); err != nil { + a.Fail("Failed to remove test path") + } + } +} + +// test the commands +func TestNewVendor(t *testing.T) { + a := assert.New(t) + gopath := setup("revel-test-new-vendor", a) + precall := func(c *model.CommandConfig) { + c.New.Vendored = true + } + t.Run("New", func(t *testing.T) { + a := assert.New(t) + c := newApp("onlyone/v/a", model.NEW, precall, a) + c.New.Vendored = true + a.Nil(main.Commands[model.NEW].RunWith(c), "New failed") + }) + t.Run("Test", func(t *testing.T) { + a := assert.New(t) + c := newApp("onlyone/v/a", model.TEST, nil, a) + a.Nil(main.Commands[model.TEST].RunWith(c), "Test failed") + }) + t.Run("Build", func(t *testing.T) { + a := assert.New(t) + c := newApp("onlyone/v/a", model.BUILD, nil, a) + c.Index = model.BUILD + c.Build.TargetPath = filepath.Join(gopath, "src/onlyone/v/a", "target") + a.Nil(main.Commands[model.BUILD].RunWith(c), " Build failed") + a.True(utils.DirExists(c.Build.TargetPath), "Target folder not made", c.Build.TargetPath) + }) + t.Run("Package", func(t *testing.T) { + a := assert.New(t) + c := newApp("onlyone/v/a", model.PACKAGE, nil, a) + c.Package.TargetPath = filepath.Join(gopath, "src/onlyone/v/a", "target.tar.gz") + a.Nil(main.Commands[model.PACKAGE].RunWith(c), "Package Failed") + a.True(utils.Exists(c.Package.TargetPath), "Target package not made", c.Package.TargetPath) + }) + t.Run("TestVendorDir", func(t *testing.T) { + // Check to see that no additional packages were downloaded outside the vendor folder + files, err := ioutil.ReadDir(gopath) + a.Nil(err, "Failed to read gopath folder") + // bin/ onlyone/ pkg/ src/ + a.Equal(3, len(files), "Expected single file in "+gopath) + files, err = ioutil.ReadDir(filepath.Join(gopath, "src")) + a.Nil(err, "Failed to read src folder") + a.Equal(1, len(files), "Expected single file in source folder", filepath.Join(gopath, "src")) + }) + if !t.Failed() { + if err := os.RemoveAll(gopath); err != nil { + a.Fail("Failed to remove test path") + } + } +} diff --git a/revel/package.go b/revel/package.go index c8b1314..963d62c 100644 --- a/revel/package.go +++ b/revel/package.go @@ -15,7 +15,7 @@ import ( ) var cmdPackage = &Command{ - UsageLine: "package -i [import path] -r [run mode]", + UsageLine: "package [-r [run mode]] [application] ", Short: "package a Revel application (e.g. for deployment)", Long: ` Package the Revel web application named by the given import path. @@ -28,7 +28,7 @@ Run mode defaults to "dev". For example: - revel package -i github.com/revel/examples/chat + revel package github.com/revel/examples/chat `, } @@ -40,19 +40,16 @@ func init() { // Called when unable to parse the command line automatically and assumes an old launch func updatePackageConfig(c *model.CommandConfig, args []string) bool { c.Index = model.PACKAGE - if len(args) == 0 { - fmt.Fprintf(os.Stderr, cmdPackage.Long) - return false - } c.Package.ImportPath = args[0] - if len(args)>1 { + if len(args) > 1 { c.Package.Mode = args[1] } return true } -func packageApp(c *model.CommandConfig) { +// Called to package the app +func packageApp(c *model.CommandConfig) (err error) { // Determine the run mode. mode := DefaultRunMode @@ -61,13 +58,22 @@ func packageApp(c *model.CommandConfig) { } appImportPath := c.ImportPath - revel_paths := model.NewRevelPaths(mode, appImportPath, "", model.DoNothingRevelCallback) + revel_paths, err := model.NewRevelPaths(mode, appImportPath, "", model.NewWrappedRevelCallback(nil, c.PackageResolver)) + if err != nil { + return + } // Remove the archive if it already exists. - destFile := filepath.Base(revel_paths.BasePath) + ".tar.gz" + destFile := filepath.Join(c.AppPath, filepath.Base(revel_paths.BasePath)+".tar.gz") + if c.Package.TargetPath != "" { + if filepath.IsAbs(c.Package.TargetPath) { + destFile = c.Package.TargetPath + } else { + destFile = filepath.Join(c.AppPath, c.Package.TargetPath) + } + } if err := os.Remove(destFile); err != nil && !os.IsNotExist(err) { - utils.Logger.Error("Unable to remove target file","error",err,"file",destFile) - os.Exit(1) + return utils.NewBuildError("Unable to remove target file", "error", err, "file", destFile) } // Collect stuff in a temp directory. @@ -83,7 +89,12 @@ func packageApp(c *model.CommandConfig) { buildApp(c) // Create the zip file. - archiveName := utils.MustTarGzDir(destFile, tmpDir) + + archiveName, err := utils.TarGzDir(destFile, tmpDir) + if err != nil { + return + } fmt.Println("Your archive is ready:", archiveName) + return } diff --git a/revel/package_test.go b/revel/package_test.go new file mode 100644 index 0000000..02e7e35 --- /dev/null +++ b/revel/package_test.go @@ -0,0 +1,30 @@ +package main_test + +import ( + "github.com/revel/cmd/model" + "github.com/revel/cmd/revel" + "github.com/stretchr/testify/assert" + "os" + "testing" +) + +// test the commands +func TestPackage(t *testing.T) { + a := assert.New(t) + gopath := setup("revel-test-package", a) + + t.Run("Package", func(t *testing.T) { + a := assert.New(t) + c := newApp("package-test", model.NEW, nil, a) + main.Commands[model.NEW].RunWith(c) + c.Index = model.PACKAGE + c.Package.ImportPath = c.ImportPath + a.Nil(main.Commands[model.PACKAGE].RunWith(c), "Failed to run package-test") + }) + + if !t.Failed() { + if err := os.RemoveAll(gopath); err != nil { + a.Fail("Failed to remove test path") + } + } +} diff --git a/revel/revel.go b/revel/revel.go index e0cc6a7..ab15574 100644 --- a/revel/revel.go +++ b/revel/revel.go @@ -8,37 +8,35 @@ package main import ( "flag" "fmt" - "io" "math/rand" "os" "runtime" "strings" - "text/template" "time" "github.com/jessevdk/go-flags" "github.com/agtorre/gocolorize" + "github.com/revel/cmd/logger" "github.com/revel/cmd/model" "github.com/revel/cmd/utils" - "github.com/revel/cmd/logger" - "os/exec" - "path/filepath" - "go/build" ) const ( // RevelCmdImportPath Revel framework cmd tool import path RevelCmdImportPath = "github.com/revel/cmd" + // RevelCmdImportPath Revel framework cmd tool import path + RevelSkeletonsImportPath = "github.com/revel/skeletons" + // DefaultRunMode for revel's application DefaultRunMode = "dev" ) // Command structure cribbed from the genius organization of the "go" command. type Command struct { - UpdateConfig func(c *model.CommandConfig, args []string) bool - RunWith func(c *model.CommandConfig) + UpdateConfig func(c *model.CommandConfig, args []string) bool + RunWith func(c *model.CommandConfig) error UsageLine, Short, Long string } @@ -53,7 +51,7 @@ func (cmd *Command) Name() string { } // The commands -var commands = []*Command{ +var Commands = []*Command{ nil, // Safety net, prevent missing index from running cmdNew, cmdRun, @@ -63,43 +61,61 @@ var commands = []*Command{ cmdTest, cmdVersion, } + func main() { if runtime.GOOS == "windows" { gocolorize.SetPlain(true) } c := &model.CommandConfig{} - wd,_ := os.Getwd() + wd, _ := os.Getwd() - utils.InitLogger(wd,logger.LvlError) + utils.InitLogger(wd, logger.LvlError) - parser := flags.NewParser(c, flags.HelpFlag | flags.PassDoubleDash) - if ini:=flag.String("ini","none","");*ini!="none" { - if err:=flags.NewIniParser(parser).ParseFile(*ini);err!=nil { - utils.Logger.Error("Unable to load ini", "error",err) + parser := flags.NewParser(c, flags.HelpFlag|flags.PassDoubleDash) + if err := ParseArgs(c, parser, os.Args[1:]); err != nil { + fmt.Fprint(os.Stderr, err.Error()) + parser.WriteHelp(os.Stdout) + os.Exit(1) + } + + // Switch based on the verbose flag + if len(c.Verbose)>1 { + utils.InitLogger(wd, logger.LvlDebug) + } else if len(c.Verbose)>0 { + utils.InitLogger(wd, logger.LvlInfo) + } else { + utils.InitLogger(wd, logger.LvlWarn) + } + + if !c.UpdateImportPath() { + utils.Logger.Fatal("Unable to determine application path") + } + + command := Commands[c.Index] + println("Revel executing:", command.Short) + + // Setting go paths + c.InitGoPaths() + + // Setup package resolver + c.InitPackageResolver() + + if err := command.RunWith(c); err != nil { + utils.Logger.Error("Unable to execute","error",err) + os.Exit(1) + } +} + +// Parse the arguments passed into the model.CommandConfig +func ParseArgs(c *model.CommandConfig, parser *flags.Parser, args []string) (err error) { + var extraArgs []string + if ini := flag.String("ini", "none", ""); *ini != "none" { + if err = flags.NewIniParser(parser).ParseFile(*ini); err != nil { + return } } else { - if _, err := parser.Parse(); err != nil { - utils.Logger.Info("Command line options failed", "error", err.Error()) - - // Decode nature of error - if perr,ok:=err.(*flags.Error); ok { - if perr.Type == flags.ErrRequired { - // Try the old way - if !main_parse_old(c) { - println("Command line error:", err.Error()) - parser.WriteHelp(os.Stdout) - os.Exit(1) - } - } else { - println("Command line error:", err.Error()) - parser.WriteHelp(os.Stdout) - os.Exit(1) - } - } else { - println("Command line error:", err.Error()) - parser.WriteHelp(os.Stdout) - os.Exit(1) - } + if extraArgs, err = parser.ParseArgs(args); err != nil { + return } else { switch parser.Active.Name { case "new": @@ -120,182 +136,18 @@ func main() { } } - // Switch based on the verbose flag - if c.Verbose { - utils.InitLogger(wd, logger.LvlDebug) - } else { - utils.InitLogger(wd, logger.LvlWarn) - } - - if c.Index==0 { - utils.Logger.Fatal("Unknown command line arguements") - } - if !c.UpdateImportPath() { - utils.Logger.Fatal("Unable to determine application path") - } - println("Revel executing:", commands[c.Index].Short) - // checking and setting go paths - initGoPaths(c) - - - commands[c.Index].RunWith(c) - - -} - -// Try to populate the CommandConfig using the old techniques -func main_parse_old(c *model.CommandConfig) bool { - // Take the old command format and try to parse them - flag.Usage = func() { usage(1) } - flag.Parse() - args := flag.Args() - - if len(args) < 1 || args[0] == "help" { - if len(args) == 1 { - usage(0) - } - - if len(args) > 1 { - for _, cmd := range commands { - if cmd!=nil && cmd.Name() == args[1] { - tmpl(os.Stdout, helpTemplate, cmd) - return false - } - } - } - usage(2) - } - - for _, cmd := range commands { - if cmd!=nil && cmd.Name() == args[0] { - println("Running", cmd.Name()) - return cmd.UpdateConfig(c, args[1:]) + if c.Index == 0 { + err = fmt.Errorf("Unknown command %v", extraArgs) + } else if len(extraArgs) > 0 { + utils.Logger.Info("Found additional arguements, setting them") + if !Commands[c.Index].UpdateConfig(c, extraArgs) { + err = fmt.Errorf("Invalid command line arguements %v", extraArgs) } } - return false -} - -func main_old() { - if runtime.GOOS == "windows" { - gocolorize.SetPlain(true) - } - fmt.Fprintf(os.Stdout, gocolorize.NewColor("blue").Paint(header)) - flag.Usage = func() { usage(1) } - flag.Parse() - args := flag.Args() - - if len(args) < 1 || args[0] == "help" { - if len(args) == 1 { - usage(0) - } - if len(args) > 1 { - for _, cmd := range commands { - if cmd.Name() == args[1] { - tmpl(os.Stdout, helpTemplate, cmd) - return - } - } - } - usage(2) - } - - // Commands use panic to abort execution when something goes wrong. - // Panics are logged at the point of error. Ignore those. - defer func() { - if err := recover(); err != nil { - if _, ok := err.(utils.LoggedError); !ok { - // This panic was not expected / logged. - panic(err) - } - os.Exit(1) - } - }() - - //for _, cmd := range commands { - // if cmd.Name() == args[0] { - // cmd.UpdateConfig(args[1:]) - // return - // } - //} - - utils.Logger.Fatalf("unknown command %q\nRun 'revel help' for usage.\n", args[0]) -} - -const header = `~ -~ revel! http://revel.github.io -~ -` - -const usageTemplate = `usage: revel command [arguments] - -The commands are: -{{range .}} - {{.Name | printf "%-11s"}} {{.Short}}{{end}} - -Use "revel help [command]" for more information. -` - -var helpTemplate = `usage: revel {{.UsageLine}} -{{.Long}} -` - -func usage(exitCode int) { - tmpl(os.Stderr, usageTemplate, commands) - os.Exit(exitCode) -} - -func tmpl(w io.Writer, text string, data interface{}) { - t := template.New("top") - template.Must(t.Parse(text)) - if err := t.Execute(w, data); err != nil { - panic(err) - } + return } func init() { rand.Seed(time.Now().UnixNano()) } - -// lookup and set Go related variables -func initGoPaths(c *model.CommandConfig) { - // lookup go path - c.GoPath = build.Default.GOPATH - if c.GoPath == "" { - utils.Logger.Fatal("Abort: GOPATH environment variable is not set. " + - "Please refer to http://golang.org/doc/code.html to configure your Go environment.") - } - - // check for go executable - var err error - c.GoCmd, err = exec.LookPath("go") - if err != nil { - utils.Logger.Fatal("Go executable not found in PATH.") - } - - // revel/revel#1004 choose go path relative to current working directory - workingDir, _ := os.Getwd() - goPathList := filepath.SplitList(c.GoPath) - for _, path := range goPathList { - if strings.HasPrefix(strings.ToLower(workingDir), strings.ToLower(path)) { - c.SrcRoot = path - break - } - - path, _ = filepath.EvalSymlinks(path) - if len(path) > 0 && strings.HasPrefix(strings.ToLower(workingDir), strings.ToLower(path)) { - c.SrcRoot = path - break - } - } - - if len(c.SrcRoot) == 0 { - if c.Index != model.VERSION { - utils.Logger.Fatal("Abort: could not create a Revel application outside of GOPATH.") - } - return - } - - // set go src path - c.SrcRoot = filepath.Join(c.SrcRoot, "src") -} \ No newline at end of file diff --git a/revel/run.go b/revel/run.go index 04f22ac..166518b 100644 --- a/revel/run.go +++ b/revel/run.go @@ -15,23 +15,23 @@ import ( ) var cmdRun = &Command{ - UsageLine: "run [import path] [run mode] [port]", + UsageLine: "run [-m [run mode] -p [port]] [import path] ", Short: "run a Revel application", Long: ` Run the Revel web application named by the given import path. For example, to run the chat room sample application: - revel run github.com/revel/examples/chat dev + revel run -m dev github.com/revel/examples/chat The run mode is used to select which set of app.conf configuration should apply and may be used to determine logic in the application itself. Run mode defaults to "dev". -You can set a port as an optional third parameter. For example: +You can set a port as well. For example: - revel run github.com/revel/examples/chat prod 8080`, + revel run -m prod -p 8080 github.com/revel/examples/chat `, } // RunArgs holds revel run parameters @@ -47,14 +47,23 @@ func init() { } func updateRunConfig(c *model.CommandConfig, args []string) bool { - + convertPort := func(value string) int { + if value != "" { + port, err := strconv.Atoi(value) + if err != nil { + utils.Logger.Fatalf("Failed to parse port as integer: %s", c.Run.Port) + } + return port + } + return 0 + } switch len(args) { case 3: // Possible combinations // revel run [import-path] [run-mode] [port] c.Run.ImportPath = args[0] c.Run.Mode = args[1] - c.Run.Port = args[2] + c.Run.Port = convertPort(args[2]) case 2: // Possible combinations // 1. revel run [import-path] [run-mode] @@ -68,7 +77,7 @@ func updateRunConfig(c *model.CommandConfig, args []string) bool { if _, err := strconv.Atoi(args[1]); err == nil { // 2nd arg is the port number - c.Run.Port = args[1] + c.Run.Port = convertPort(args[1]) } else { // 2nd arg is the run mode c.Run.Mode = args[1] @@ -76,7 +85,7 @@ func updateRunConfig(c *model.CommandConfig, args []string) bool { } else { // 1st arg is the run mode c.Run.Mode = args[0] - c.Run.Port = args[1] + c.Run.Port = convertPort(args[1]) } case 1: // Possible combinations @@ -93,7 +102,7 @@ func updateRunConfig(c *model.CommandConfig, args []string) bool { c.Run.ImportPath = args[0] } else if _, err := strconv.Atoi(args[0]); err == nil { // 1st arg is the port number - c.Run.Port = args[0] + c.Run.Port = convertPort(args[0]) } else { // 1st arg is the run mode c.Run.Mode = args[0] @@ -105,18 +114,20 @@ func updateRunConfig(c *model.CommandConfig, args []string) bool { return true } -func runApp(c *model.CommandConfig) { +// Called to run the app +func runApp(c *model.CommandConfig) (err error) { if c.Run.Mode == "" { c.Run.Mode = "dev" } - revel_path := model.NewRevelPaths(c.Run.Mode, c.ImportPath, "", model.DoNothingRevelCallback) - if c.Run.Port != "" { - port, err := strconv.Atoi(c.Run.Port) - if err != nil { - utils.Logger.Fatalf("Failed to parse port as integer: %s", c.Run.Port) - } - revel_path.HTTPPort = port + revel_path, err := model.NewRevelPaths(c.Run.Mode, c.ImportPath, "", model.NewWrappedRevelCallback(nil, c.PackageResolver)) + if err != nil { + return utils.NewBuildIfError(err, "Revel paths") + } + if c.Run.Port > -1 { + revel_path.HTTPPort = c.Run.Port + } else { + c.Run.Port = revel_path.HTTPPort } utils.Logger.Infof("Running %s (%s) in %s mode\n", revel_path.AppName, revel_path.ImportPath, revel_path.RunMode) @@ -145,4 +156,5 @@ func runApp(c *model.CommandConfig) { runMode = revel_path.RunMode } app.Cmd(runMode).Run() + return } diff --git a/revel/run_test.go b/revel/run_test.go new file mode 100644 index 0000000..7a39b77 --- /dev/null +++ b/revel/run_test.go @@ -0,0 +1,21 @@ +package main_test + +import ( + "github.com/stretchr/testify/assert" + "os" + "testing" +) + +// test the commands +func TestRun(t *testing.T) { + a := assert.New(t) + gopath := setup("revel-test-run", a) + + // TODO Testing run + + if !t.Failed() { + if err := os.RemoveAll(gopath); err != nil { + a.Fail("Failed to remove test path") + } + } +} diff --git a/revel/skeleton/.gitignore b/revel/skeleton/.gitignore deleted file mode 100644 index dae67d0..0000000 --- a/revel/skeleton/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -test-results/ -tmp/ -routes/ diff --git a/revel/skeleton/README.md b/revel/skeleton/README.md deleted file mode 100644 index d418163..0000000 --- a/revel/skeleton/README.md +++ /dev/null @@ -1,43 +0,0 @@ -# Welcome to Revel - -A high-productivity web framework for the [Go language](http://www.golang.org/). - - -### Start the web server: - - revel run myapp - -### Go to http://localhost:9000/ and you'll see: - - "It works" - -## Code Layout - -The directory structure of a generated Revel application: - - conf/ Configuration directory - app.conf Main app configuration file - routes Routes definition file - - app/ App sources - init.go Interceptor registration - controllers/ App controllers go here - views/ Templates directory - - messages/ Message files - - public/ Public static assets - css/ CSS files - js/ Javascript files - images/ Image files - - tests/ Test suites - - -## Help - -* The [Getting Started with Revel](http://revel.github.io/tutorial/gettingstarted.html). -* The [Revel guides](http://revel.github.io/manual/index.html). -* The [Revel sample apps](http://revel.github.io/examples/index.html). -* The [API documentation](https://godoc.org/github.com/revel/revel). - diff --git a/revel/skeleton/app/controllers/app.go b/revel/skeleton/app/controllers/app.go deleted file mode 100644 index 1e94062..0000000 --- a/revel/skeleton/app/controllers/app.go +++ /dev/null @@ -1,13 +0,0 @@ -package controllers - -import ( - "github.com/revel/revel" -) - -type App struct { - *revel.Controller -} - -func (c App) Index() revel.Result { - return c.Render() -} diff --git a/revel/skeleton/app/init.go b/revel/skeleton/app/init.go deleted file mode 100644 index 117dd4e..0000000 --- a/revel/skeleton/app/init.go +++ /dev/null @@ -1,59 +0,0 @@ -package app - -import ( - "github.com/revel/revel" -) - -var ( - // AppVersion revel app version (ldflags) - AppVersion string - - // BuildTime revel app build-time (ldflags) - BuildTime string -) - -func init() { - // Filters is the default set of global filters. - revel.Filters = []revel.Filter{ - revel.PanicFilter, // Recover from panics and display an error page instead. - revel.RouterFilter, // Use the routing table to select the right Action - revel.FilterConfiguringFilter, // A hook for adding or removing per-Action filters. - revel.ParamsFilter, // Parse parameters into Controller.Params. - revel.SessionFilter, // Restore and write the session cookie. - revel.FlashFilter, // Restore and write the flash cookie. - revel.ValidationFilter, // Restore kept validation errors and save new ones from cookie. - revel.I18nFilter, // Resolve the requested language - HeaderFilter, // Add some security based headers - revel.InterceptorFilter, // Run interceptors around the action. - revel.CompressFilter, // Compress the result. - revel.BeforeAfterFilter, // Call the before and after filter functions - revel.ActionInvoker, // Invoke the action. - } - - // Register startup functions with OnAppStart - // revel.DevMode and revel.RunMode only work inside of OnAppStart. See Example Startup Script - // ( order dependent ) - // revel.OnAppStart(ExampleStartupScript) - // revel.OnAppStart(InitDB) - // revel.OnAppStart(FillCache) -} - -// HeaderFilter adds common security headers -// There is a full implementation of a CSRF filter in -// https://github.com/revel/modules/tree/master/csrf -var HeaderFilter = func(c *revel.Controller, fc []revel.Filter) { - c.Response.Out.Header().Add("X-Frame-Options", "SAMEORIGIN") - c.Response.Out.Header().Add("X-XSS-Protection", "1; mode=block") - c.Response.Out.Header().Add("X-Content-Type-Options", "nosniff") - c.Response.Out.Header().Add("Referrer-Policy", "strict-origin-when-cross-origin") - - fc[0](c, fc[1:]) // Execute the next filter stage. -} - -//func ExampleStartupScript() { -// // revel.DevMod and revel.RunMode work here -// // Use this script to check for dev mode and set dev/prod startup scripts here! -// if revel.DevMode == true { -// // Dev mode -// } -//} diff --git a/revel/skeleton/app/views/App/Index.html b/revel/skeleton/app/views/App/Index.html deleted file mode 100644 index abfa102..0000000 --- a/revel/skeleton/app/views/App/Index.html +++ /dev/null @@ -1,21 +0,0 @@ -{{set . "title" "Home"}} -{{template "header.html" .}} - -
-
-
-

It works!

-

-
-
-
- -
-
-
- {{template "flash.html" .}} -
-
-
- -{{template "footer.html" .}} diff --git a/revel/skeleton/app/views/debug.html b/revel/skeleton/app/views/debug.html deleted file mode 100644 index 5f1013c..0000000 --- a/revel/skeleton/app/views/debug.html +++ /dev/null @@ -1,64 +0,0 @@ - - - - - diff --git a/revel/skeleton/app/views/errors/404.html b/revel/skeleton/app/views/errors/404.html deleted file mode 100644 index ebdfe10..0000000 --- a/revel/skeleton/app/views/errors/404.html +++ /dev/null @@ -1,20 +0,0 @@ - - - - Not found - - -{{if eq .RunMode "dev"}} -{{template "errors/404-dev.html" .}} -{{else}} - {{with .Error}} -

- {{.Title}} -

-

- {{.Description}} -

- {{end}} -{{end}} - - diff --git a/revel/skeleton/app/views/errors/500.html b/revel/skeleton/app/views/errors/500.html deleted file mode 100644 index 0cef4de..0000000 --- a/revel/skeleton/app/views/errors/500.html +++ /dev/null @@ -1,16 +0,0 @@ - - - - Application error - - - {{if eq .RunMode "dev"}} - {{template "errors/500-dev.html" .}} - {{else}} -

Oops, an error occured

-

- This exception has been logged. -

- {{end}} - - diff --git a/revel/skeleton/app/views/flash.html b/revel/skeleton/app/views/flash.html deleted file mode 100644 index 1c764c0..0000000 --- a/revel/skeleton/app/views/flash.html +++ /dev/null @@ -1,18 +0,0 @@ -{{if .flash.success}} -
- {{.flash.success}} -
-{{end}} - -{{if or .errors .flash.error}} -
- {{if .flash.error}} - {{.flash.error}} - {{end}} -
    - {{range .errors}} -
  • {{.}}
  • - {{end}} -
-
-{{end}} diff --git a/revel/skeleton/app/views/footer.html b/revel/skeleton/app/views/footer.html deleted file mode 100644 index baf786e..0000000 --- a/revel/skeleton/app/views/footer.html +++ /dev/null @@ -1,5 +0,0 @@ - {{if .DevMode}} - {{template "debug.html" .}} - {{end}} - - diff --git a/revel/skeleton/app/views/header.html b/revel/skeleton/app/views/header.html deleted file mode 100644 index 63e9fe5..0000000 --- a/revel/skeleton/app/views/header.html +++ /dev/null @@ -1,19 +0,0 @@ - - - - - {{.title}} - - - - - - - {{range .moreStyles}} - - {{end}} - {{range .moreScripts}} - - {{end}} - - diff --git a/revel/skeleton/conf/app.conf.template b/revel/skeleton/conf/app.conf.template deleted file mode 100644 index 367fe36..0000000 --- a/revel/skeleton/conf/app.conf.template +++ /dev/null @@ -1,223 +0,0 @@ -################################################################################ -# Revel configuration file -# More info at http://revel.github.io/manual/appconf.html -################################################################################ - -# Revel build section -# This section contains values that are not reloadable -################################################################################ - -# Comma delimited list of folders that are included with the package, or build commands -# If you want to not include folders within these ones prefix the folder with a . to make it hidden -package.folders = conf, public, app/views - - - - -# Revel reconfigurable section -# -################################################################################ - - -# Sets `revel.AppName` for use in-app. -# Example: -# `if revel.AppName {...}` -app.name = {{ .AppName }} - -# A secret string which is passed to cryptographically sign the cookie to prevent -# (and detect) user modification. -# Keep this string secret or users will be able to inject arbitrary cookie values -# into your application -app.secret = {{ .Secret }} - -# Revel running behind proxy like nginx, haproxy, etc. -app.behind.proxy = false - - -# The IP address on which to listen. -http.addr = - -# The port on which to listen. -http.port = 9000 - -# Whether to use SSL or not. -http.ssl = false - -# Path to an X509 certificate file, if using SSL. -#http.sslcert = - -# Path to an X509 certificate key, if using SSL. -#http.sslkey = - - -# Timeout specifies a time limit for request (in seconds) made by a single client. -# A Timeout of zero means no timeout. -http.timeout.read = 90 -http.timeout.write = 60 - - -# For any cookies set by Revel (Session,Flash,Error) these properties will set -# the fields of: -# http://golang.org/pkg/net/http/#Cookie -# -# Each cookie set by Revel is prefixed with this string. -cookie.prefix = REVEL - -# A secure cookie has the secure attribute enabled and is only used via HTTPS, -# ensuring that the cookie is always encrypted when transmitting from client to -# server. This makes the cookie less likely to be exposed to cookie theft via -# eavesdropping. -# -# Defaults to false. If 'http.ssl' is enabled, this will be defaulted to true. -# This should only be true when Revel is handling SSL connections. If you are -# using a proxy in front of revel (Nginx, Apache, etc), then this should be left -# as false. -# cookie.secure = false - -# Limit cookie access to a given domain. -#cookie.domain = - -# Define when your session cookie expires. -# Values: -# "720h" -# A time duration (http://golang.org/pkg/time/#ParseDuration) after which -# the cookie expires and the session is invalid. -# "session" -# Sets a session cookie which invalidates the session when the user close -# the browser. -session.expires = 720h - - -# The date format used by Revel. Possible formats defined by the Go `time` -# package (http://golang.org/pkg/time/#Parse) -format.date = 2006-01-02 -format.datetime = 2006-01-02 15:04 - - -# Determines whether the template rendering should use chunked encoding. -# Chunked encoding can decrease the time to first byte on the client side by -# sending data before the entire template has been fully rendered. -results.chunked = false - - -# The default language of this application. -i18n.default_language = en - -# The default format when message is missing. -# The original message shows in %s -#i18n.unknown_format = "??? %s ???" - - -# Module to serve static content such as CSS, JavaScript and Media files -# Allows Routes like this: -# `Static.ServeModule("modulename","public")` -module.static = github.com/revel/modules/static - - - -################################################################################ - -# Section: dev -# This section is evaluated when running Revel in dev mode. Like so: -# `revel run path/to/myapp` -[dev] - -# This sets `revel.DevMode` for use in-app. -# Example: -# `if revel.DevMode {...}` -# or in your templates with -# `{{.DevMode}}` -# Values: -# "true" -# Sets `DevMode` to `true`. -# "false" -# Sets `DevMode` to `false`. -mode.dev = true - - -# Pretty print JSON/XML when calling RenderJSON/RenderXML -# Values: -# "true" -# Enables pretty printing. -# "false" -# Disables pretty printing. -results.pretty = true - - -# Watch your applicaton files for changes and automatically rebuild -# Values: -# "true" -# Enables auto rebuilding. -# "false" -# Disables auto rebuilding. -watch = true - - -# Define when to rebuild new changes. -# Values: -# "normal" -# Rebuild when a new request is received and changes have been detected. -# "eager" -# Rebuild as soon as changes are detected. -watch.mode = eager - -# Watch the entire `$GOPATH` for changes. -# Values: -# "true" -# Includes `$GOPATH` in watch path. -# "false" -# Excludes `$GOPATH` from watch path. Default value. -#watch.gopath = true - - -# Module to run code tests in the browser -# See: -# http://revel.github.io/manual/testing.html -module.testrunner = github.com/revel/modules/testrunner - - -# Where to log the various Revel logs -# Values: -# "off" -# Disable log output. -# "stdout" -# Log to OS's standard output. -# "stderr" -# Log to Os's standard error output. Default value. -# "relative/path/to/log" -# Log to file. -log.all.filter.module.app = stdout # Log all loggers for the application to the stdout -log.error.nfilter.module.app = stderr # Everything else that logs an error to stderr -log.crit.output = stderr # Everything that logs something as critical goes to this - -# Revel request access log -# Access log line format: -# INFO 21:53:55 static server-engine.go:169: Request Stats ip=127.0.0.1 path=/public/vendors/datatables.net-buttons/js/buttons.html5.min.js method=GET start=2017/08/31 21:53:55 status=200 duration_seconds=0.0002583 section=requestlog -log.request.output = stdout - - - -################################################################################ -# Section: prod -# This section is evaluated when running Revel in production mode. Like so: -# `revel run path/to/myapp prod` -# See: -# [dev] section for documentation of the various settings -[prod] - -mode.dev = false - -results.pretty = false - -watch = false - -module.testrunner = - -log.warn.output = log/%(app.name)s-warn.json # Log all warn messages to file -log.error.output = log/%(app.name)s-error.json # Log all errors to file -log.crit.output = log/%(app.name)s-critical.json # Log all critical to file - -# Revel request access log (json format) -# Example: -# log.request.output = %(app.name)s-request.json -log.request.output = log/%(app.name)s-requests.json diff --git a/revel/skeleton/conf/routes b/revel/skeleton/conf/routes deleted file mode 100644 index ba93d61..0000000 --- a/revel/skeleton/conf/routes +++ /dev/null @@ -1,26 +0,0 @@ -# Routes Config -# -# This file defines all application routes (Higher priority routes first) -# - -module:testrunner -# module:jobs - - -GET / App.Index - -# Ignore favicon requests -GET /favicon.ico 404 - -# Map static resources from the /app/public folder to the /public path -GET /public/*filepath Static.Serve("public") - -# Catch all, this will route any request into the controller path -# -# **** WARNING **** -# Enabling this exposes any controller and function to the web. -# ** This is a serious security issue if used online ** -# -# For rapid development uncomment the following to add new controller.action endpoints -# without having to add them to the routes table. -# * /:controller/:action :controller.:action diff --git a/revel/skeleton/messages/sample.en b/revel/skeleton/messages/sample.en deleted file mode 100644 index 32f3f6b..0000000 --- a/revel/skeleton/messages/sample.en +++ /dev/null @@ -1,8 +0,0 @@ -# Sample messages file for the English language (en) -# Message file extensions should be ISO 639-1 codes (http://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) -# Sections within each message file can optionally override the defaults using ISO 3166-1 alpha-2 codes (http://en.wikipedia.org/wiki/ISO_3166-1_alpha-2) -# See also: -# - http://www.rfc-editor.org/rfc/bcp/bcp47.txt -# - http://www.w3.org/International/questions/qa-accept-lang-locales -[DEFAULT] - diff --git a/revel/skeleton/public/css/bootstrap-3.3.6.min.css b/revel/skeleton/public/css/bootstrap-3.3.6.min.css deleted file mode 100644 index 3e8b94d..0000000 --- a/revel/skeleton/public/css/bootstrap-3.3.6.min.css +++ /dev/null @@ -1,5 +0,0 @@ -/*! - * Bootstrap v3.3.6 (http://getbootstrap.com) - * Copyright 2011-2015 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - *//*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */html{font-family:sans-serif;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}dfn{font-style:italic}h1{margin:.67em 0;font-size:2em}mark{color:#000;background:#ff0}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{height:0;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{margin:0;font:inherit;color:inherit}button{overflow:visible}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0}input{line-height:normal}input[type=checkbox],input[type=radio]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}input[type=search]{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-appearance:textfield}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}fieldset{padding:.35em .625em .75em;margin:0 2px;border:1px solid silver}legend{padding:0;border:0}textarea{overflow:auto}optgroup{font-weight:700}table{border-spacing:0;border-collapse:collapse}td,th{padding:0}/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */@media print{*,:after,:before{color:#000!important;text-shadow:none!important;background:0 0!important;-webkit-box-shadow:none!important;box-shadow:none!important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) ")"}a[href^="javascript:"]:after,a[href^="#"]:after{content:""}blockquote,pre{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}img,tr{page-break-inside:avoid}img{max-width:100%!important}h2,h3,p{orphans:3;widows:3}h2,h3{page-break-after:avoid}.navbar{display:none}.btn>.caret,.dropup>.btn>.caret{border-top-color:#000!important}.label{border:1px solid #000}.table{border-collapse:collapse!important}.table td,.table th{background-color:#fff!important}.table-bordered td,.table-bordered th{border:1px solid #ddd!important}}@font-face{font-family:'Glyphicons Halflings';src:url(../fonts/glyphicons-halflings-regular.eot);src:url(../fonts/glyphicons-halflings-regular.eot?#iefix) format('embedded-opentype'),url(../fonts/glyphicons-halflings-regular.woff2) format('woff2'),url(../fonts/glyphicons-halflings-regular.woff) format('woff'),url(../fonts/glyphicons-halflings-regular.ttf) format('truetype'),url(../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular) format('svg')}.glyphicon{position:relative;top:1px;display:inline-block;font-family:'Glyphicons Halflings';font-style:normal;font-weight:400;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.glyphicon-asterisk:before{content:"\002a"}.glyphicon-plus:before{content:"\002b"}.glyphicon-eur:before,.glyphicon-euro:before{content:"\20ac"}.glyphicon-minus:before{content:"\2212"}.glyphicon-cloud:before{content:"\2601"}.glyphicon-envelope:before{content:"\2709"}.glyphicon-pencil:before{content:"\270f"}.glyphicon-glass:before{content:"\e001"}.glyphicon-music:before{content:"\e002"}.glyphicon-search:before{content:"\e003"}.glyphicon-heart:before{content:"\e005"}.glyphicon-star:before{content:"\e006"}.glyphicon-star-empty:before{content:"\e007"}.glyphicon-user:before{content:"\e008"}.glyphicon-film:before{content:"\e009"}.glyphicon-th-large:before{content:"\e010"}.glyphicon-th:before{content:"\e011"}.glyphicon-th-list:before{content:"\e012"}.glyphicon-ok:before{content:"\e013"}.glyphicon-remove:before{content:"\e014"}.glyphicon-zoom-in:before{content:"\e015"}.glyphicon-zoom-out:before{content:"\e016"}.glyphicon-off:before{content:"\e017"}.glyphicon-signal:before{content:"\e018"}.glyphicon-cog:before{content:"\e019"}.glyphicon-trash:before{content:"\e020"}.glyphicon-home:before{content:"\e021"}.glyphicon-file:before{content:"\e022"}.glyphicon-time:before{content:"\e023"}.glyphicon-road:before{content:"\e024"}.glyphicon-download-alt:before{content:"\e025"}.glyphicon-download:before{content:"\e026"}.glyphicon-upload:before{content:"\e027"}.glyphicon-inbox:before{content:"\e028"}.glyphicon-play-circle:before{content:"\e029"}.glyphicon-repeat:before{content:"\e030"}.glyphicon-refresh:before{content:"\e031"}.glyphicon-list-alt:before{content:"\e032"}.glyphicon-lock:before{content:"\e033"}.glyphicon-flag:before{content:"\e034"}.glyphicon-headphones:before{content:"\e035"}.glyphicon-volume-off:before{content:"\e036"}.glyphicon-volume-down:before{content:"\e037"}.glyphicon-volume-up:before{content:"\e038"}.glyphicon-qrcode:before{content:"\e039"}.glyphicon-barcode:before{content:"\e040"}.glyphicon-tag:before{content:"\e041"}.glyphicon-tags:before{content:"\e042"}.glyphicon-book:before{content:"\e043"}.glyphicon-bookmark:before{content:"\e044"}.glyphicon-print:before{content:"\e045"}.glyphicon-camera:before{content:"\e046"}.glyphicon-font:before{content:"\e047"}.glyphicon-bold:before{content:"\e048"}.glyphicon-italic:before{content:"\e049"}.glyphicon-text-height:before{content:"\e050"}.glyphicon-text-width:before{content:"\e051"}.glyphicon-align-left:before{content:"\e052"}.glyphicon-align-center:before{content:"\e053"}.glyphicon-align-right:before{content:"\e054"}.glyphicon-align-justify:before{content:"\e055"}.glyphicon-list:before{content:"\e056"}.glyphicon-indent-left:before{content:"\e057"}.glyphicon-indent-right:before{content:"\e058"}.glyphicon-facetime-video:before{content:"\e059"}.glyphicon-picture:before{content:"\e060"}.glyphicon-map-marker:before{content:"\e062"}.glyphicon-adjust:before{content:"\e063"}.glyphicon-tint:before{content:"\e064"}.glyphicon-edit:before{content:"\e065"}.glyphicon-share:before{content:"\e066"}.glyphicon-check:before{content:"\e067"}.glyphicon-move:before{content:"\e068"}.glyphicon-step-backward:before{content:"\e069"}.glyphicon-fast-backward:before{content:"\e070"}.glyphicon-backward:before{content:"\e071"}.glyphicon-play:before{content:"\e072"}.glyphicon-pause:before{content:"\e073"}.glyphicon-stop:before{content:"\e074"}.glyphicon-forward:before{content:"\e075"}.glyphicon-fast-forward:before{content:"\e076"}.glyphicon-step-forward:before{content:"\e077"}.glyphicon-eject:before{content:"\e078"}.glyphicon-chevron-left:before{content:"\e079"}.glyphicon-chevron-right:before{content:"\e080"}.glyphicon-plus-sign:before{content:"\e081"}.glyphicon-minus-sign:before{content:"\e082"}.glyphicon-remove-sign:before{content:"\e083"}.glyphicon-ok-sign:before{content:"\e084"}.glyphicon-question-sign:before{content:"\e085"}.glyphicon-info-sign:before{content:"\e086"}.glyphicon-screenshot:before{content:"\e087"}.glyphicon-remove-circle:before{content:"\e088"}.glyphicon-ok-circle:before{content:"\e089"}.glyphicon-ban-circle:before{content:"\e090"}.glyphicon-arrow-left:before{content:"\e091"}.glyphicon-arrow-right:before{content:"\e092"}.glyphicon-arrow-up:before{content:"\e093"}.glyphicon-arrow-down:before{content:"\e094"}.glyphicon-share-alt:before{content:"\e095"}.glyphicon-resize-full:before{content:"\e096"}.glyphicon-resize-small:before{content:"\e097"}.glyphicon-exclamation-sign:before{content:"\e101"}.glyphicon-gift:before{content:"\e102"}.glyphicon-leaf:before{content:"\e103"}.glyphicon-fire:before{content:"\e104"}.glyphicon-eye-open:before{content:"\e105"}.glyphicon-eye-close:before{content:"\e106"}.glyphicon-warning-sign:before{content:"\e107"}.glyphicon-plane:before{content:"\e108"}.glyphicon-calendar:before{content:"\e109"}.glyphicon-random:before{content:"\e110"}.glyphicon-comment:before{content:"\e111"}.glyphicon-magnet:before{content:"\e112"}.glyphicon-chevron-up:before{content:"\e113"}.glyphicon-chevron-down:before{content:"\e114"}.glyphicon-retweet:before{content:"\e115"}.glyphicon-shopping-cart:before{content:"\e116"}.glyphicon-folder-close:before{content:"\e117"}.glyphicon-folder-open:before{content:"\e118"}.glyphicon-resize-vertical:before{content:"\e119"}.glyphicon-resize-horizontal:before{content:"\e120"}.glyphicon-hdd:before{content:"\e121"}.glyphicon-bullhorn:before{content:"\e122"}.glyphicon-bell:before{content:"\e123"}.glyphicon-certificate:before{content:"\e124"}.glyphicon-thumbs-up:before{content:"\e125"}.glyphicon-thumbs-down:before{content:"\e126"}.glyphicon-hand-right:before{content:"\e127"}.glyphicon-hand-left:before{content:"\e128"}.glyphicon-hand-up:before{content:"\e129"}.glyphicon-hand-down:before{content:"\e130"}.glyphicon-circle-arrow-right:before{content:"\e131"}.glyphicon-circle-arrow-left:before{content:"\e132"}.glyphicon-circle-arrow-up:before{content:"\e133"}.glyphicon-circle-arrow-down:before{content:"\e134"}.glyphicon-globe:before{content:"\e135"}.glyphicon-wrench:before{content:"\e136"}.glyphicon-tasks:before{content:"\e137"}.glyphicon-filter:before{content:"\e138"}.glyphicon-briefcase:before{content:"\e139"}.glyphicon-fullscreen:before{content:"\e140"}.glyphicon-dashboard:before{content:"\e141"}.glyphicon-paperclip:before{content:"\e142"}.glyphicon-heart-empty:before{content:"\e143"}.glyphicon-link:before{content:"\e144"}.glyphicon-phone:before{content:"\e145"}.glyphicon-pushpin:before{content:"\e146"}.glyphicon-usd:before{content:"\e148"}.glyphicon-gbp:before{content:"\e149"}.glyphicon-sort:before{content:"\e150"}.glyphicon-sort-by-alphabet:before{content:"\e151"}.glyphicon-sort-by-alphabet-alt:before{content:"\e152"}.glyphicon-sort-by-order:before{content:"\e153"}.glyphicon-sort-by-order-alt:before{content:"\e154"}.glyphicon-sort-by-attributes:before{content:"\e155"}.glyphicon-sort-by-attributes-alt:before{content:"\e156"}.glyphicon-unchecked:before{content:"\e157"}.glyphicon-expand:before{content:"\e158"}.glyphicon-collapse-down:before{content:"\e159"}.glyphicon-collapse-up:before{content:"\e160"}.glyphicon-log-in:before{content:"\e161"}.glyphicon-flash:before{content:"\e162"}.glyphicon-log-out:before{content:"\e163"}.glyphicon-new-window:before{content:"\e164"}.glyphicon-record:before{content:"\e165"}.glyphicon-save:before{content:"\e166"}.glyphicon-open:before{content:"\e167"}.glyphicon-saved:before{content:"\e168"}.glyphicon-import:before{content:"\e169"}.glyphicon-export:before{content:"\e170"}.glyphicon-send:before{content:"\e171"}.glyphicon-floppy-disk:before{content:"\e172"}.glyphicon-floppy-saved:before{content:"\e173"}.glyphicon-floppy-remove:before{content:"\e174"}.glyphicon-floppy-save:before{content:"\e175"}.glyphicon-floppy-open:before{content:"\e176"}.glyphicon-credit-card:before{content:"\e177"}.glyphicon-transfer:before{content:"\e178"}.glyphicon-cutlery:before{content:"\e179"}.glyphicon-header:before{content:"\e180"}.glyphicon-compressed:before{content:"\e181"}.glyphicon-earphone:before{content:"\e182"}.glyphicon-phone-alt:before{content:"\e183"}.glyphicon-tower:before{content:"\e184"}.glyphicon-stats:before{content:"\e185"}.glyphicon-sd-video:before{content:"\e186"}.glyphicon-hd-video:before{content:"\e187"}.glyphicon-subtitles:before{content:"\e188"}.glyphicon-sound-stereo:before{content:"\e189"}.glyphicon-sound-dolby:before{content:"\e190"}.glyphicon-sound-5-1:before{content:"\e191"}.glyphicon-sound-6-1:before{content:"\e192"}.glyphicon-sound-7-1:before{content:"\e193"}.glyphicon-copyright-mark:before{content:"\e194"}.glyphicon-registration-mark:before{content:"\e195"}.glyphicon-cloud-download:before{content:"\e197"}.glyphicon-cloud-upload:before{content:"\e198"}.glyphicon-tree-conifer:before{content:"\e199"}.glyphicon-tree-deciduous:before{content:"\e200"}.glyphicon-cd:before{content:"\e201"}.glyphicon-save-file:before{content:"\e202"}.glyphicon-open-file:before{content:"\e203"}.glyphicon-level-up:before{content:"\e204"}.glyphicon-copy:before{content:"\e205"}.glyphicon-paste:before{content:"\e206"}.glyphicon-alert:before{content:"\e209"}.glyphicon-equalizer:before{content:"\e210"}.glyphicon-king:before{content:"\e211"}.glyphicon-queen:before{content:"\e212"}.glyphicon-pawn:before{content:"\e213"}.glyphicon-bishop:before{content:"\e214"}.glyphicon-knight:before{content:"\e215"}.glyphicon-baby-formula:before{content:"\e216"}.glyphicon-tent:before{content:"\26fa"}.glyphicon-blackboard:before{content:"\e218"}.glyphicon-bed:before{content:"\e219"}.glyphicon-apple:before{content:"\f8ff"}.glyphicon-erase:before{content:"\e221"}.glyphicon-hourglass:before{content:"\231b"}.glyphicon-lamp:before{content:"\e223"}.glyphicon-duplicate:before{content:"\e224"}.glyphicon-piggy-bank:before{content:"\e225"}.glyphicon-scissors:before{content:"\e226"}.glyphicon-bitcoin:before{content:"\e227"}.glyphicon-btc:before{content:"\e227"}.glyphicon-xbt:before{content:"\e227"}.glyphicon-yen:before{content:"\00a5"}.glyphicon-jpy:before{content:"\00a5"}.glyphicon-ruble:before{content:"\20bd"}.glyphicon-rub:before{content:"\20bd"}.glyphicon-scale:before{content:"\e230"}.glyphicon-ice-lolly:before{content:"\e231"}.glyphicon-ice-lolly-tasted:before{content:"\e232"}.glyphicon-education:before{content:"\e233"}.glyphicon-option-horizontal:before{content:"\e234"}.glyphicon-option-vertical:before{content:"\e235"}.glyphicon-menu-hamburger:before{content:"\e236"}.glyphicon-modal-window:before{content:"\e237"}.glyphicon-oil:before{content:"\e238"}.glyphicon-grain:before{content:"\e239"}.glyphicon-sunglasses:before{content:"\e240"}.glyphicon-text-size:before{content:"\e241"}.glyphicon-text-color:before{content:"\e242"}.glyphicon-text-background:before{content:"\e243"}.glyphicon-object-align-top:before{content:"\e244"}.glyphicon-object-align-bottom:before{content:"\e245"}.glyphicon-object-align-horizontal:before{content:"\e246"}.glyphicon-object-align-left:before{content:"\e247"}.glyphicon-object-align-vertical:before{content:"\e248"}.glyphicon-object-align-right:before{content:"\e249"}.glyphicon-triangle-right:before{content:"\e250"}.glyphicon-triangle-left:before{content:"\e251"}.glyphicon-triangle-bottom:before{content:"\e252"}.glyphicon-triangle-top:before{content:"\e253"}.glyphicon-console:before{content:"\e254"}.glyphicon-superscript:before{content:"\e255"}.glyphicon-subscript:before{content:"\e256"}.glyphicon-menu-left:before{content:"\e257"}.glyphicon-menu-right:before{content:"\e258"}.glyphicon-menu-down:before{content:"\e259"}.glyphicon-menu-up:before{content:"\e260"}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}:after,:before{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:10px;-webkit-tap-highlight-color:rgba(0,0,0,0)}body{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:1.42857143;color:#333;background-color:#fff}button,input,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}a{color:#337ab7;text-decoration:none}a:focus,a:hover{color:#23527c;text-decoration:underline}a:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}figure{margin:0}img{vertical-align:middle}.carousel-inner>.item>a>img,.carousel-inner>.item>img,.img-responsive,.thumbnail a>img,.thumbnail>img{display:block;max-width:100%;height:auto}.img-rounded{border-radius:6px}.img-thumbnail{display:inline-block;max-width:100%;height:auto;padding:4px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.img-circle{border-radius:50%}hr{margin-top:20px;margin-bottom:20px;border:0;border-top:1px solid #eee}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}[role=button]{cursor:pointer}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{font-family:inherit;font-weight:500;line-height:1.1;color:inherit}.h1 .small,.h1 small,.h2 .small,.h2 small,.h3 .small,.h3 small,.h4 .small,.h4 small,.h5 .small,.h5 small,.h6 .small,.h6 small,h1 .small,h1 small,h2 .small,h2 small,h3 .small,h3 small,h4 .small,h4 small,h5 .small,h5 small,h6 .small,h6 small{font-weight:400;line-height:1;color:#777}.h1,.h2,.h3,h1,h2,h3{margin-top:20px;margin-bottom:10px}.h1 .small,.h1 small,.h2 .small,.h2 small,.h3 .small,.h3 small,h1 .small,h1 small,h2 .small,h2 small,h3 .small,h3 small{font-size:65%}.h4,.h5,.h6,h4,h5,h6{margin-top:10px;margin-bottom:10px}.h4 .small,.h4 small,.h5 .small,.h5 small,.h6 .small,.h6 small,h4 .small,h4 small,h5 .small,h5 small,h6 .small,h6 small{font-size:75%}.h1,h1{font-size:36px}.h2,h2{font-size:30px}.h3,h3{font-size:24px}.h4,h4{font-size:18px}.h5,h5{font-size:14px}.h6,h6{font-size:12px}p{margin:0 0 10px}.lead{margin-bottom:20px;font-size:16px;font-weight:300;line-height:1.4}@media (min-width:768px){.lead{font-size:21px}}.small,small{font-size:85%}.mark,mark{padding:.2em;background-color:#fcf8e3}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}.text-justify{text-align:justify}.text-nowrap{white-space:nowrap}.text-lowercase{text-transform:lowercase}.text-uppercase{text-transform:uppercase}.text-capitalize{text-transform:capitalize}.text-muted{color:#777}.text-primary{color:#337ab7}a.text-primary:focus,a.text-primary:hover{color:#286090}.text-success{color:#3c763d}a.text-success:focus,a.text-success:hover{color:#2b542c}.text-info{color:#31708f}a.text-info:focus,a.text-info:hover{color:#245269}.text-warning{color:#8a6d3b}a.text-warning:focus,a.text-warning:hover{color:#66512c}.text-danger{color:#a94442}a.text-danger:focus,a.text-danger:hover{color:#843534}.bg-primary{color:#fff;background-color:#337ab7}a.bg-primary:focus,a.bg-primary:hover{background-color:#286090}.bg-success{background-color:#dff0d8}a.bg-success:focus,a.bg-success:hover{background-color:#c1e2b3}.bg-info{background-color:#d9edf7}a.bg-info:focus,a.bg-info:hover{background-color:#afd9ee}.bg-warning{background-color:#fcf8e3}a.bg-warning:focus,a.bg-warning:hover{background-color:#f7ecb5}.bg-danger{background-color:#f2dede}a.bg-danger:focus,a.bg-danger:hover{background-color:#e4b9b9}.page-header{padding-bottom:9px;margin:40px 0 20px;border-bottom:1px solid #eee}ol,ul{margin-top:0;margin-bottom:10px}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;margin-left:-5px;list-style:none}.list-inline>li{display:inline-block;padding-right:5px;padding-left:5px}dl{margin-top:0;margin-bottom:20px}dd,dt{line-height:1.42857143}dt{font-weight:700}dd{margin-left:0}@media (min-width:768px){.dl-horizontal dt{float:left;width:160px;overflow:hidden;clear:left;text-align:right;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}}abbr[data-original-title],abbr[title]{cursor:help;border-bottom:1px dotted #777}.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:10px 20px;margin:0 0 20px;font-size:17.5px;border-left:5px solid #eee}blockquote ol:last-child,blockquote p:last-child,blockquote ul:last-child{margin-bottom:0}blockquote .small,blockquote footer,blockquote small{display:block;font-size:80%;line-height:1.42857143;color:#777}blockquote .small:before,blockquote footer:before,blockquote small:before{content:'\2014 \00A0'}.blockquote-reverse,blockquote.pull-right{padding-right:15px;padding-left:0;text-align:right;border-right:5px solid #eee;border-left:0}.blockquote-reverse .small:before,.blockquote-reverse footer:before,.blockquote-reverse small:before,blockquote.pull-right .small:before,blockquote.pull-right footer:before,blockquote.pull-right small:before{content:''}.blockquote-reverse .small:after,.blockquote-reverse footer:after,.blockquote-reverse small:after,blockquote.pull-right .small:after,blockquote.pull-right footer:after,blockquote.pull-right small:after{content:'\00A0 \2014'}address{margin-bottom:20px;font-style:normal;line-height:1.42857143}code,kbd,pre,samp{font-family:Menlo,Monaco,Consolas,"Courier New",monospace}code{padding:2px 4px;font-size:90%;color:#c7254e;background-color:#f9f2f4;border-radius:4px}kbd{padding:2px 4px;font-size:90%;color:#fff;background-color:#333;border-radius:3px;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.25);box-shadow:inset 0 -1px 0 rgba(0,0,0,.25)}kbd kbd{padding:0;font-size:100%;font-weight:700;-webkit-box-shadow:none;box-shadow:none}pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:1.42857143;color:#333;word-break:break-all;word-wrap:break-word;background-color:#f5f5f5;border:1px solid #ccc;border-radius:4px}pre code{padding:0;font-size:inherit;color:inherit;white-space:pre-wrap;background-color:transparent;border-radius:0}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}@media (min-width:768px){.container{width:750px}}@media (min-width:992px){.container{width:970px}}@media (min-width:1200px){.container{width:1170px}}.container-fluid{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}.row{margin-right:-15px;margin-left:-15px}.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9{position:relative;min-height:1px;padding-right:15px;padding-left:15px}.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9{float:left}.col-xs-12{width:100%}.col-xs-11{width:91.66666667%}.col-xs-10{width:83.33333333%}.col-xs-9{width:75%}.col-xs-8{width:66.66666667%}.col-xs-7{width:58.33333333%}.col-xs-6{width:50%}.col-xs-5{width:41.66666667%}.col-xs-4{width:33.33333333%}.col-xs-3{width:25%}.col-xs-2{width:16.66666667%}.col-xs-1{width:8.33333333%}.col-xs-pull-12{right:100%}.col-xs-pull-11{right:91.66666667%}.col-xs-pull-10{right:83.33333333%}.col-xs-pull-9{right:75%}.col-xs-pull-8{right:66.66666667%}.col-xs-pull-7{right:58.33333333%}.col-xs-pull-6{right:50%}.col-xs-pull-5{right:41.66666667%}.col-xs-pull-4{right:33.33333333%}.col-xs-pull-3{right:25%}.col-xs-pull-2{right:16.66666667%}.col-xs-pull-1{right:8.33333333%}.col-xs-pull-0{right:auto}.col-xs-push-12{left:100%}.col-xs-push-11{left:91.66666667%}.col-xs-push-10{left:83.33333333%}.col-xs-push-9{left:75%}.col-xs-push-8{left:66.66666667%}.col-xs-push-7{left:58.33333333%}.col-xs-push-6{left:50%}.col-xs-push-5{left:41.66666667%}.col-xs-push-4{left:33.33333333%}.col-xs-push-3{left:25%}.col-xs-push-2{left:16.66666667%}.col-xs-push-1{left:8.33333333%}.col-xs-push-0{left:auto}.col-xs-offset-12{margin-left:100%}.col-xs-offset-11{margin-left:91.66666667%}.col-xs-offset-10{margin-left:83.33333333%}.col-xs-offset-9{margin-left:75%}.col-xs-offset-8{margin-left:66.66666667%}.col-xs-offset-7{margin-left:58.33333333%}.col-xs-offset-6{margin-left:50%}.col-xs-offset-5{margin-left:41.66666667%}.col-xs-offset-4{margin-left:33.33333333%}.col-xs-offset-3{margin-left:25%}.col-xs-offset-2{margin-left:16.66666667%}.col-xs-offset-1{margin-left:8.33333333%}.col-xs-offset-0{margin-left:0}@media (min-width:768px){.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9{float:left}.col-sm-12{width:100%}.col-sm-11{width:91.66666667%}.col-sm-10{width:83.33333333%}.col-sm-9{width:75%}.col-sm-8{width:66.66666667%}.col-sm-7{width:58.33333333%}.col-sm-6{width:50%}.col-sm-5{width:41.66666667%}.col-sm-4{width:33.33333333%}.col-sm-3{width:25%}.col-sm-2{width:16.66666667%}.col-sm-1{width:8.33333333%}.col-sm-pull-12{right:100%}.col-sm-pull-11{right:91.66666667%}.col-sm-pull-10{right:83.33333333%}.col-sm-pull-9{right:75%}.col-sm-pull-8{right:66.66666667%}.col-sm-pull-7{right:58.33333333%}.col-sm-pull-6{right:50%}.col-sm-pull-5{right:41.66666667%}.col-sm-pull-4{right:33.33333333%}.col-sm-pull-3{right:25%}.col-sm-pull-2{right:16.66666667%}.col-sm-pull-1{right:8.33333333%}.col-sm-pull-0{right:auto}.col-sm-push-12{left:100%}.col-sm-push-11{left:91.66666667%}.col-sm-push-10{left:83.33333333%}.col-sm-push-9{left:75%}.col-sm-push-8{left:66.66666667%}.col-sm-push-7{left:58.33333333%}.col-sm-push-6{left:50%}.col-sm-push-5{left:41.66666667%}.col-sm-push-4{left:33.33333333%}.col-sm-push-3{left:25%}.col-sm-push-2{left:16.66666667%}.col-sm-push-1{left:8.33333333%}.col-sm-push-0{left:auto}.col-sm-offset-12{margin-left:100%}.col-sm-offset-11{margin-left:91.66666667%}.col-sm-offset-10{margin-left:83.33333333%}.col-sm-offset-9{margin-left:75%}.col-sm-offset-8{margin-left:66.66666667%}.col-sm-offset-7{margin-left:58.33333333%}.col-sm-offset-6{margin-left:50%}.col-sm-offset-5{margin-left:41.66666667%}.col-sm-offset-4{margin-left:33.33333333%}.col-sm-offset-3{margin-left:25%}.col-sm-offset-2{margin-left:16.66666667%}.col-sm-offset-1{margin-left:8.33333333%}.col-sm-offset-0{margin-left:0}}@media (min-width:992px){.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9{float:left}.col-md-12{width:100%}.col-md-11{width:91.66666667%}.col-md-10{width:83.33333333%}.col-md-9{width:75%}.col-md-8{width:66.66666667%}.col-md-7{width:58.33333333%}.col-md-6{width:50%}.col-md-5{width:41.66666667%}.col-md-4{width:33.33333333%}.col-md-3{width:25%}.col-md-2{width:16.66666667%}.col-md-1{width:8.33333333%}.col-md-pull-12{right:100%}.col-md-pull-11{right:91.66666667%}.col-md-pull-10{right:83.33333333%}.col-md-pull-9{right:75%}.col-md-pull-8{right:66.66666667%}.col-md-pull-7{right:58.33333333%}.col-md-pull-6{right:50%}.col-md-pull-5{right:41.66666667%}.col-md-pull-4{right:33.33333333%}.col-md-pull-3{right:25%}.col-md-pull-2{right:16.66666667%}.col-md-pull-1{right:8.33333333%}.col-md-pull-0{right:auto}.col-md-push-12{left:100%}.col-md-push-11{left:91.66666667%}.col-md-push-10{left:83.33333333%}.col-md-push-9{left:75%}.col-md-push-8{left:66.66666667%}.col-md-push-7{left:58.33333333%}.col-md-push-6{left:50%}.col-md-push-5{left:41.66666667%}.col-md-push-4{left:33.33333333%}.col-md-push-3{left:25%}.col-md-push-2{left:16.66666667%}.col-md-push-1{left:8.33333333%}.col-md-push-0{left:auto}.col-md-offset-12{margin-left:100%}.col-md-offset-11{margin-left:91.66666667%}.col-md-offset-10{margin-left:83.33333333%}.col-md-offset-9{margin-left:75%}.col-md-offset-8{margin-left:66.66666667%}.col-md-offset-7{margin-left:58.33333333%}.col-md-offset-6{margin-left:50%}.col-md-offset-5{margin-left:41.66666667%}.col-md-offset-4{margin-left:33.33333333%}.col-md-offset-3{margin-left:25%}.col-md-offset-2{margin-left:16.66666667%}.col-md-offset-1{margin-left:8.33333333%}.col-md-offset-0{margin-left:0}}@media (min-width:1200px){.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9{float:left}.col-lg-12{width:100%}.col-lg-11{width:91.66666667%}.col-lg-10{width:83.33333333%}.col-lg-9{width:75%}.col-lg-8{width:66.66666667%}.col-lg-7{width:58.33333333%}.col-lg-6{width:50%}.col-lg-5{width:41.66666667%}.col-lg-4{width:33.33333333%}.col-lg-3{width:25%}.col-lg-2{width:16.66666667%}.col-lg-1{width:8.33333333%}.col-lg-pull-12{right:100%}.col-lg-pull-11{right:91.66666667%}.col-lg-pull-10{right:83.33333333%}.col-lg-pull-9{right:75%}.col-lg-pull-8{right:66.66666667%}.col-lg-pull-7{right:58.33333333%}.col-lg-pull-6{right:50%}.col-lg-pull-5{right:41.66666667%}.col-lg-pull-4{right:33.33333333%}.col-lg-pull-3{right:25%}.col-lg-pull-2{right:16.66666667%}.col-lg-pull-1{right:8.33333333%}.col-lg-pull-0{right:auto}.col-lg-push-12{left:100%}.col-lg-push-11{left:91.66666667%}.col-lg-push-10{left:83.33333333%}.col-lg-push-9{left:75%}.col-lg-push-8{left:66.66666667%}.col-lg-push-7{left:58.33333333%}.col-lg-push-6{left:50%}.col-lg-push-5{left:41.66666667%}.col-lg-push-4{left:33.33333333%}.col-lg-push-3{left:25%}.col-lg-push-2{left:16.66666667%}.col-lg-push-1{left:8.33333333%}.col-lg-push-0{left:auto}.col-lg-offset-12{margin-left:100%}.col-lg-offset-11{margin-left:91.66666667%}.col-lg-offset-10{margin-left:83.33333333%}.col-lg-offset-9{margin-left:75%}.col-lg-offset-8{margin-left:66.66666667%}.col-lg-offset-7{margin-left:58.33333333%}.col-lg-offset-6{margin-left:50%}.col-lg-offset-5{margin-left:41.66666667%}.col-lg-offset-4{margin-left:33.33333333%}.col-lg-offset-3{margin-left:25%}.col-lg-offset-2{margin-left:16.66666667%}.col-lg-offset-1{margin-left:8.33333333%}.col-lg-offset-0{margin-left:0}}table{background-color:transparent}caption{padding-top:8px;padding-bottom:8px;color:#777;text-align:left}th{text-align:left}.table{width:100%;max-width:100%;margin-bottom:20px}.table>tbody>tr>td,.table>tbody>tr>th,.table>tfoot>tr>td,.table>tfoot>tr>th,.table>thead>tr>td,.table>thead>tr>th{padding:8px;line-height:1.42857143;vertical-align:top;border-top:1px solid #ddd}.table>thead>tr>th{vertical-align:bottom;border-bottom:2px solid #ddd}.table>caption+thead>tr:first-child>td,.table>caption+thead>tr:first-child>th,.table>colgroup+thead>tr:first-child>td,.table>colgroup+thead>tr:first-child>th,.table>thead:first-child>tr:first-child>td,.table>thead:first-child>tr:first-child>th{border-top:0}.table>tbody+tbody{border-top:2px solid #ddd}.table .table{background-color:#fff}.table-condensed>tbody>tr>td,.table-condensed>tbody>tr>th,.table-condensed>tfoot>tr>td,.table-condensed>tfoot>tr>th,.table-condensed>thead>tr>td,.table-condensed>thead>tr>th{padding:5px}.table-bordered{border:1px solid #ddd}.table-bordered>tbody>tr>td,.table-bordered>tbody>tr>th,.table-bordered>tfoot>tr>td,.table-bordered>tfoot>tr>th,.table-bordered>thead>tr>td,.table-bordered>thead>tr>th{border:1px solid #ddd}.table-bordered>thead>tr>td,.table-bordered>thead>tr>th{border-bottom-width:2px}.table-striped>tbody>tr:nth-of-type(odd){background-color:#f9f9f9}.table-hover>tbody>tr:hover{background-color:#f5f5f5}table col[class*=col-]{position:static;display:table-column;float:none}table td[class*=col-],table th[class*=col-]{position:static;display:table-cell;float:none}.table>tbody>tr.active>td,.table>tbody>tr.active>th,.table>tbody>tr>td.active,.table>tbody>tr>th.active,.table>tfoot>tr.active>td,.table>tfoot>tr.active>th,.table>tfoot>tr>td.active,.table>tfoot>tr>th.active,.table>thead>tr.active>td,.table>thead>tr.active>th,.table>thead>tr>td.active,.table>thead>tr>th.active{background-color:#f5f5f5}.table-hover>tbody>tr.active:hover>td,.table-hover>tbody>tr.active:hover>th,.table-hover>tbody>tr:hover>.active,.table-hover>tbody>tr>td.active:hover,.table-hover>tbody>tr>th.active:hover{background-color:#e8e8e8}.table>tbody>tr.success>td,.table>tbody>tr.success>th,.table>tbody>tr>td.success,.table>tbody>tr>th.success,.table>tfoot>tr.success>td,.table>tfoot>tr.success>th,.table>tfoot>tr>td.success,.table>tfoot>tr>th.success,.table>thead>tr.success>td,.table>thead>tr.success>th,.table>thead>tr>td.success,.table>thead>tr>th.success{background-color:#dff0d8}.table-hover>tbody>tr.success:hover>td,.table-hover>tbody>tr.success:hover>th,.table-hover>tbody>tr:hover>.success,.table-hover>tbody>tr>td.success:hover,.table-hover>tbody>tr>th.success:hover{background-color:#d0e9c6}.table>tbody>tr.info>td,.table>tbody>tr.info>th,.table>tbody>tr>td.info,.table>tbody>tr>th.info,.table>tfoot>tr.info>td,.table>tfoot>tr.info>th,.table>tfoot>tr>td.info,.table>tfoot>tr>th.info,.table>thead>tr.info>td,.table>thead>tr.info>th,.table>thead>tr>td.info,.table>thead>tr>th.info{background-color:#d9edf7}.table-hover>tbody>tr.info:hover>td,.table-hover>tbody>tr.info:hover>th,.table-hover>tbody>tr:hover>.info,.table-hover>tbody>tr>td.info:hover,.table-hover>tbody>tr>th.info:hover{background-color:#c4e3f3}.table>tbody>tr.warning>td,.table>tbody>tr.warning>th,.table>tbody>tr>td.warning,.table>tbody>tr>th.warning,.table>tfoot>tr.warning>td,.table>tfoot>tr.warning>th,.table>tfoot>tr>td.warning,.table>tfoot>tr>th.warning,.table>thead>tr.warning>td,.table>thead>tr.warning>th,.table>thead>tr>td.warning,.table>thead>tr>th.warning{background-color:#fcf8e3}.table-hover>tbody>tr.warning:hover>td,.table-hover>tbody>tr.warning:hover>th,.table-hover>tbody>tr:hover>.warning,.table-hover>tbody>tr>td.warning:hover,.table-hover>tbody>tr>th.warning:hover{background-color:#faf2cc}.table>tbody>tr.danger>td,.table>tbody>tr.danger>th,.table>tbody>tr>td.danger,.table>tbody>tr>th.danger,.table>tfoot>tr.danger>td,.table>tfoot>tr.danger>th,.table>tfoot>tr>td.danger,.table>tfoot>tr>th.danger,.table>thead>tr.danger>td,.table>thead>tr.danger>th,.table>thead>tr>td.danger,.table>thead>tr>th.danger{background-color:#f2dede}.table-hover>tbody>tr.danger:hover>td,.table-hover>tbody>tr.danger:hover>th,.table-hover>tbody>tr:hover>.danger,.table-hover>tbody>tr>td.danger:hover,.table-hover>tbody>tr>th.danger:hover{background-color:#ebcccc}.table-responsive{min-height:.01%;overflow-x:auto}@media screen and (max-width:767px){.table-responsive{width:100%;margin-bottom:15px;overflow-y:hidden;-ms-overflow-style:-ms-autohiding-scrollbar;border:1px solid #ddd}.table-responsive>.table{margin-bottom:0}.table-responsive>.table>tbody>tr>td,.table-responsive>.table>tbody>tr>th,.table-responsive>.table>tfoot>tr>td,.table-responsive>.table>tfoot>tr>th,.table-responsive>.table>thead>tr>td,.table-responsive>.table>thead>tr>th{white-space:nowrap}.table-responsive>.table-bordered{border:0}.table-responsive>.table-bordered>tbody>tr>td:first-child,.table-responsive>.table-bordered>tbody>tr>th:first-child,.table-responsive>.table-bordered>tfoot>tr>td:first-child,.table-responsive>.table-bordered>tfoot>tr>th:first-child,.table-responsive>.table-bordered>thead>tr>td:first-child,.table-responsive>.table-bordered>thead>tr>th:first-child{border-left:0}.table-responsive>.table-bordered>tbody>tr>td:last-child,.table-responsive>.table-bordered>tbody>tr>th:last-child,.table-responsive>.table-bordered>tfoot>tr>td:last-child,.table-responsive>.table-bordered>tfoot>tr>th:last-child,.table-responsive>.table-bordered>thead>tr>td:last-child,.table-responsive>.table-bordered>thead>tr>th:last-child{border-right:0}.table-responsive>.table-bordered>tbody>tr:last-child>td,.table-responsive>.table-bordered>tbody>tr:last-child>th,.table-responsive>.table-bordered>tfoot>tr:last-child>td,.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:inherit;color:#333;border:0;border-bottom:1px solid #e5e5e5}label{display:inline-block;max-width:100%;margin-bottom:5px;font-weight:700}input[type=search]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type=checkbox],input[type=radio]{margin:4px 0 0;margin-top:1px\9;line-height:normal}input[type=file]{display:block}input[type=range]{display:block;width:100%}select[multiple],select[size]{height:auto}input[type=file]:focus,input[type=checkbox]:focus,input[type=radio]:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}output{display:block;padding-top:7px;font-size:14px;line-height:1.42857143;color:#555}.form-control{display:block;width:100%;height:34px;padding:6px 12px;font-size:14px;line-height:1.42857143;color:#555;background-color:#fff;background-image:none;border:1px solid #ccc;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075);-webkit-transition:border-color ease-in-out .15s,-webkit-box-shadow ease-in-out .15s;-o-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s}.form-control:focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6)}.form-control::-moz-placeholder{color:#999;opacity:1}.form-control:-ms-input-placeholder{color:#999}.form-control::-webkit-input-placeholder{color:#999}.form-control::-ms-expand{background-color:transparent;border:0}.form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{background-color:#eee;opacity:1}.form-control[disabled],fieldset[disabled] .form-control{cursor:not-allowed}textarea.form-control{height:auto}input[type=search]{-webkit-appearance:none}@media screen and (-webkit-min-device-pixel-ratio:0){input[type=date].form-control,input[type=time].form-control,input[type=datetime-local].form-control,input[type=month].form-control{line-height:34px}.input-group-sm input[type=date],.input-group-sm input[type=time],.input-group-sm input[type=datetime-local],.input-group-sm input[type=month],input[type=date].input-sm,input[type=time].input-sm,input[type=datetime-local].input-sm,input[type=month].input-sm{line-height:30px}.input-group-lg input[type=date],.input-group-lg input[type=time],.input-group-lg input[type=datetime-local],.input-group-lg input[type=month],input[type=date].input-lg,input[type=time].input-lg,input[type=datetime-local].input-lg,input[type=month].input-lg{line-height:46px}}.form-group{margin-bottom:15px}.checkbox,.radio{position:relative;display:block;margin-top:10px;margin-bottom:10px}.checkbox label,.radio label{min-height:20px;padding-left:20px;margin-bottom:0;font-weight:400;cursor:pointer}.checkbox input[type=checkbox],.checkbox-inline input[type=checkbox],.radio input[type=radio],.radio-inline input[type=radio]{position:absolute;margin-top:4px\9;margin-left:-20px}.checkbox+.checkbox,.radio+.radio{margin-top:-5px}.checkbox-inline,.radio-inline{position:relative;display:inline-block;padding-left:20px;margin-bottom:0;font-weight:400;vertical-align:middle;cursor:pointer}.checkbox-inline+.checkbox-inline,.radio-inline+.radio-inline{margin-top:0;margin-left:10px}fieldset[disabled] input[type=checkbox],fieldset[disabled] input[type=radio],input[type=checkbox].disabled,input[type=checkbox][disabled],input[type=radio].disabled,input[type=radio][disabled]{cursor:not-allowed}.checkbox-inline.disabled,.radio-inline.disabled,fieldset[disabled] .checkbox-inline,fieldset[disabled] .radio-inline{cursor:not-allowed}.checkbox.disabled label,.radio.disabled label,fieldset[disabled] .checkbox label,fieldset[disabled] .radio label{cursor:not-allowed}.form-control-static{min-height:34px;padding-top:7px;padding-bottom:7px;margin-bottom:0}.form-control-static.input-lg,.form-control-static.input-sm{padding-right:0;padding-left:0}.input-sm{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-sm{height:30px;line-height:30px}select[multiple].input-sm,textarea.input-sm{height:auto}.form-group-sm .form-control{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.form-group-sm select.form-control{height:30px;line-height:30px}.form-group-sm select[multiple].form-control,.form-group-sm textarea.form-control{height:auto}.form-group-sm .form-control-static{height:30px;min-height:32px;padding:6px 10px;font-size:12px;line-height:1.5}.input-lg{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}select.input-lg{height:46px;line-height:46px}select[multiple].input-lg,textarea.input-lg{height:auto}.form-group-lg .form-control{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}.form-group-lg select.form-control{height:46px;line-height:46px}.form-group-lg select[multiple].form-control,.form-group-lg textarea.form-control{height:auto}.form-group-lg .form-control-static{height:46px;min-height:38px;padding:11px 16px;font-size:18px;line-height:1.3333333}.has-feedback{position:relative}.has-feedback .form-control{padding-right:42.5px}.form-control-feedback{position:absolute;top:0;right:0;z-index:2;display:block;width:34px;height:34px;line-height:34px;text-align:center;pointer-events:none}.form-group-lg .form-control+.form-control-feedback,.input-group-lg+.form-control-feedback,.input-lg+.form-control-feedback{width:46px;height:46px;line-height:46px}.form-group-sm .form-control+.form-control-feedback,.input-group-sm+.form-control-feedback,.input-sm+.form-control-feedback{width:30px;height:30px;line-height:30px}.has-success .checkbox,.has-success .checkbox-inline,.has-success .control-label,.has-success .help-block,.has-success .radio,.has-success .radio-inline,.has-success.checkbox label,.has-success.checkbox-inline label,.has-success.radio label,.has-success.radio-inline label{color:#3c763d}.has-success .form-control{border-color:#3c763d;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-success .form-control:focus{border-color:#2b542c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168}.has-success .input-group-addon{color:#3c763d;background-color:#dff0d8;border-color:#3c763d}.has-success .form-control-feedback{color:#3c763d}.has-warning .checkbox,.has-warning .checkbox-inline,.has-warning .control-label,.has-warning .help-block,.has-warning .radio,.has-warning .radio-inline,.has-warning.checkbox label,.has-warning.checkbox-inline label,.has-warning.radio label,.has-warning.radio-inline label{color:#8a6d3b}.has-warning .form-control{border-color:#8a6d3b;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-warning .form-control:focus{border-color:#66512c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b}.has-warning .input-group-addon{color:#8a6d3b;background-color:#fcf8e3;border-color:#8a6d3b}.has-warning .form-control-feedback{color:#8a6d3b}.has-error .checkbox,.has-error .checkbox-inline,.has-error .control-label,.has-error .help-block,.has-error .radio,.has-error .radio-inline,.has-error.checkbox label,.has-error.checkbox-inline label,.has-error.radio label,.has-error.radio-inline label{color:#a94442}.has-error .form-control{border-color:#a94442;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-error .form-control:focus{border-color:#843534;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483}.has-error .input-group-addon{color:#a94442;background-color:#f2dede;border-color:#a94442}.has-error .form-control-feedback{color:#a94442}.has-feedback label~.form-control-feedback{top:25px}.has-feedback label.sr-only~.form-control-feedback{top:0}.help-block{display:block;margin-top:5px;margin-bottom:10px;color:#737373}@media (min-width:768px){.form-inline .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .form-control-static{display:inline-block}.form-inline .input-group{display:inline-table;vertical-align:middle}.form-inline .input-group .form-control,.form-inline .input-group .input-group-addon,.form-inline .input-group .input-group-btn{width:auto}.form-inline .input-group>.form-control{width:100%}.form-inline .control-label{margin-bottom:0;vertical-align:middle}.form-inline .checkbox,.form-inline .radio{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.form-inline .checkbox label,.form-inline .radio label{padding-left:0}.form-inline .checkbox input[type=checkbox],.form-inline .radio input[type=radio]{position:relative;margin-left:0}.form-inline .has-feedback .form-control-feedback{top:0}}.form-horizontal .checkbox,.form-horizontal .checkbox-inline,.form-horizontal .radio,.form-horizontal .radio-inline{padding-top:7px;margin-top:0;margin-bottom:0}.form-horizontal .checkbox,.form-horizontal .radio{min-height:27px}.form-horizontal .form-group{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.form-horizontal .control-label{padding-top:7px;margin-bottom:0;text-align:right}}.form-horizontal .has-feedback .form-control-feedback{right:15px}@media (min-width:768px){.form-horizontal .form-group-lg .control-label{padding-top:11px;font-size:18px}}@media (min-width:768px){.form-horizontal .form-group-sm .control-label{padding-top:6px;font-size:12px}}.btn{display:inline-block;padding:6px 12px;margin-bottom:0;font-size:14px;font-weight:400;line-height:1.42857143;text-align:center;white-space:nowrap;vertical-align:middle;-ms-touch-action:manipulation;touch-action:manipulation;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-image:none;border:1px solid transparent;border-radius:4px}.btn.active.focus,.btn.active:focus,.btn.focus,.btn:active.focus,.btn:active:focus,.btn:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn.focus,.btn:focus,.btn:hover{color:#333;text-decoration:none}.btn.active,.btn:active{background-image:none;outline:0;-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn.disabled,.btn[disabled],fieldset[disabled] .btn{cursor:not-allowed;filter:alpha(opacity=65);-webkit-box-shadow:none;box-shadow:none;opacity:.65}a.btn.disabled,fieldset[disabled] a.btn{pointer-events:none}.btn-default{color:#333;background-color:#fff;border-color:#ccc}.btn-default.focus,.btn-default:focus{color:#333;background-color:#e6e6e6;border-color:#8c8c8c}.btn-default:hover{color:#333;background-color:#e6e6e6;border-color:#adadad}.btn-default.active,.btn-default:active,.open>.dropdown-toggle.btn-default{color:#333;background-color:#e6e6e6;border-color:#adadad}.btn-default.active.focus,.btn-default.active:focus,.btn-default.active:hover,.btn-default:active.focus,.btn-default:active:focus,.btn-default:active:hover,.open>.dropdown-toggle.btn-default.focus,.open>.dropdown-toggle.btn-default:focus,.open>.dropdown-toggle.btn-default:hover{color:#333;background-color:#d4d4d4;border-color:#8c8c8c}.btn-default.active,.btn-default:active,.open>.dropdown-toggle.btn-default{background-image:none}.btn-default.disabled.focus,.btn-default.disabled:focus,.btn-default.disabled:hover,.btn-default[disabled].focus,.btn-default[disabled]:focus,.btn-default[disabled]:hover,fieldset[disabled] .btn-default.focus,fieldset[disabled] .btn-default:focus,fieldset[disabled] .btn-default:hover{background-color:#fff;border-color:#ccc}.btn-default .badge{color:#fff;background-color:#333}.btn-primary{color:#fff;background-color:#337ab7;border-color:#2e6da4}.btn-primary.focus,.btn-primary:focus{color:#fff;background-color:#286090;border-color:#122b40}.btn-primary:hover{color:#fff;background-color:#286090;border-color:#204d74}.btn-primary.active,.btn-primary:active,.open>.dropdown-toggle.btn-primary{color:#fff;background-color:#286090;border-color:#204d74}.btn-primary.active.focus,.btn-primary.active:focus,.btn-primary.active:hover,.btn-primary:active.focus,.btn-primary:active:focus,.btn-primary:active:hover,.open>.dropdown-toggle.btn-primary.focus,.open>.dropdown-toggle.btn-primary:focus,.open>.dropdown-toggle.btn-primary:hover{color:#fff;background-color:#204d74;border-color:#122b40}.btn-primary.active,.btn-primary:active,.open>.dropdown-toggle.btn-primary{background-image:none}.btn-primary.disabled.focus,.btn-primary.disabled:focus,.btn-primary.disabled:hover,.btn-primary[disabled].focus,.btn-primary[disabled]:focus,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary.focus,fieldset[disabled] .btn-primary:focus,fieldset[disabled] .btn-primary:hover{background-color:#337ab7;border-color:#2e6da4}.btn-primary .badge{color:#337ab7;background-color:#fff}.btn-success{color:#fff;background-color:#5cb85c;border-color:#4cae4c}.btn-success.focus,.btn-success:focus{color:#fff;background-color:#449d44;border-color:#255625}.btn-success:hover{color:#fff;background-color:#449d44;border-color:#398439}.btn-success.active,.btn-success:active,.open>.dropdown-toggle.btn-success{color:#fff;background-color:#449d44;border-color:#398439}.btn-success.active.focus,.btn-success.active:focus,.btn-success.active:hover,.btn-success:active.focus,.btn-success:active:focus,.btn-success:active:hover,.open>.dropdown-toggle.btn-success.focus,.open>.dropdown-toggle.btn-success:focus,.open>.dropdown-toggle.btn-success:hover{color:#fff;background-color:#398439;border-color:#255625}.btn-success.active,.btn-success:active,.open>.dropdown-toggle.btn-success{background-image:none}.btn-success.disabled.focus,.btn-success.disabled:focus,.btn-success.disabled:hover,.btn-success[disabled].focus,.btn-success[disabled]:focus,.btn-success[disabled]:hover,fieldset[disabled] .btn-success.focus,fieldset[disabled] .btn-success:focus,fieldset[disabled] .btn-success:hover{background-color:#5cb85c;border-color:#4cae4c}.btn-success .badge{color:#5cb85c;background-color:#fff}.btn-info{color:#fff;background-color:#5bc0de;border-color:#46b8da}.btn-info.focus,.btn-info:focus{color:#fff;background-color:#31b0d5;border-color:#1b6d85}.btn-info:hover{color:#fff;background-color:#31b0d5;border-color:#269abc}.btn-info.active,.btn-info:active,.open>.dropdown-toggle.btn-info{color:#fff;background-color:#31b0d5;border-color:#269abc}.btn-info.active.focus,.btn-info.active:focus,.btn-info.active:hover,.btn-info:active.focus,.btn-info:active:focus,.btn-info:active:hover,.open>.dropdown-toggle.btn-info.focus,.open>.dropdown-toggle.btn-info:focus,.open>.dropdown-toggle.btn-info:hover{color:#fff;background-color:#269abc;border-color:#1b6d85}.btn-info.active,.btn-info:active,.open>.dropdown-toggle.btn-info{background-image:none}.btn-info.disabled.focus,.btn-info.disabled:focus,.btn-info.disabled:hover,.btn-info[disabled].focus,.btn-info[disabled]:focus,.btn-info[disabled]:hover,fieldset[disabled] .btn-info.focus,fieldset[disabled] .btn-info:focus,fieldset[disabled] .btn-info:hover{background-color:#5bc0de;border-color:#46b8da}.btn-info .badge{color:#5bc0de;background-color:#fff}.btn-warning{color:#fff;background-color:#f0ad4e;border-color:#eea236}.btn-warning.focus,.btn-warning:focus{color:#fff;background-color:#ec971f;border-color:#985f0d}.btn-warning:hover{color:#fff;background-color:#ec971f;border-color:#d58512}.btn-warning.active,.btn-warning:active,.open>.dropdown-toggle.btn-warning{color:#fff;background-color:#ec971f;border-color:#d58512}.btn-warning.active.focus,.btn-warning.active:focus,.btn-warning.active:hover,.btn-warning:active.focus,.btn-warning:active:focus,.btn-warning:active:hover,.open>.dropdown-toggle.btn-warning.focus,.open>.dropdown-toggle.btn-warning:focus,.open>.dropdown-toggle.btn-warning:hover{color:#fff;background-color:#d58512;border-color:#985f0d}.btn-warning.active,.btn-warning:active,.open>.dropdown-toggle.btn-warning{background-image:none}.btn-warning.disabled.focus,.btn-warning.disabled:focus,.btn-warning.disabled:hover,.btn-warning[disabled].focus,.btn-warning[disabled]:focus,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning.focus,fieldset[disabled] .btn-warning:focus,fieldset[disabled] .btn-warning:hover{background-color:#f0ad4e;border-color:#eea236}.btn-warning .badge{color:#f0ad4e;background-color:#fff}.btn-danger{color:#fff;background-color:#d9534f;border-color:#d43f3a}.btn-danger.focus,.btn-danger:focus{color:#fff;background-color:#c9302c;border-color:#761c19}.btn-danger:hover{color:#fff;background-color:#c9302c;border-color:#ac2925}.btn-danger.active,.btn-danger:active,.open>.dropdown-toggle.btn-danger{color:#fff;background-color:#c9302c;border-color:#ac2925}.btn-danger.active.focus,.btn-danger.active:focus,.btn-danger.active:hover,.btn-danger:active.focus,.btn-danger:active:focus,.btn-danger:active:hover,.open>.dropdown-toggle.btn-danger.focus,.open>.dropdown-toggle.btn-danger:focus,.open>.dropdown-toggle.btn-danger:hover{color:#fff;background-color:#ac2925;border-color:#761c19}.btn-danger.active,.btn-danger:active,.open>.dropdown-toggle.btn-danger{background-image:none}.btn-danger.disabled.focus,.btn-danger.disabled:focus,.btn-danger.disabled:hover,.btn-danger[disabled].focus,.btn-danger[disabled]:focus,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger.focus,fieldset[disabled] .btn-danger:focus,fieldset[disabled] .btn-danger:hover{background-color:#d9534f;border-color:#d43f3a}.btn-danger .badge{color:#d9534f;background-color:#fff}.btn-link{font-weight:400;color:#337ab7;border-radius:0}.btn-link,.btn-link.active,.btn-link:active,.btn-link[disabled],fieldset[disabled] .btn-link{background-color:transparent;-webkit-box-shadow:none;box-shadow:none}.btn-link,.btn-link:active,.btn-link:focus,.btn-link:hover{border-color:transparent}.btn-link:focus,.btn-link:hover{color:#23527c;text-decoration:underline;background-color:transparent}.btn-link[disabled]:focus,.btn-link[disabled]:hover,fieldset[disabled] .btn-link:focus,fieldset[disabled] .btn-link:hover{color:#777;text-decoration:none}.btn-group-lg>.btn,.btn-lg{padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}.btn-group-sm>.btn,.btn-sm{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.btn-group-xs>.btn,.btn-xs{padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:5px}input[type=button].btn-block,input[type=reset].btn-block,input[type=submit].btn-block{width:100%}.fade{opacity:0;-webkit-transition:opacity .15s linear;-o-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{display:none}.collapse.in{display:block}tr.collapse.in{display:table-row}tbody.collapse.in{display:table-row-group}.collapsing{position:relative;height:0;overflow:hidden;-webkit-transition-timing-function:ease;-o-transition-timing-function:ease;transition-timing-function:ease;-webkit-transition-duration:.35s;-o-transition-duration:.35s;transition-duration:.35s;-webkit-transition-property:height,visibility;-o-transition-property:height,visibility;transition-property:height,visibility}.caret{display:inline-block;width:0;height:0;margin-left:2px;vertical-align:middle;border-top:4px dashed;border-top:4px solid\9;border-right:4px solid transparent;border-left:4px solid transparent}.dropdown,.dropup{position:relative}.dropdown-toggle:focus{outline:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;font-size:14px;text-align:left;list-style:none;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.15);border-radius:4px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,.175);box-shadow:0 6px 12px rgba(0,0,0,.175)}.dropdown-menu.pull-right{right:0;left:auto}.dropdown-menu .divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:400;line-height:1.42857143;color:#333;white-space:nowrap}.dropdown-menu>li>a:focus,.dropdown-menu>li>a:hover{color:#262626;text-decoration:none;background-color:#f5f5f5}.dropdown-menu>.active>a,.dropdown-menu>.active>a:focus,.dropdown-menu>.active>a:hover{color:#fff;text-decoration:none;background-color:#337ab7;outline:0}.dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:focus,.dropdown-menu>.disabled>a:hover{color:#777}.dropdown-menu>.disabled>a:focus,.dropdown-menu>.disabled>a:hover{text-decoration:none;cursor:not-allowed;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.open>.dropdown-menu{display:block}.open>a{outline:0}.dropdown-menu-right{right:0;left:auto}.dropdown-menu-left{right:auto;left:0}.dropdown-header{display:block;padding:3px 20px;font-size:12px;line-height:1.42857143;color:#777;white-space:nowrap}.dropdown-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:990}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{content:"";border-top:0;border-bottom:4px dashed;border-bottom:4px solid\9}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:2px}@media (min-width:768px){.navbar-right .dropdown-menu{right:0;left:auto}.navbar-right .dropdown-menu-left{right:auto;left:0}}.btn-group,.btn-group-vertical{position:relative;display:inline-block;vertical-align:middle}.btn-group-vertical>.btn,.btn-group>.btn{position:relative;float:left}.btn-group-vertical>.btn.active,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn:focus,.btn-group-vertical>.btn:hover,.btn-group>.btn.active,.btn-group>.btn:active,.btn-group>.btn:focus,.btn-group>.btn:hover{z-index:2}.btn-group .btn+.btn,.btn-group .btn+.btn-group,.btn-group .btn-group+.btn,.btn-group .btn-group+.btn-group{margin-left:-1px}.btn-toolbar{margin-left:-5px}.btn-toolbar .btn,.btn-toolbar .btn-group,.btn-toolbar .input-group{float:left}.btn-toolbar>.btn,.btn-toolbar>.btn-group,.btn-toolbar>.input-group{margin-left:5px}.btn-group>.btn:not(:first-child):not(:last-child):not(.dropdown-toggle){border-radius:0}.btn-group>.btn:first-child{margin-left:0}.btn-group>.btn:first-child:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn:last-child:not(:first-child),.btn-group>.dropdown-toggle:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.btn-group>.btn-group{float:left}.btn-group>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-left-radius:0;border-bottom-left-radius:0}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group>.btn+.dropdown-toggle{padding-right:8px;padding-left:8px}.btn-group>.btn-lg+.dropdown-toggle{padding-right:12px;padding-left:12px}.btn-group.open .dropdown-toggle{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn-group.open .dropdown-toggle.btn-link{-webkit-box-shadow:none;box-shadow:none}.btn .caret{margin-left:0}.btn-lg .caret{border-width:5px 5px 0;border-bottom-width:0}.dropup .btn-lg .caret{border-width:0 5px 5px}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group,.btn-group-vertical>.btn-group>.btn{display:block;float:none;width:100%;max-width:100%}.btn-group-vertical>.btn-group>.btn{float:none}.btn-group-vertical>.btn+.btn,.btn-group-vertical>.btn+.btn-group,.btn-group-vertical>.btn-group+.btn,.btn-group-vertical>.btn-group+.btn-group{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:not(:first-child):not(:last-child){border-radius:0}.btn-group-vertical>.btn:first-child:not(:last-child){border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn:last-child:not(:first-child){border-top-left-radius:0;border-top-right-radius:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}.btn-group-vertical>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group-vertical>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group-vertical>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-left-radius:0;border-top-right-radius:0}.btn-group-justified{display:table;width:100%;table-layout:fixed;border-collapse:separate}.btn-group-justified>.btn,.btn-group-justified>.btn-group{display:table-cell;float:none;width:1%}.btn-group-justified>.btn-group .btn{width:100%}.btn-group-justified>.btn-group .dropdown-menu{left:auto}[data-toggle=buttons]>.btn input[type=checkbox],[data-toggle=buttons]>.btn input[type=radio],[data-toggle=buttons]>.btn-group>.btn input[type=checkbox],[data-toggle=buttons]>.btn-group>.btn input[type=radio]{position:absolute;clip:rect(0,0,0,0);pointer-events:none}.input-group{position:relative;display:table;border-collapse:separate}.input-group[class*=col-]{float:none;padding-right:0;padding-left:0}.input-group .form-control{position:relative;z-index:2;float:left;width:100%;margin-bottom:0}.input-group .form-control:focus{z-index:3}.input-group-lg>.form-control,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.btn{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}select.input-group-lg>.form-control,select.input-group-lg>.input-group-addon,select.input-group-lg>.input-group-btn>.btn{height:46px;line-height:46px}select[multiple].input-group-lg>.form-control,select[multiple].input-group-lg>.input-group-addon,select[multiple].input-group-lg>.input-group-btn>.btn,textarea.input-group-lg>.form-control,textarea.input-group-lg>.input-group-addon,textarea.input-group-lg>.input-group-btn>.btn{height:auto}.input-group-sm>.form-control,.input-group-sm>.input-group-addon,.input-group-sm>.input-group-btn>.btn{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-group-sm>.form-control,select.input-group-sm>.input-group-addon,select.input-group-sm>.input-group-btn>.btn{height:30px;line-height:30px}select[multiple].input-group-sm>.form-control,select[multiple].input-group-sm>.input-group-addon,select[multiple].input-group-sm>.input-group-btn>.btn,textarea.input-group-sm>.form-control,textarea.input-group-sm>.input-group-addon,textarea.input-group-sm>.input-group-btn>.btn{height:auto}.input-group .form-control,.input-group-addon,.input-group-btn{display:table-cell}.input-group .form-control:not(:first-child):not(:last-child),.input-group-addon:not(:first-child):not(:last-child),.input-group-btn:not(:first-child):not(:last-child){border-radius:0}.input-group-addon,.input-group-btn{width:1%;white-space:nowrap;vertical-align:middle}.input-group-addon{padding:6px 12px;font-size:14px;font-weight:400;line-height:1;color:#555;text-align:center;background-color:#eee;border:1px solid #ccc;border-radius:4px}.input-group-addon.input-sm{padding:5px 10px;font-size:12px;border-radius:3px}.input-group-addon.input-lg{padding:10px 16px;font-size:18px;border-radius:6px}.input-group-addon input[type=checkbox],.input-group-addon input[type=radio]{margin-top:0}.input-group .form-control:first-child,.input-group-addon:first-child,.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group>.btn,.input-group-btn:first-child>.dropdown-toggle,.input-group-btn:last-child>.btn-group:not(:last-child)>.btn,.input-group-btn:last-child>.btn:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.input-group-addon:first-child{border-right:0}.input-group .form-control:last-child,.input-group-addon:last-child,.input-group-btn:first-child>.btn-group:not(:first-child)>.btn,.input-group-btn:first-child>.btn:not(:first-child),.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group>.btn,.input-group-btn:last-child>.dropdown-toggle{border-top-left-radius:0;border-bottom-left-radius:0}.input-group-addon:last-child{border-left:0}.input-group-btn{position:relative;font-size:0;white-space:nowrap}.input-group-btn>.btn{position:relative}.input-group-btn>.btn+.btn{margin-left:-1px}.input-group-btn>.btn:active,.input-group-btn>.btn:focus,.input-group-btn>.btn:hover{z-index:2}.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group{margin-right:-1px}.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group{z-index:2;margin-left:-1px}.nav{padding-left:0;margin-bottom:0;list-style:none}.nav>li{position:relative;display:block}.nav>li>a{position:relative;display:block;padding:10px 15px}.nav>li>a:focus,.nav>li>a:hover{text-decoration:none;background-color:#eee}.nav>li.disabled>a{color:#777}.nav>li.disabled>a:focus,.nav>li.disabled>a:hover{color:#777;text-decoration:none;cursor:not-allowed;background-color:transparent}.nav .open>a,.nav .open>a:focus,.nav .open>a:hover{background-color:#eee;border-color:#337ab7}.nav .nav-divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.nav>li>a>img{max-width:none}.nav-tabs{border-bottom:1px solid #ddd}.nav-tabs>li{float:left;margin-bottom:-1px}.nav-tabs>li>a{margin-right:2px;line-height:1.42857143;border:1px solid transparent;border-radius:4px 4px 0 0}.nav-tabs>li>a:hover{border-color:#eee #eee #ddd}.nav-tabs>li.active>a,.nav-tabs>li.active>a:focus,.nav-tabs>li.active>a:hover{color:#555;cursor:default;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent}.nav-tabs.nav-justified{width:100%;border-bottom:0}.nav-tabs.nav-justified>li{float:none}.nav-tabs.nav-justified>li>a{margin-bottom:5px;text-align:center}.nav-tabs.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-tabs.nav-justified>li{display:table-cell;width:1%}.nav-tabs.nav-justified>li>a{margin-bottom:0}}.nav-tabs.nav-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:focus,.nav-tabs.nav-justified>.active>a:hover{border:1px solid #ddd}@media (min-width:768px){.nav-tabs.nav-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:focus,.nav-tabs.nav-justified>.active>a:hover{border-bottom-color:#fff}}.nav-pills>li{float:left}.nav-pills>li>a{border-radius:4px}.nav-pills>li+li{margin-left:2px}.nav-pills>li.active>a,.nav-pills>li.active>a:focus,.nav-pills>li.active>a:hover{color:#fff;background-color:#337ab7}.nav-stacked>li{float:none}.nav-stacked>li+li{margin-top:2px;margin-left:0}.nav-justified{width:100%}.nav-justified>li{float:none}.nav-justified>li>a{margin-bottom:5px;text-align:center}.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-justified>li{display:table-cell;width:1%}.nav-justified>li>a{margin-bottom:0}}.nav-tabs-justified{border-bottom:0}.nav-tabs-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:focus,.nav-tabs-justified>.active>a:hover{border:1px solid #ddd}@media (min-width:768px){.nav-tabs-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:focus,.nav-tabs-justified>.active>a:hover{border-bottom-color:#fff}}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-left-radius:0;border-top-right-radius:0}.navbar{position:relative;min-height:50px;margin-bottom:20px;border:1px solid transparent}@media (min-width:768px){.navbar{border-radius:4px}}@media (min-width:768px){.navbar-header{float:left}}.navbar-collapse{padding-right:15px;padding-left:15px;overflow-x:visible;-webkit-overflow-scrolling:touch;border-top:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.1)}.navbar-collapse.in{overflow-y:auto}@media (min-width:768px){.navbar-collapse{width:auto;border-top:0;-webkit-box-shadow:none;box-shadow:none}.navbar-collapse.collapse{display:block!important;height:auto!important;padding-bottom:0;overflow:visible!important}.navbar-collapse.in{overflow-y:visible}.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse,.navbar-static-top .navbar-collapse{padding-right:0;padding-left:0}}.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse{max-height:340px}@media (max-device-width:480px) and (orientation:landscape){.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse{max-height:200px}}.container-fluid>.navbar-collapse,.container-fluid>.navbar-header,.container>.navbar-collapse,.container>.navbar-header{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.container-fluid>.navbar-collapse,.container-fluid>.navbar-header,.container>.navbar-collapse,.container>.navbar-header{margin-right:0;margin-left:0}}.navbar-static-top{z-index:1000;border-width:0 0 1px}@media (min-width:768px){.navbar-static-top{border-radius:0}}.navbar-fixed-bottom,.navbar-fixed-top{position:fixed;right:0;left:0;z-index:1030}@media (min-width:768px){.navbar-fixed-bottom,.navbar-fixed-top{border-radius:0}}.navbar-fixed-top{top:0;border-width:0 0 1px}.navbar-fixed-bottom{bottom:0;margin-bottom:0;border-width:1px 0 0}.navbar-brand{float:left;height:50px;padding:15px 15px;font-size:18px;line-height:20px}.navbar-brand:focus,.navbar-brand:hover{text-decoration:none}.navbar-brand>img{display:block}@media (min-width:768px){.navbar>.container .navbar-brand,.navbar>.container-fluid .navbar-brand{margin-left:-15px}}.navbar-toggle{position:relative;float:right;padding:9px 10px;margin-top:8px;margin-right:15px;margin-bottom:8px;background-color:transparent;background-image:none;border:1px solid transparent;border-radius:4px}.navbar-toggle:focus{outline:0}.navbar-toggle .icon-bar{display:block;width:22px;height:2px;border-radius:1px}.navbar-toggle .icon-bar+.icon-bar{margin-top:4px}@media (min-width:768px){.navbar-toggle{display:none}}.navbar-nav{margin:7.5px -15px}.navbar-nav>li>a{padding-top:10px;padding-bottom:10px;line-height:20px}@media (max-width:767px){.navbar-nav .open .dropdown-menu{position:static;float:none;width:auto;margin-top:0;background-color:transparent;border:0;-webkit-box-shadow:none;box-shadow:none}.navbar-nav .open .dropdown-menu .dropdown-header,.navbar-nav .open .dropdown-menu>li>a{padding:5px 15px 5px 25px}.navbar-nav .open .dropdown-menu>li>a{line-height:20px}.navbar-nav .open .dropdown-menu>li>a:focus,.navbar-nav .open .dropdown-menu>li>a:hover{background-image:none}}@media (min-width:768px){.navbar-nav{float:left;margin:0}.navbar-nav>li{float:left}.navbar-nav>li>a{padding-top:15px;padding-bottom:15px}}.navbar-form{padding:10px 15px;margin-top:8px;margin-right:-15px;margin-bottom:8px;margin-left:-15px;border-top:1px solid transparent;border-bottom:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1)}@media (min-width:768px){.navbar-form .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.navbar-form .form-control{display:inline-block;width:auto;vertical-align:middle}.navbar-form .form-control-static{display:inline-block}.navbar-form .input-group{display:inline-table;vertical-align:middle}.navbar-form .input-group .form-control,.navbar-form .input-group .input-group-addon,.navbar-form .input-group .input-group-btn{width:auto}.navbar-form .input-group>.form-control{width:100%}.navbar-form .control-label{margin-bottom:0;vertical-align:middle}.navbar-form .checkbox,.navbar-form .radio{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.navbar-form .checkbox label,.navbar-form .radio label{padding-left:0}.navbar-form .checkbox input[type=checkbox],.navbar-form .radio input[type=radio]{position:relative;margin-left:0}.navbar-form .has-feedback .form-control-feedback{top:0}}@media (max-width:767px){.navbar-form .form-group{margin-bottom:5px}.navbar-form .form-group:last-child{margin-bottom:0}}@media (min-width:768px){.navbar-form{width:auto;padding-top:0;padding-bottom:0;margin-right:0;margin-left:0;border:0;-webkit-box-shadow:none;box-shadow:none}}.navbar-nav>li>.dropdown-menu{margin-top:0;border-top-left-radius:0;border-top-right-radius:0}.navbar-fixed-bottom .navbar-nav>li>.dropdown-menu{margin-bottom:0;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.navbar-btn{margin-top:8px;margin-bottom:8px}.navbar-btn.btn-sm{margin-top:10px;margin-bottom:10px}.navbar-btn.btn-xs{margin-top:14px;margin-bottom:14px}.navbar-text{margin-top:15px;margin-bottom:15px}@media (min-width:768px){.navbar-text{float:left;margin-right:15px;margin-left:15px}}@media (min-width:768px){.navbar-left{float:left!important}.navbar-right{float:right!important;margin-right:-15px}.navbar-right~.navbar-right{margin-right:0}}.navbar-default{background-color:#f8f8f8;border-color:#e7e7e7}.navbar-default .navbar-brand{color:#777}.navbar-default .navbar-brand:focus,.navbar-default .navbar-brand:hover{color:#5e5e5e;background-color:transparent}.navbar-default .navbar-text{color:#777}.navbar-default .navbar-nav>li>a{color:#777}.navbar-default .navbar-nav>li>a:focus,.navbar-default .navbar-nav>li>a:hover{color:#333;background-color:transparent}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.active>a:focus,.navbar-default .navbar-nav>.active>a:hover{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav>.disabled>a,.navbar-default .navbar-nav>.disabled>a:focus,.navbar-default .navbar-nav>.disabled>a:hover{color:#ccc;background-color:transparent}.navbar-default .navbar-toggle{border-color:#ddd}.navbar-default .navbar-toggle:focus,.navbar-default .navbar-toggle:hover{background-color:#ddd}.navbar-default .navbar-toggle .icon-bar{background-color:#888}.navbar-default .navbar-collapse,.navbar-default .navbar-form{border-color:#e7e7e7}.navbar-default .navbar-nav>.open>a,.navbar-default .navbar-nav>.open>a:focus,.navbar-default .navbar-nav>.open>a:hover{color:#555;background-color:#e7e7e7}@media (max-width:767px){.navbar-default .navbar-nav .open .dropdown-menu>li>a{color:#777}.navbar-default .navbar-nav .open .dropdown-menu>li>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>li>a:hover{color:#333;background-color:transparent}.navbar-default .navbar-nav .open .dropdown-menu>.active>a,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:hover{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:hover{color:#ccc;background-color:transparent}}.navbar-default .navbar-link{color:#777}.navbar-default .navbar-link:hover{color:#333}.navbar-default .btn-link{color:#777}.navbar-default .btn-link:focus,.navbar-default .btn-link:hover{color:#333}.navbar-default .btn-link[disabled]:focus,.navbar-default .btn-link[disabled]:hover,fieldset[disabled] .navbar-default .btn-link:focus,fieldset[disabled] .navbar-default .btn-link:hover{color:#ccc}.navbar-inverse{background-color:#222;border-color:#080808}.navbar-inverse .navbar-brand{color:#9d9d9d}.navbar-inverse .navbar-brand:focus,.navbar-inverse .navbar-brand:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-text{color:#9d9d9d}.navbar-inverse .navbar-nav>li>a{color:#9d9d9d}.navbar-inverse .navbar-nav>li>a:focus,.navbar-inverse .navbar-nav>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.active>a:focus,.navbar-inverse .navbar-nav>.active>a:hover{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav>.disabled>a,.navbar-inverse .navbar-nav>.disabled>a:focus,.navbar-inverse .navbar-nav>.disabled>a:hover{color:#444;background-color:transparent}.navbar-inverse .navbar-toggle{border-color:#333}.navbar-inverse .navbar-toggle:focus,.navbar-inverse .navbar-toggle:hover{background-color:#333}.navbar-inverse .navbar-toggle .icon-bar{background-color:#fff}.navbar-inverse .navbar-collapse,.navbar-inverse .navbar-form{border-color:#101010}.navbar-inverse .navbar-nav>.open>a,.navbar-inverse .navbar-nav>.open>a:focus,.navbar-inverse .navbar-nav>.open>a:hover{color:#fff;background-color:#080808}@media (max-width:767px){.navbar-inverse .navbar-nav .open .dropdown-menu>.dropdown-header{border-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu .divider{background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a{color:#9d9d9d}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:hover{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:hover{color:#444;background-color:transparent}}.navbar-inverse .navbar-link{color:#9d9d9d}.navbar-inverse .navbar-link:hover{color:#fff}.navbar-inverse .btn-link{color:#9d9d9d}.navbar-inverse .btn-link:focus,.navbar-inverse .btn-link:hover{color:#fff}.navbar-inverse .btn-link[disabled]:focus,.navbar-inverse .btn-link[disabled]:hover,fieldset[disabled] .navbar-inverse .btn-link:focus,fieldset[disabled] .navbar-inverse .btn-link:hover{color:#444}.breadcrumb{padding:8px 15px;margin-bottom:20px;list-style:none;background-color:#f5f5f5;border-radius:4px}.breadcrumb>li{display:inline-block}.breadcrumb>li+li:before{padding:0 5px;color:#ccc;content:"/\00a0"}.breadcrumb>.active{color:#777}.pagination{display:inline-block;padding-left:0;margin:20px 0;border-radius:4px}.pagination>li{display:inline}.pagination>li>a,.pagination>li>span{position:relative;float:left;padding:6px 12px;margin-left:-1px;line-height:1.42857143;color:#337ab7;text-decoration:none;background-color:#fff;border:1px solid #ddd}.pagination>li:first-child>a,.pagination>li:first-child>span{margin-left:0;border-top-left-radius:4px;border-bottom-left-radius:4px}.pagination>li:last-child>a,.pagination>li:last-child>span{border-top-right-radius:4px;border-bottom-right-radius:4px}.pagination>li>a:focus,.pagination>li>a:hover,.pagination>li>span:focus,.pagination>li>span:hover{z-index:2;color:#23527c;background-color:#eee;border-color:#ddd}.pagination>.active>a,.pagination>.active>a:focus,.pagination>.active>a:hover,.pagination>.active>span,.pagination>.active>span:focus,.pagination>.active>span:hover{z-index:3;color:#fff;cursor:default;background-color:#337ab7;border-color:#337ab7}.pagination>.disabled>a,.pagination>.disabled>a:focus,.pagination>.disabled>a:hover,.pagination>.disabled>span,.pagination>.disabled>span:focus,.pagination>.disabled>span:hover{color:#777;cursor:not-allowed;background-color:#fff;border-color:#ddd}.pagination-lg>li>a,.pagination-lg>li>span{padding:10px 16px;font-size:18px;line-height:1.3333333}.pagination-lg>li:first-child>a,.pagination-lg>li:first-child>span{border-top-left-radius:6px;border-bottom-left-radius:6px}.pagination-lg>li:last-child>a,.pagination-lg>li:last-child>span{border-top-right-radius:6px;border-bottom-right-radius:6px}.pagination-sm>li>a,.pagination-sm>li>span{padding:5px 10px;font-size:12px;line-height:1.5}.pagination-sm>li:first-child>a,.pagination-sm>li:first-child>span{border-top-left-radius:3px;border-bottom-left-radius:3px}.pagination-sm>li:last-child>a,.pagination-sm>li:last-child>span{border-top-right-radius:3px;border-bottom-right-radius:3px}.pager{padding-left:0;margin:20px 0;text-align:center;list-style:none}.pager li{display:inline}.pager li>a,.pager li>span{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;border-radius:15px}.pager li>a:focus,.pager li>a:hover{text-decoration:none;background-color:#eee}.pager .next>a,.pager .next>span{float:right}.pager .previous>a,.pager .previous>span{float:left}.pager .disabled>a,.pager .disabled>a:focus,.pager .disabled>a:hover,.pager .disabled>span{color:#777;cursor:not-allowed;background-color:#fff}.label{display:inline;padding:.2em .6em .3em;font-size:75%;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25em}a.label:focus,a.label:hover{color:#fff;text-decoration:none;cursor:pointer}.label:empty{display:none}.btn .label{position:relative;top:-1px}.label-default{background-color:#777}.label-default[href]:focus,.label-default[href]:hover{background-color:#5e5e5e}.label-primary{background-color:#337ab7}.label-primary[href]:focus,.label-primary[href]:hover{background-color:#286090}.label-success{background-color:#5cb85c}.label-success[href]:focus,.label-success[href]:hover{background-color:#449d44}.label-info{background-color:#5bc0de}.label-info[href]:focus,.label-info[href]:hover{background-color:#31b0d5}.label-warning{background-color:#f0ad4e}.label-warning[href]:focus,.label-warning[href]:hover{background-color:#ec971f}.label-danger{background-color:#d9534f}.label-danger[href]:focus,.label-danger[href]:hover{background-color:#c9302c}.badge{display:inline-block;min-width:10px;padding:3px 7px;font-size:12px;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:middle;background-color:#777;border-radius:10px}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.btn-group-xs>.btn .badge,.btn-xs .badge{top:0;padding:1px 5px}a.badge:focus,a.badge:hover{color:#fff;text-decoration:none;cursor:pointer}.list-group-item.active>.badge,.nav-pills>.active>a>.badge{color:#337ab7;background-color:#fff}.list-group-item>.badge{float:right}.list-group-item>.badge+.badge{margin-right:5px}.nav-pills>li>a>.badge{margin-left:3px}.jumbotron{padding-top:30px;padding-bottom:30px;margin-bottom:30px;color:inherit;background-color:#eee}.jumbotron .h1,.jumbotron h1{color:inherit}.jumbotron p{margin-bottom:15px;font-size:21px;font-weight:200}.jumbotron>hr{border-top-color:#d5d5d5}.container .jumbotron,.container-fluid .jumbotron{padding-right:15px;padding-left:15px;border-radius:6px}.jumbotron .container{max-width:100%}@media screen and (min-width:768px){.jumbotron{padding-top:48px;padding-bottom:48px}.container .jumbotron,.container-fluid .jumbotron{padding-right:60px;padding-left:60px}.jumbotron .h1,.jumbotron h1{font-size:63px}}.thumbnail{display:block;padding:4px;margin-bottom:20px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:border .2s ease-in-out;-o-transition:border .2s ease-in-out;transition:border .2s ease-in-out}.thumbnail a>img,.thumbnail>img{margin-right:auto;margin-left:auto}a.thumbnail.active,a.thumbnail:focus,a.thumbnail:hover{border-color:#337ab7}.thumbnail .caption{padding:9px;color:#333}.alert{padding:15px;margin-bottom:20px;border:1px solid transparent;border-radius:4px}.alert h4{margin-top:0;color:inherit}.alert .alert-link{font-weight:700}.alert>p,.alert>ul{margin-bottom:0}.alert>p+p{margin-top:5px}.alert-dismissable,.alert-dismissible{padding-right:35px}.alert-dismissable .close,.alert-dismissible .close{position:relative;top:-2px;right:-21px;color:inherit}.alert-success{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.alert-success hr{border-top-color:#c9e2b3}.alert-success .alert-link{color:#2b542c}.alert-info{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.alert-info hr{border-top-color:#a6e1ec}.alert-info .alert-link{color:#245269}.alert-warning{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.alert-warning hr{border-top-color:#f7e1b5}.alert-warning .alert-link{color:#66512c}.alert-danger{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.alert-danger hr{border-top-color:#e4b9c0}.alert-danger .alert-link{color:#843534}@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-o-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}.progress{height:20px;margin-bottom:20px;overflow:hidden;background-color:#f5f5f5;border-radius:4px;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,.1);box-shadow:inset 0 1px 2px rgba(0,0,0,.1)}.progress-bar{float:left;width:0;height:100%;font-size:12px;line-height:20px;color:#fff;text-align:center;background-color:#337ab7;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);-webkit-transition:width .6s ease;-o-transition:width .6s ease;transition:width .6s ease}.progress-bar-striped,.progress-striped .progress-bar{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);-webkit-background-size:40px 40px;background-size:40px 40px}.progress-bar.active,.progress.active .progress-bar{-webkit-animation:progress-bar-stripes 2s linear infinite;-o-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress-bar-success{background-color:#5cb85c}.progress-striped .progress-bar-success{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-info{background-color:#5bc0de}.progress-striped .progress-bar-info{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-warning{background-color:#f0ad4e}.progress-striped .progress-bar-warning{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-danger{background-color:#d9534f}.progress-striped .progress-bar-danger{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.media{margin-top:15px}.media:first-child{margin-top:0}.media,.media-body{overflow:hidden;zoom:1}.media-body{width:10000px}.media-object{display:block}.media-object.img-thumbnail{max-width:none}.media-right,.media>.pull-right{padding-left:10px}.media-left,.media>.pull-left{padding-right:10px}.media-body,.media-left,.media-right{display:table-cell;vertical-align:top}.media-middle{vertical-align:middle}.media-bottom{vertical-align:bottom}.media-heading{margin-top:0;margin-bottom:5px}.media-list{padding-left:0;list-style:none}.list-group{padding-left:0;margin-bottom:20px}.list-group-item{position:relative;display:block;padding:10px 15px;margin-bottom:-1px;background-color:#fff;border:1px solid #ddd}.list-group-item:first-child{border-top-left-radius:4px;border-top-right-radius:4px}.list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}a.list-group-item,button.list-group-item{color:#555}a.list-group-item .list-group-item-heading,button.list-group-item .list-group-item-heading{color:#333}a.list-group-item:focus,a.list-group-item:hover,button.list-group-item:focus,button.list-group-item:hover{color:#555;text-decoration:none;background-color:#f5f5f5}button.list-group-item{width:100%;text-align:left}.list-group-item.disabled,.list-group-item.disabled:focus,.list-group-item.disabled:hover{color:#777;cursor:not-allowed;background-color:#eee}.list-group-item.disabled .list-group-item-heading,.list-group-item.disabled:focus .list-group-item-heading,.list-group-item.disabled:hover .list-group-item-heading{color:inherit}.list-group-item.disabled .list-group-item-text,.list-group-item.disabled:focus .list-group-item-text,.list-group-item.disabled:hover .list-group-item-text{color:#777}.list-group-item.active,.list-group-item.active:focus,.list-group-item.active:hover{z-index:2;color:#fff;background-color:#337ab7;border-color:#337ab7}.list-group-item.active .list-group-item-heading,.list-group-item.active .list-group-item-heading>.small,.list-group-item.active .list-group-item-heading>small,.list-group-item.active:focus .list-group-item-heading,.list-group-item.active:focus .list-group-item-heading>.small,.list-group-item.active:focus .list-group-item-heading>small,.list-group-item.active:hover .list-group-item-heading,.list-group-item.active:hover .list-group-item-heading>.small,.list-group-item.active:hover .list-group-item-heading>small{color:inherit}.list-group-item.active .list-group-item-text,.list-group-item.active:focus .list-group-item-text,.list-group-item.active:hover .list-group-item-text{color:#c7ddef}.list-group-item-success{color:#3c763d;background-color:#dff0d8}a.list-group-item-success,button.list-group-item-success{color:#3c763d}a.list-group-item-success .list-group-item-heading,button.list-group-item-success .list-group-item-heading{color:inherit}a.list-group-item-success:focus,a.list-group-item-success:hover,button.list-group-item-success:focus,button.list-group-item-success:hover{color:#3c763d;background-color:#d0e9c6}a.list-group-item-success.active,a.list-group-item-success.active:focus,a.list-group-item-success.active:hover,button.list-group-item-success.active,button.list-group-item-success.active:focus,button.list-group-item-success.active:hover{color:#fff;background-color:#3c763d;border-color:#3c763d}.list-group-item-info{color:#31708f;background-color:#d9edf7}a.list-group-item-info,button.list-group-item-info{color:#31708f}a.list-group-item-info .list-group-item-heading,button.list-group-item-info .list-group-item-heading{color:inherit}a.list-group-item-info:focus,a.list-group-item-info:hover,button.list-group-item-info:focus,button.list-group-item-info:hover{color:#31708f;background-color:#c4e3f3}a.list-group-item-info.active,a.list-group-item-info.active:focus,a.list-group-item-info.active:hover,button.list-group-item-info.active,button.list-group-item-info.active:focus,button.list-group-item-info.active:hover{color:#fff;background-color:#31708f;border-color:#31708f}.list-group-item-warning{color:#8a6d3b;background-color:#fcf8e3}a.list-group-item-warning,button.list-group-item-warning{color:#8a6d3b}a.list-group-item-warning .list-group-item-heading,button.list-group-item-warning .list-group-item-heading{color:inherit}a.list-group-item-warning:focus,a.list-group-item-warning:hover,button.list-group-item-warning:focus,button.list-group-item-warning:hover{color:#8a6d3b;background-color:#faf2cc}a.list-group-item-warning.active,a.list-group-item-warning.active:focus,a.list-group-item-warning.active:hover,button.list-group-item-warning.active,button.list-group-item-warning.active:focus,button.list-group-item-warning.active:hover{color:#fff;background-color:#8a6d3b;border-color:#8a6d3b}.list-group-item-danger{color:#a94442;background-color:#f2dede}a.list-group-item-danger,button.list-group-item-danger{color:#a94442}a.list-group-item-danger .list-group-item-heading,button.list-group-item-danger .list-group-item-heading{color:inherit}a.list-group-item-danger:focus,a.list-group-item-danger:hover,button.list-group-item-danger:focus,button.list-group-item-danger:hover{color:#a94442;background-color:#ebcccc}a.list-group-item-danger.active,a.list-group-item-danger.active:focus,a.list-group-item-danger.active:hover,button.list-group-item-danger.active,button.list-group-item-danger.active:focus,button.list-group-item-danger.active:hover{color:#fff;background-color:#a94442;border-color:#a94442}.list-group-item-heading{margin-top:0;margin-bottom:5px}.list-group-item-text{margin-bottom:0;line-height:1.3}.panel{margin-bottom:20px;background-color:#fff;border:1px solid transparent;border-radius:4px;-webkit-box-shadow:0 1px 1px rgba(0,0,0,.05);box-shadow:0 1px 1px rgba(0,0,0,.05)}.panel-body{padding:15px}.panel-heading{padding:10px 15px;border-bottom:1px solid transparent;border-top-left-radius:3px;border-top-right-radius:3px}.panel-heading>.dropdown .dropdown-toggle{color:inherit}.panel-title{margin-top:0;margin-bottom:0;font-size:16px;color:inherit}.panel-title>.small,.panel-title>.small>a,.panel-title>a,.panel-title>small,.panel-title>small>a{color:inherit}.panel-footer{padding:10px 15px;background-color:#f5f5f5;border-top:1px solid #ddd;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.list-group,.panel>.panel-collapse>.list-group{margin-bottom:0}.panel>.list-group .list-group-item,.panel>.panel-collapse>.list-group .list-group-item{border-width:1px 0;border-radius:0}.panel>.list-group:first-child .list-group-item:first-child,.panel>.panel-collapse>.list-group:first-child .list-group-item:first-child{border-top:0;border-top-left-radius:3px;border-top-right-radius:3px}.panel>.list-group:last-child .list-group-item:last-child,.panel>.panel-collapse>.list-group:last-child .list-group-item:last-child{border-bottom:0;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.panel-heading+.panel-collapse>.list-group .list-group-item:first-child{border-top-left-radius:0;border-top-right-radius:0}.panel-heading+.list-group .list-group-item:first-child{border-top-width:0}.list-group+.panel-footer{border-top-width:0}.panel>.panel-collapse>.table,.panel>.table,.panel>.table-responsive>.table{margin-bottom:0}.panel>.panel-collapse>.table caption,.panel>.table caption,.panel>.table-responsive>.table caption{padding-right:15px;padding-left:15px}.panel>.table-responsive:first-child>.table:first-child,.panel>.table:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child,.panel>.table:first-child>thead:first-child>tr:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table:first-child>thead:first-child>tr:first-child th:first-child{border-top-left-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table:first-child>thead:first-child>tr:first-child th:last-child{border-top-right-radius:3px}.panel>.table-responsive:last-child>.table:last-child,.panel>.table:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:first-child{border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:last-child{border-bottom-right-radius:3px}.panel>.panel-body+.table,.panel>.panel-body+.table-responsive,.panel>.table+.panel-body,.panel>.table-responsive+.panel-body{border-top:1px solid #ddd}.panel>.table>tbody:first-child>tr:first-child td,.panel>.table>tbody:first-child>tr:first-child th{border-top:0}.panel>.table-bordered,.panel>.table-responsive>.table-bordered{border:0}.panel>.table-bordered>tbody>tr>td:first-child,.panel>.table-bordered>tbody>tr>th:first-child,.panel>.table-bordered>tfoot>tr>td:first-child,.panel>.table-bordered>tfoot>tr>th:first-child,.panel>.table-bordered>thead>tr>td:first-child,.panel>.table-bordered>thead>tr>th:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:first-child,.panel>.table-responsive>.table-bordered>thead>tr>td:first-child,.panel>.table-responsive>.table-bordered>thead>tr>th:first-child{border-left:0}.panel>.table-bordered>tbody>tr>td:last-child,.panel>.table-bordered>tbody>tr>th:last-child,.panel>.table-bordered>tfoot>tr>td:last-child,.panel>.table-bordered>tfoot>tr>th:last-child,.panel>.table-bordered>thead>tr>td:last-child,.panel>.table-bordered>thead>tr>th:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:last-child,.panel>.table-responsive>.table-bordered>thead>tr>td:last-child,.panel>.table-responsive>.table-bordered>thead>tr>th:last-child{border-right:0}.panel>.table-bordered>tbody>tr:first-child>td,.panel>.table-bordered>tbody>tr:first-child>th,.panel>.table-bordered>thead>tr:first-child>td,.panel>.table-bordered>thead>tr:first-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>th,.panel>.table-responsive>.table-bordered>thead>tr:first-child>td,.panel>.table-responsive>.table-bordered>thead>tr:first-child>th{border-bottom:0}.panel>.table-bordered>tbody>tr:last-child>td,.panel>.table-bordered>tbody>tr:last-child>th,.panel>.table-bordered>tfoot>tr:last-child>td,.panel>.table-bordered>tfoot>tr:last-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>th,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>td,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}.panel>.table-responsive{margin-bottom:0;border:0}.panel-group{margin-bottom:20px}.panel-group .panel{margin-bottom:0;border-radius:4px}.panel-group .panel+.panel{margin-top:5px}.panel-group .panel-heading{border-bottom:0}.panel-group .panel-heading+.panel-collapse>.list-group,.panel-group .panel-heading+.panel-collapse>.panel-body{border-top:1px solid #ddd}.panel-group .panel-footer{border-top:0}.panel-group .panel-footer+.panel-collapse .panel-body{border-bottom:1px solid #ddd}.panel-default{border-color:#ddd}.panel-default>.panel-heading{color:#333;background-color:#f5f5f5;border-color:#ddd}.panel-default>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ddd}.panel-default>.panel-heading .badge{color:#f5f5f5;background-color:#333}.panel-default>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ddd}.panel-primary{border-color:#337ab7}.panel-primary>.panel-heading{color:#fff;background-color:#337ab7;border-color:#337ab7}.panel-primary>.panel-heading+.panel-collapse>.panel-body{border-top-color:#337ab7}.panel-primary>.panel-heading .badge{color:#337ab7;background-color:#fff}.panel-primary>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#337ab7}.panel-success{border-color:#d6e9c6}.panel-success>.panel-heading{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.panel-success>.panel-heading+.panel-collapse>.panel-body{border-top-color:#d6e9c6}.panel-success>.panel-heading .badge{color:#dff0d8;background-color:#3c763d}.panel-success>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#d6e9c6}.panel-info{border-color:#bce8f1}.panel-info>.panel-heading{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.panel-info>.panel-heading+.panel-collapse>.panel-body{border-top-color:#bce8f1}.panel-info>.panel-heading .badge{color:#d9edf7;background-color:#31708f}.panel-info>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#bce8f1}.panel-warning{border-color:#faebcc}.panel-warning>.panel-heading{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.panel-warning>.panel-heading+.panel-collapse>.panel-body{border-top-color:#faebcc}.panel-warning>.panel-heading .badge{color:#fcf8e3;background-color:#8a6d3b}.panel-warning>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#faebcc}.panel-danger{border-color:#ebccd1}.panel-danger>.panel-heading{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.panel-danger>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ebccd1}.panel-danger>.panel-heading .badge{color:#f2dede;background-color:#a94442}.panel-danger>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ebccd1}.embed-responsive{position:relative;display:block;height:0;padding:0;overflow:hidden}.embed-responsive .embed-responsive-item,.embed-responsive embed,.embed-responsive iframe,.embed-responsive object,.embed-responsive video{position:absolute;top:0;bottom:0;left:0;width:100%;height:100%;border:0}.embed-responsive-16by9{padding-bottom:56.25%}.embed-responsive-4by3{padding-bottom:75%}.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.05);box-shadow:inset 0 1px 1px rgba(0,0,0,.05)}.well blockquote{border-color:#ddd;border-color:rgba(0,0,0,.15)}.well-lg{padding:24px;border-radius:6px}.well-sm{padding:9px;border-radius:3px}.close{float:right;font-size:21px;font-weight:700;line-height:1;color:#000;text-shadow:0 1px 0 #fff;filter:alpha(opacity=20);opacity:.2}.close:focus,.close:hover{color:#000;text-decoration:none;cursor:pointer;filter:alpha(opacity=50);opacity:.5}button.close{-webkit-appearance:none;padding:0;cursor:pointer;background:0 0;border:0}.modal-open{overflow:hidden}.modal{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1050;display:none;overflow:hidden;-webkit-overflow-scrolling:touch;outline:0}.modal.fade .modal-dialog{-webkit-transition:-webkit-transform .3s ease-out;-o-transition:-o-transform .3s ease-out;transition:transform .3s ease-out;-webkit-transform:translate(0,-25%);-ms-transform:translate(0,-25%);-o-transform:translate(0,-25%);transform:translate(0,-25%)}.modal.in .modal-dialog{-webkit-transform:translate(0,0);-ms-transform:translate(0,0);-o-transform:translate(0,0);transform:translate(0,0)}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal-dialog{position:relative;width:auto;margin:10px}.modal-content{position:relative;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #999;border:1px solid rgba(0,0,0,.2);border-radius:6px;outline:0;-webkit-box-shadow:0 3px 9px rgba(0,0,0,.5);box-shadow:0 3px 9px rgba(0,0,0,.5)}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000}.modal-backdrop.fade{filter:alpha(opacity=0);opacity:0}.modal-backdrop.in{filter:alpha(opacity=50);opacity:.5}.modal-header{padding:15px;border-bottom:1px solid #e5e5e5}.modal-header .close{margin-top:-2px}.modal-title{margin:0;line-height:1.42857143}.modal-body{position:relative;padding:15px}.modal-footer{padding:15px;text-align:right;border-top:1px solid #e5e5e5}.modal-footer .btn+.btn{margin-bottom:0;margin-left:5px}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-footer .btn-block+.btn-block{margin-left:0}.modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}@media (min-width:768px){.modal-dialog{width:600px;margin:30px auto}.modal-content{-webkit-box-shadow:0 5px 15px rgba(0,0,0,.5);box-shadow:0 5px 15px rgba(0,0,0,.5)}.modal-sm{width:300px}}@media (min-width:992px){.modal-lg{width:900px}}.tooltip{position:absolute;z-index:1070;display:block;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:12px;font-style:normal;font-weight:400;line-height:1.42857143;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;word-wrap:normal;white-space:normal;filter:alpha(opacity=0);opacity:0;line-break:auto}.tooltip.in{filter:alpha(opacity=90);opacity:.9}.tooltip.top{padding:5px 0;margin-top:-3px}.tooltip.right{padding:0 5px;margin-left:3px}.tooltip.bottom{padding:5px 0;margin-top:3px}.tooltip.left{padding:0 5px;margin-left:-3px}.tooltip-inner{max-width:200px;padding:3px 8px;color:#fff;text-align:center;background-color:#000;border-radius:4px}.tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-left .tooltip-arrow{right:5px;bottom:0;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-right .tooltip-arrow{bottom:0;left:5px;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-width:5px 5px 5px 0;border-right-color:#000}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-width:5px 0 5px 5px;border-left-color:#000}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-left .tooltip-arrow{top:0;right:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-right .tooltip-arrow{top:0;left:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000}.popover{position:absolute;top:0;left:0;z-index:1060;display:none;max-width:276px;padding:1px;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;font-style:normal;font-weight:400;line-height:1.42857143;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;word-wrap:normal;white-space:normal;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.2);border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,.2);box-shadow:0 5px 10px rgba(0,0,0,.2);line-break:auto}.popover.top{margin-top:-10px}.popover.right{margin-left:10px}.popover.bottom{margin-top:10px}.popover.left{margin-left:-10px}.popover-title{padding:8px 14px;margin:0;font-size:14px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-radius:5px 5px 0 0}.popover-content{padding:9px 14px}.popover>.arrow,.popover>.arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.popover>.arrow{border-width:11px}.popover>.arrow:after{content:"";border-width:10px}.popover.top>.arrow{bottom:-11px;left:50%;margin-left:-11px;border-top-color:#999;border-top-color:rgba(0,0,0,.25);border-bottom-width:0}.popover.top>.arrow:after{bottom:1px;margin-left:-10px;content:" ";border-top-color:#fff;border-bottom-width:0}.popover.right>.arrow{top:50%;left:-11px;margin-top:-11px;border-right-color:#999;border-right-color:rgba(0,0,0,.25);border-left-width:0}.popover.right>.arrow:after{bottom:-10px;left:1px;content:" ";border-right-color:#fff;border-left-width:0}.popover.bottom>.arrow{top:-11px;left:50%;margin-left:-11px;border-top-width:0;border-bottom-color:#999;border-bottom-color:rgba(0,0,0,.25)}.popover.bottom>.arrow:after{top:1px;margin-left:-10px;content:" ";border-top-width:0;border-bottom-color:#fff}.popover.left>.arrow{top:50%;right:-11px;margin-top:-11px;border-right-width:0;border-left-color:#999;border-left-color:rgba(0,0,0,.25)}.popover.left>.arrow:after{right:1px;bottom:-10px;content:" ";border-right-width:0;border-left-color:#fff}.carousel{position:relative}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner>.item{position:relative;display:none;-webkit-transition:.6s ease-in-out left;-o-transition:.6s ease-in-out left;transition:.6s ease-in-out left}.carousel-inner>.item>a>img,.carousel-inner>.item>img{line-height:1}@media all and (transform-3d),(-webkit-transform-3d){.carousel-inner>.item{-webkit-transition:-webkit-transform .6s ease-in-out;-o-transition:-o-transform .6s ease-in-out;transition:transform .6s ease-in-out;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-perspective:1000px;perspective:1000px}.carousel-inner>.item.active.right,.carousel-inner>.item.next{left:0;-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}.carousel-inner>.item.active.left,.carousel-inner>.item.prev{left:0;-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}.carousel-inner>.item.active,.carousel-inner>.item.next.left,.carousel-inner>.item.prev.right{left:0;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}.carousel-inner>.active,.carousel-inner>.next,.carousel-inner>.prev{display:block}.carousel-inner>.active{left:0}.carousel-inner>.next,.carousel-inner>.prev{position:absolute;top:0;width:100%}.carousel-inner>.next{left:100%}.carousel-inner>.prev{left:-100%}.carousel-inner>.next.left,.carousel-inner>.prev.right{left:0}.carousel-inner>.active.left{left:-100%}.carousel-inner>.active.right{left:100%}.carousel-control{position:absolute;top:0;bottom:0;left:0;width:15%;font-size:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6);background-color:rgba(0,0,0,0);filter:alpha(opacity=50);opacity:.5}.carousel-control.left{background-image:-webkit-linear-gradient(left,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-image:-o-linear-gradient(left,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-image:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,.5)),to(rgba(0,0,0,.0001)));background-image:linear-gradient(to right,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1);background-repeat:repeat-x}.carousel-control.right{right:0;left:auto;background-image:-webkit-linear-gradient(left,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-image:-o-linear-gradient(left,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-image:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,.0001)),to(rgba(0,0,0,.5)));background-image:linear-gradient(to right,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1);background-repeat:repeat-x}.carousel-control:focus,.carousel-control:hover{color:#fff;text-decoration:none;filter:alpha(opacity=90);outline:0;opacity:.9}.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next,.carousel-control .icon-prev{position:absolute;top:50%;z-index:5;display:inline-block;margin-top:-10px}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{left:50%;margin-left:-10px}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{right:50%;margin-right:-10px}.carousel-control .icon-next,.carousel-control .icon-prev{width:20px;height:20px;font-family:serif;line-height:1}.carousel-control .icon-prev:before{content:'\2039'}.carousel-control .icon-next:before{content:'\203a'}.carousel-indicators{position:absolute;bottom:10px;left:50%;z-index:15;width:60%;padding-left:0;margin-left:-30%;text-align:center;list-style:none}.carousel-indicators li{display:inline-block;width:10px;height:10px;margin:1px;text-indent:-999px;cursor:pointer;background-color:#000\9;background-color:rgba(0,0,0,0);border:1px solid #fff;border-radius:10px}.carousel-indicators .active{width:12px;height:12px;margin:0;background-color:#fff}.carousel-caption{position:absolute;right:15%;bottom:20px;left:15%;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6)}.carousel-caption .btn{text-shadow:none}@media screen and (min-width:768px){.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next,.carousel-control .icon-prev{width:30px;height:30px;margin-top:-10px;font-size:30px}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{margin-left:-10px}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{margin-right:-10px}.carousel-caption{right:20%;left:20%;padding-bottom:30px}.carousel-indicators{bottom:20px}}.btn-group-vertical>.btn-group:after,.btn-group-vertical>.btn-group:before,.btn-toolbar:after,.btn-toolbar:before,.clearfix:after,.clearfix:before,.container-fluid:after,.container-fluid:before,.container:after,.container:before,.dl-horizontal dd:after,.dl-horizontal dd:before,.form-horizontal .form-group:after,.form-horizontal .form-group:before,.modal-footer:after,.modal-footer:before,.modal-header:after,.modal-header:before,.nav:after,.nav:before,.navbar-collapse:after,.navbar-collapse:before,.navbar-header:after,.navbar-header:before,.navbar:after,.navbar:before,.pager:after,.pager:before,.panel-body:after,.panel-body:before,.row:after,.row:before{display:table;content:" "}.btn-group-vertical>.btn-group:after,.btn-toolbar:after,.clearfix:after,.container-fluid:after,.container:after,.dl-horizontal dd:after,.form-horizontal .form-group:after,.modal-footer:after,.modal-header:after,.nav:after,.navbar-collapse:after,.navbar-header:after,.navbar:after,.pager:after,.panel-body:after,.row:after{clear:both}.center-block{display:block;margin-right:auto;margin-left:auto}.pull-right{float:right!important}.pull-left{float:left!important}.hide{display:none!important}.show{display:block!important}.invisible{visibility:hidden}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.hidden{display:none!important}.affix{position:fixed}@-ms-viewport{width:device-width}.visible-lg,.visible-md,.visible-sm,.visible-xs{display:none!important}.visible-lg-block,.visible-lg-inline,.visible-lg-inline-block,.visible-md-block,.visible-md-inline,.visible-md-inline-block,.visible-sm-block,.visible-sm-inline,.visible-sm-inline-block,.visible-xs-block,.visible-xs-inline,.visible-xs-inline-block{display:none!important}@media (max-width:767px){.visible-xs{display:block!important}table.visible-xs{display:table!important}tr.visible-xs{display:table-row!important}td.visible-xs,th.visible-xs{display:table-cell!important}}@media (max-width:767px){.visible-xs-block{display:block!important}}@media (max-width:767px){.visible-xs-inline{display:inline!important}}@media (max-width:767px){.visible-xs-inline-block{display:inline-block!important}}@media (min-width:768px) and (max-width:991px){.visible-sm{display:block!important}table.visible-sm{display:table!important}tr.visible-sm{display:table-row!important}td.visible-sm,th.visible-sm{display:table-cell!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-block{display:block!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline{display:inline!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline-block{display:inline-block!important}}@media (min-width:992px) and (max-width:1199px){.visible-md{display:block!important}table.visible-md{display:table!important}tr.visible-md{display:table-row!important}td.visible-md,th.visible-md{display:table-cell!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-block{display:block!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline{display:inline!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline-block{display:inline-block!important}}@media (min-width:1200px){.visible-lg{display:block!important}table.visible-lg{display:table!important}tr.visible-lg{display:table-row!important}td.visible-lg,th.visible-lg{display:table-cell!important}}@media (min-width:1200px){.visible-lg-block{display:block!important}}@media (min-width:1200px){.visible-lg-inline{display:inline!important}}@media (min-width:1200px){.visible-lg-inline-block{display:inline-block!important}}@media (max-width:767px){.hidden-xs{display:none!important}}@media (min-width:768px) and (max-width:991px){.hidden-sm{display:none!important}}@media (min-width:992px) and (max-width:1199px){.hidden-md{display:none!important}}@media (min-width:1200px){.hidden-lg{display:none!important}}.visible-print{display:none!important}@media print{.visible-print{display:block!important}table.visible-print{display:table!important}tr.visible-print{display:table-row!important}td.visible-print,th.visible-print{display:table-cell!important}}.visible-print-block{display:none!important}@media print{.visible-print-block{display:block!important}}.visible-print-inline{display:none!important}@media print{.visible-print-inline{display:inline!important}}.visible-print-inline-block{display:none!important}@media print{.visible-print-inline-block{display:inline-block!important}}@media print{.hidden-print{display:none!important}} diff --git a/revel/skeleton/public/fonts/glyphicons-halflings-regular.ttf b/revel/skeleton/public/fonts/glyphicons-halflings-regular.ttf deleted file mode 100644 index 1413fc6..0000000 Binary files a/revel/skeleton/public/fonts/glyphicons-halflings-regular.ttf and /dev/null differ diff --git a/revel/skeleton/public/fonts/glyphicons-halflings-regular.woff b/revel/skeleton/public/fonts/glyphicons-halflings-regular.woff deleted file mode 100644 index 9e61285..0000000 Binary files a/revel/skeleton/public/fonts/glyphicons-halflings-regular.woff and /dev/null differ diff --git a/revel/skeleton/public/fonts/glyphicons-halflings-regular.woff2 b/revel/skeleton/public/fonts/glyphicons-halflings-regular.woff2 deleted file mode 100644 index 64539b5..0000000 Binary files a/revel/skeleton/public/fonts/glyphicons-halflings-regular.woff2 and /dev/null differ diff --git a/revel/skeleton/public/img/favicon.png b/revel/skeleton/public/img/favicon.png deleted file mode 100644 index 0303cba..0000000 Binary files a/revel/skeleton/public/img/favicon.png and /dev/null differ diff --git a/revel/skeleton/public/js/bootstrap-3.3.6.min.js b/revel/skeleton/public/js/bootstrap-3.3.6.min.js deleted file mode 100644 index e79c065..0000000 --- a/revel/skeleton/public/js/bootstrap-3.3.6.min.js +++ /dev/null @@ -1,7 +0,0 @@ -/*! - * Bootstrap v3.3.6 (http://getbootstrap.com) - * Copyright 2011-2015 Twitter, Inc. - * Licensed under the MIT license - */ -if("undefined"==typeof jQuery)throw new Error("Bootstrap's JavaScript requires jQuery");+function(a){"use strict";var b=a.fn.jquery.split(" ")[0].split(".");if(b[0]<2&&b[1]<9||1==b[0]&&9==b[1]&&b[2]<1||b[0]>2)throw new Error("Bootstrap's JavaScript requires jQuery version 1.9.1 or higher, but lower than version 3")}(jQuery),+function(a){"use strict";function b(){var a=document.createElement("bootstrap"),b={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var c in b)if(void 0!==a.style[c])return{end:b[c]};return!1}a.fn.emulateTransitionEnd=function(b){var c=!1,d=this;a(this).one("bsTransitionEnd",function(){c=!0});var e=function(){c||a(d).trigger(a.support.transition.end)};return setTimeout(e,b),this},a(function(){a.support.transition=b(),a.support.transition&&(a.event.special.bsTransitionEnd={bindType:a.support.transition.end,delegateType:a.support.transition.end,handle:function(b){return a(b.target).is(this)?b.handleObj.handler.apply(this,arguments):void 0}})})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var c=a(this),e=c.data("bs.alert");e||c.data("bs.alert",e=new d(this)),"string"==typeof b&&e[b].call(c)})}var c='[data-dismiss="alert"]',d=function(b){a(b).on("click",c,this.close)};d.VERSION="3.3.6",d.TRANSITION_DURATION=150,d.prototype.close=function(b){function c(){g.detach().trigger("closed.bs.alert").remove()}var e=a(this),f=e.attr("data-target");f||(f=e.attr("href"),f=f&&f.replace(/.*(?=#[^\s]*$)/,""));var g=a(f);b&&b.preventDefault(),g.length||(g=e.closest(".alert")),g.trigger(b=a.Event("close.bs.alert")),b.isDefaultPrevented()||(g.removeClass("in"),a.support.transition&&g.hasClass("fade")?g.one("bsTransitionEnd",c).emulateTransitionEnd(d.TRANSITION_DURATION):c())};var e=a.fn.alert;a.fn.alert=b,a.fn.alert.Constructor=d,a.fn.alert.noConflict=function(){return a.fn.alert=e,this},a(document).on("click.bs.alert.data-api",c,d.prototype.close)}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.button"),f="object"==typeof b&&b;e||d.data("bs.button",e=new c(this,f)),"toggle"==b?e.toggle():b&&e.setState(b)})}var c=function(b,d){this.$element=a(b),this.options=a.extend({},c.DEFAULTS,d),this.isLoading=!1};c.VERSION="3.3.6",c.DEFAULTS={loadingText:"loading..."},c.prototype.setState=function(b){var c="disabled",d=this.$element,e=d.is("input")?"val":"html",f=d.data();b+="Text",null==f.resetText&&d.data("resetText",d[e]()),setTimeout(a.proxy(function(){d[e](null==f[b]?this.options[b]:f[b]),"loadingText"==b?(this.isLoading=!0,d.addClass(c).attr(c,c)):this.isLoading&&(this.isLoading=!1,d.removeClass(c).removeAttr(c))},this),0)},c.prototype.toggle=function(){var a=!0,b=this.$element.closest('[data-toggle="buttons"]');if(b.length){var c=this.$element.find("input");"radio"==c.prop("type")?(c.prop("checked")&&(a=!1),b.find(".active").removeClass("active"),this.$element.addClass("active")):"checkbox"==c.prop("type")&&(c.prop("checked")!==this.$element.hasClass("active")&&(a=!1),this.$element.toggleClass("active")),c.prop("checked",this.$element.hasClass("active")),a&&c.trigger("change")}else this.$element.attr("aria-pressed",!this.$element.hasClass("active")),this.$element.toggleClass("active")};var d=a.fn.button;a.fn.button=b,a.fn.button.Constructor=c,a.fn.button.noConflict=function(){return a.fn.button=d,this},a(document).on("click.bs.button.data-api",'[data-toggle^="button"]',function(c){var d=a(c.target);d.hasClass("btn")||(d=d.closest(".btn")),b.call(d,"toggle"),a(c.target).is('input[type="radio"]')||a(c.target).is('input[type="checkbox"]')||c.preventDefault()}).on("focus.bs.button.data-api blur.bs.button.data-api",'[data-toggle^="button"]',function(b){a(b.target).closest(".btn").toggleClass("focus",/^focus(in)?$/.test(b.type))})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.carousel"),f=a.extend({},c.DEFAULTS,d.data(),"object"==typeof b&&b),g="string"==typeof b?b:f.slide;e||d.data("bs.carousel",e=new c(this,f)),"number"==typeof b?e.to(b):g?e[g]():f.interval&&e.pause().cycle()})}var c=function(b,c){this.$element=a(b),this.$indicators=this.$element.find(".carousel-indicators"),this.options=c,this.paused=null,this.sliding=null,this.interval=null,this.$active=null,this.$items=null,this.options.keyboard&&this.$element.on("keydown.bs.carousel",a.proxy(this.keydown,this)),"hover"==this.options.pause&&!("ontouchstart"in document.documentElement)&&this.$element.on("mouseenter.bs.carousel",a.proxy(this.pause,this)).on("mouseleave.bs.carousel",a.proxy(this.cycle,this))};c.VERSION="3.3.6",c.TRANSITION_DURATION=600,c.DEFAULTS={interval:5e3,pause:"hover",wrap:!0,keyboard:!0},c.prototype.keydown=function(a){if(!/input|textarea/i.test(a.target.tagName)){switch(a.which){case 37:this.prev();break;case 39:this.next();break;default:return}a.preventDefault()}},c.prototype.cycle=function(b){return b||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(a.proxy(this.next,this),this.options.interval)),this},c.prototype.getItemIndex=function(a){return this.$items=a.parent().children(".item"),this.$items.index(a||this.$active)},c.prototype.getItemForDirection=function(a,b){var c=this.getItemIndex(b),d="prev"==a&&0===c||"next"==a&&c==this.$items.length-1;if(d&&!this.options.wrap)return b;var e="prev"==a?-1:1,f=(c+e)%this.$items.length;return this.$items.eq(f)},c.prototype.to=function(a){var b=this,c=this.getItemIndex(this.$active=this.$element.find(".item.active"));return a>this.$items.length-1||0>a?void 0:this.sliding?this.$element.one("slid.bs.carousel",function(){b.to(a)}):c==a?this.pause().cycle():this.slide(a>c?"next":"prev",this.$items.eq(a))},c.prototype.pause=function(b){return b||(this.paused=!0),this.$element.find(".next, .prev").length&&a.support.transition&&(this.$element.trigger(a.support.transition.end),this.cycle(!0)),this.interval=clearInterval(this.interval),this},c.prototype.next=function(){return this.sliding?void 0:this.slide("next")},c.prototype.prev=function(){return this.sliding?void 0:this.slide("prev")},c.prototype.slide=function(b,d){var e=this.$element.find(".item.active"),f=d||this.getItemForDirection(b,e),g=this.interval,h="next"==b?"left":"right",i=this;if(f.hasClass("active"))return this.sliding=!1;var j=f[0],k=a.Event("slide.bs.carousel",{relatedTarget:j,direction:h});if(this.$element.trigger(k),!k.isDefaultPrevented()){if(this.sliding=!0,g&&this.pause(),this.$indicators.length){this.$indicators.find(".active").removeClass("active");var l=a(this.$indicators.children()[this.getItemIndex(f)]);l&&l.addClass("active")}var m=a.Event("slid.bs.carousel",{relatedTarget:j,direction:h});return a.support.transition&&this.$element.hasClass("slide")?(f.addClass(b),f[0].offsetWidth,e.addClass(h),f.addClass(h),e.one("bsTransitionEnd",function(){f.removeClass([b,h].join(" ")).addClass("active"),e.removeClass(["active",h].join(" ")),i.sliding=!1,setTimeout(function(){i.$element.trigger(m)},0)}).emulateTransitionEnd(c.TRANSITION_DURATION)):(e.removeClass("active"),f.addClass("active"),this.sliding=!1,this.$element.trigger(m)),g&&this.cycle(),this}};var d=a.fn.carousel;a.fn.carousel=b,a.fn.carousel.Constructor=c,a.fn.carousel.noConflict=function(){return a.fn.carousel=d,this};var e=function(c){var d,e=a(this),f=a(e.attr("data-target")||(d=e.attr("href"))&&d.replace(/.*(?=#[^\s]+$)/,""));if(f.hasClass("carousel")){var g=a.extend({},f.data(),e.data()),h=e.attr("data-slide-to");h&&(g.interval=!1),b.call(f,g),h&&f.data("bs.carousel").to(h),c.preventDefault()}};a(document).on("click.bs.carousel.data-api","[data-slide]",e).on("click.bs.carousel.data-api","[data-slide-to]",e),a(window).on("load",function(){a('[data-ride="carousel"]').each(function(){var c=a(this);b.call(c,c.data())})})}(jQuery),+function(a){"use strict";function b(b){var c,d=b.attr("data-target")||(c=b.attr("href"))&&c.replace(/.*(?=#[^\s]+$)/,"");return a(d)}function c(b){return this.each(function(){var c=a(this),e=c.data("bs.collapse"),f=a.extend({},d.DEFAULTS,c.data(),"object"==typeof b&&b);!e&&f.toggle&&/show|hide/.test(b)&&(f.toggle=!1),e||c.data("bs.collapse",e=new d(this,f)),"string"==typeof b&&e[b]()})}var d=function(b,c){this.$element=a(b),this.options=a.extend({},d.DEFAULTS,c),this.$trigger=a('[data-toggle="collapse"][href="#'+b.id+'"],[data-toggle="collapse"][data-target="#'+b.id+'"]'),this.transitioning=null,this.options.parent?this.$parent=this.getParent():this.addAriaAndCollapsedClass(this.$element,this.$trigger),this.options.toggle&&this.toggle()};d.VERSION="3.3.6",d.TRANSITION_DURATION=350,d.DEFAULTS={toggle:!0},d.prototype.dimension=function(){var a=this.$element.hasClass("width");return a?"width":"height"},d.prototype.show=function(){if(!this.transitioning&&!this.$element.hasClass("in")){var b,e=this.$parent&&this.$parent.children(".panel").children(".in, .collapsing");if(!(e&&e.length&&(b=e.data("bs.collapse"),b&&b.transitioning))){var f=a.Event("show.bs.collapse");if(this.$element.trigger(f),!f.isDefaultPrevented()){e&&e.length&&(c.call(e,"hide"),b||e.data("bs.collapse",null));var g=this.dimension();this.$element.removeClass("collapse").addClass("collapsing")[g](0).attr("aria-expanded",!0),this.$trigger.removeClass("collapsed").attr("aria-expanded",!0),this.transitioning=1;var h=function(){this.$element.removeClass("collapsing").addClass("collapse in")[g](""),this.transitioning=0,this.$element.trigger("shown.bs.collapse")};if(!a.support.transition)return h.call(this);var i=a.camelCase(["scroll",g].join("-"));this.$element.one("bsTransitionEnd",a.proxy(h,this)).emulateTransitionEnd(d.TRANSITION_DURATION)[g](this.$element[0][i])}}}},d.prototype.hide=function(){if(!this.transitioning&&this.$element.hasClass("in")){var b=a.Event("hide.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.dimension();this.$element[c](this.$element[c]())[0].offsetHeight,this.$element.addClass("collapsing").removeClass("collapse in").attr("aria-expanded",!1),this.$trigger.addClass("collapsed").attr("aria-expanded",!1),this.transitioning=1;var e=function(){this.transitioning=0,this.$element.removeClass("collapsing").addClass("collapse").trigger("hidden.bs.collapse")};return a.support.transition?void this.$element[c](0).one("bsTransitionEnd",a.proxy(e,this)).emulateTransitionEnd(d.TRANSITION_DURATION):e.call(this)}}},d.prototype.toggle=function(){this[this.$element.hasClass("in")?"hide":"show"]()},d.prototype.getParent=function(){return a(this.options.parent).find('[data-toggle="collapse"][data-parent="'+this.options.parent+'"]').each(a.proxy(function(c,d){var e=a(d);this.addAriaAndCollapsedClass(b(e),e)},this)).end()},d.prototype.addAriaAndCollapsedClass=function(a,b){var c=a.hasClass("in");a.attr("aria-expanded",c),b.toggleClass("collapsed",!c).attr("aria-expanded",c)};var e=a.fn.collapse;a.fn.collapse=c,a.fn.collapse.Constructor=d,a.fn.collapse.noConflict=function(){return a.fn.collapse=e,this},a(document).on("click.bs.collapse.data-api",'[data-toggle="collapse"]',function(d){var e=a(this);e.attr("data-target")||d.preventDefault();var f=b(e),g=f.data("bs.collapse"),h=g?"toggle":e.data();c.call(f,h)})}(jQuery),+function(a){"use strict";function b(b){var c=b.attr("data-target");c||(c=b.attr("href"),c=c&&/#[A-Za-z]/.test(c)&&c.replace(/.*(?=#[^\s]*$)/,""));var d=c&&a(c);return d&&d.length?d:b.parent()}function c(c){c&&3===c.which||(a(e).remove(),a(f).each(function(){var d=a(this),e=b(d),f={relatedTarget:this};e.hasClass("open")&&(c&&"click"==c.type&&/input|textarea/i.test(c.target.tagName)&&a.contains(e[0],c.target)||(e.trigger(c=a.Event("hide.bs.dropdown",f)),c.isDefaultPrevented()||(d.attr("aria-expanded","false"),e.removeClass("open").trigger(a.Event("hidden.bs.dropdown",f)))))}))}function d(b){return this.each(function(){var c=a(this),d=c.data("bs.dropdown");d||c.data("bs.dropdown",d=new g(this)),"string"==typeof b&&d[b].call(c)})}var e=".dropdown-backdrop",f='[data-toggle="dropdown"]',g=function(b){a(b).on("click.bs.dropdown",this.toggle)};g.VERSION="3.3.6",g.prototype.toggle=function(d){var e=a(this);if(!e.is(".disabled, :disabled")){var f=b(e),g=f.hasClass("open");if(c(),!g){"ontouchstart"in document.documentElement&&!f.closest(".navbar-nav").length&&a(document.createElement("div")).addClass("dropdown-backdrop").insertAfter(a(this)).on("click",c);var h={relatedTarget:this};if(f.trigger(d=a.Event("show.bs.dropdown",h)),d.isDefaultPrevented())return;e.trigger("focus").attr("aria-expanded","true"),f.toggleClass("open").trigger(a.Event("shown.bs.dropdown",h))}return!1}},g.prototype.keydown=function(c){if(/(38|40|27|32)/.test(c.which)&&!/input|textarea/i.test(c.target.tagName)){var d=a(this);if(c.preventDefault(),c.stopPropagation(),!d.is(".disabled, :disabled")){var e=b(d),g=e.hasClass("open");if(!g&&27!=c.which||g&&27==c.which)return 27==c.which&&e.find(f).trigger("focus"),d.trigger("click");var h=" li:not(.disabled):visible a",i=e.find(".dropdown-menu"+h);if(i.length){var j=i.index(c.target);38==c.which&&j>0&&j--,40==c.which&&jdocument.documentElement.clientHeight;this.$element.css({paddingLeft:!this.bodyIsOverflowing&&a?this.scrollbarWidth:"",paddingRight:this.bodyIsOverflowing&&!a?this.scrollbarWidth:""})},c.prototype.resetAdjustments=function(){this.$element.css({paddingLeft:"",paddingRight:""})},c.prototype.checkScrollbar=function(){var a=window.innerWidth;if(!a){var b=document.documentElement.getBoundingClientRect();a=b.right-Math.abs(b.left)}this.bodyIsOverflowing=document.body.clientWidth
',trigger:"hover focus",title:"",delay:0,html:!1,container:!1,viewport:{selector:"body",padding:0}},c.prototype.init=function(b,c,d){if(this.enabled=!0,this.type=b,this.$element=a(c),this.options=this.getOptions(d),this.$viewport=this.options.viewport&&a(a.isFunction(this.options.viewport)?this.options.viewport.call(this,this.$element):this.options.viewport.selector||this.options.viewport),this.inState={click:!1,hover:!1,focus:!1},this.$element[0]instanceof document.constructor&&!this.options.selector)throw new Error("`selector` option must be specified when initializing "+this.type+" on the window.document object!");for(var e=this.options.trigger.split(" "),f=e.length;f--;){var g=e[f];if("click"==g)this.$element.on("click."+this.type,this.options.selector,a.proxy(this.toggle,this));else if("manual"!=g){var h="hover"==g?"mouseenter":"focusin",i="hover"==g?"mouseleave":"focusout";this.$element.on(h+"."+this.type,this.options.selector,a.proxy(this.enter,this)),this.$element.on(i+"."+this.type,this.options.selector,a.proxy(this.leave,this))}}this.options.selector?this._options=a.extend({},this.options,{trigger:"manual",selector:""}):this.fixTitle()},c.prototype.getDefaults=function(){return c.DEFAULTS},c.prototype.getOptions=function(b){return b=a.extend({},this.getDefaults(),this.$element.data(),b),b.delay&&"number"==typeof b.delay&&(b.delay={show:b.delay,hide:b.delay}),b},c.prototype.getDelegateOptions=function(){var b={},c=this.getDefaults();return this._options&&a.each(this._options,function(a,d){c[a]!=d&&(b[a]=d)}),b},c.prototype.enter=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget).data("bs."+this.type);return c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c)),b instanceof a.Event&&(c.inState["focusin"==b.type?"focus":"hover"]=!0),c.tip().hasClass("in")||"in"==c.hoverState?void(c.hoverState="in"):(clearTimeout(c.timeout),c.hoverState="in",c.options.delay&&c.options.delay.show?void(c.timeout=setTimeout(function(){"in"==c.hoverState&&c.show()},c.options.delay.show)):c.show())},c.prototype.isInStateTrue=function(){for(var a in this.inState)if(this.inState[a])return!0;return!1},c.prototype.leave=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget).data("bs."+this.type);return c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c)),b instanceof a.Event&&(c.inState["focusout"==b.type?"focus":"hover"]=!1),c.isInStateTrue()?void 0:(clearTimeout(c.timeout),c.hoverState="out",c.options.delay&&c.options.delay.hide?void(c.timeout=setTimeout(function(){"out"==c.hoverState&&c.hide()},c.options.delay.hide)):c.hide())},c.prototype.show=function(){var b=a.Event("show.bs."+this.type);if(this.hasContent()&&this.enabled){this.$element.trigger(b);var d=a.contains(this.$element[0].ownerDocument.documentElement,this.$element[0]);if(b.isDefaultPrevented()||!d)return;var e=this,f=this.tip(),g=this.getUID(this.type);this.setContent(),f.attr("id",g),this.$element.attr("aria-describedby",g),this.options.animation&&f.addClass("fade");var h="function"==typeof this.options.placement?this.options.placement.call(this,f[0],this.$element[0]):this.options.placement,i=/\s?auto?\s?/i,j=i.test(h);j&&(h=h.replace(i,"")||"top"),f.detach().css({top:0,left:0,display:"block"}).addClass(h).data("bs."+this.type,this),this.options.container?f.appendTo(this.options.container):f.insertAfter(this.$element),this.$element.trigger("inserted.bs."+this.type);var k=this.getPosition(),l=f[0].offsetWidth,m=f[0].offsetHeight;if(j){var n=h,o=this.getPosition(this.$viewport);h="bottom"==h&&k.bottom+m>o.bottom?"top":"top"==h&&k.top-mo.width?"left":"left"==h&&k.left-lg.top+g.height&&(e.top=g.top+g.height-i)}else{var j=b.left-f,k=b.left+f+c;jg.right&&(e.left=g.left+g.width-k)}return e},c.prototype.getTitle=function(){var a,b=this.$element,c=this.options;return a=b.attr("data-original-title")||("function"==typeof c.title?c.title.call(b[0]):c.title)},c.prototype.getUID=function(a){do a+=~~(1e6*Math.random());while(document.getElementById(a));return a},c.prototype.tip=function(){if(!this.$tip&&(this.$tip=a(this.options.template),1!=this.$tip.length))throw new Error(this.type+" `template` option must consist of exactly 1 top-level element!");return this.$tip},c.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".tooltip-arrow")},c.prototype.enable=function(){this.enabled=!0},c.prototype.disable=function(){this.enabled=!1},c.prototype.toggleEnabled=function(){this.enabled=!this.enabled},c.prototype.toggle=function(b){var c=this;b&&(c=a(b.currentTarget).data("bs."+this.type),c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c))),b?(c.inState.click=!c.inState.click,c.isInStateTrue()?c.enter(c):c.leave(c)):c.tip().hasClass("in")?c.leave(c):c.enter(c)},c.prototype.destroy=function(){var a=this;clearTimeout(this.timeout),this.hide(function(){a.$element.off("."+a.type).removeData("bs."+a.type),a.$tip&&a.$tip.detach(),a.$tip=null,a.$arrow=null,a.$viewport=null})};var d=a.fn.tooltip;a.fn.tooltip=b,a.fn.tooltip.Constructor=c,a.fn.tooltip.noConflict=function(){return a.fn.tooltip=d,this}}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.popover"),f="object"==typeof b&&b;(e||!/destroy|hide/.test(b))&&(e||d.data("bs.popover",e=new c(this,f)),"string"==typeof b&&e[b]())})}var c=function(a,b){this.init("popover",a,b)};if(!a.fn.tooltip)throw new Error("Popover requires tooltip.js");c.VERSION="3.3.6",c.DEFAULTS=a.extend({},a.fn.tooltip.Constructor.DEFAULTS,{placement:"right",trigger:"click",content:"",template:''}),c.prototype=a.extend({},a.fn.tooltip.Constructor.prototype),c.prototype.constructor=c,c.prototype.getDefaults=function(){return c.DEFAULTS},c.prototype.setContent=function(){var a=this.tip(),b=this.getTitle(),c=this.getContent();a.find(".popover-title")[this.options.html?"html":"text"](b),a.find(".popover-content").children().detach().end()[this.options.html?"string"==typeof c?"html":"append":"text"](c),a.removeClass("fade top bottom left right in"),a.find(".popover-title").html()||a.find(".popover-title").hide()},c.prototype.hasContent=function(){return this.getTitle()||this.getContent()},c.prototype.getContent=function(){var a=this.$element,b=this.options;return a.attr("data-content")||("function"==typeof b.content?b.content.call(a[0]):b.content)},c.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".arrow")};var d=a.fn.popover;a.fn.popover=b,a.fn.popover.Constructor=c,a.fn.popover.noConflict=function(){return a.fn.popover=d,this}}(jQuery),+function(a){"use strict";function b(c,d){this.$body=a(document.body),this.$scrollElement=a(a(c).is(document.body)?window:c),this.options=a.extend({},b.DEFAULTS,d),this.selector=(this.options.target||"")+" .nav li > a",this.offsets=[],this.targets=[],this.activeTarget=null,this.scrollHeight=0,this.$scrollElement.on("scroll.bs.scrollspy",a.proxy(this.process,this)),this.refresh(),this.process()}function c(c){return this.each(function(){var d=a(this),e=d.data("bs.scrollspy"),f="object"==typeof c&&c;e||d.data("bs.scrollspy",e=new b(this,f)),"string"==typeof c&&e[c]()})}b.VERSION="3.3.6",b.DEFAULTS={offset:10},b.prototype.getScrollHeight=function(){return this.$scrollElement[0].scrollHeight||Math.max(this.$body[0].scrollHeight,document.documentElement.scrollHeight)},b.prototype.refresh=function(){var b=this,c="offset",d=0;this.offsets=[],this.targets=[],this.scrollHeight=this.getScrollHeight(),a.isWindow(this.$scrollElement[0])||(c="position",d=this.$scrollElement.scrollTop()),this.$body.find(this.selector).map(function(){var b=a(this),e=b.data("target")||b.attr("href"),f=/^#./.test(e)&&a(e);return f&&f.length&&f.is(":visible")&&[[f[c]().top+d,e]]||null}).sort(function(a,b){return a[0]-b[0]}).each(function(){b.offsets.push(this[0]),b.targets.push(this[1])})},b.prototype.process=function(){var a,b=this.$scrollElement.scrollTop()+this.options.offset,c=this.getScrollHeight(),d=this.options.offset+c-this.$scrollElement.height(),e=this.offsets,f=this.targets,g=this.activeTarget;if(this.scrollHeight!=c&&this.refresh(),b>=d)return g!=(a=f[f.length-1])&&this.activate(a);if(g&&b=e[a]&&(void 0===e[a+1]||b .dropdown-menu > .active").removeClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!1),b.addClass("active").find('[data-toggle="tab"]').attr("aria-expanded",!0),h?(b[0].offsetWidth,b.addClass("in")):b.removeClass("fade"),b.parent(".dropdown-menu").length&&b.closest("li.dropdown").addClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!0),e&&e()}var g=d.find("> .active"),h=e&&a.support.transition&&(g.length&&g.hasClass("fade")||!!d.find("> .fade").length);g.length&&h?g.one("bsTransitionEnd",f).emulateTransitionEnd(c.TRANSITION_DURATION):f(),g.removeClass("in")};var d=a.fn.tab;a.fn.tab=b,a.fn.tab.Constructor=c,a.fn.tab.noConflict=function(){return a.fn.tab=d,this};var e=function(c){c.preventDefault(),b.call(a(this),"show")};a(document).on("click.bs.tab.data-api",'[data-toggle="tab"]',e).on("click.bs.tab.data-api",'[data-toggle="pill"]',e)}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.affix"),f="object"==typeof b&&b;e||d.data("bs.affix",e=new c(this,f)),"string"==typeof b&&e[b]()})}var c=function(b,d){this.options=a.extend({},c.DEFAULTS,d),this.$target=a(this.options.target).on("scroll.bs.affix.data-api",a.proxy(this.checkPosition,this)).on("click.bs.affix.data-api",a.proxy(this.checkPositionWithEventLoop,this)),this.$element=a(b),this.affixed=null,this.unpin=null,this.pinnedOffset=null,this.checkPosition()};c.VERSION="3.3.6",c.RESET="affix affix-top affix-bottom",c.DEFAULTS={offset:0,target:window},c.prototype.getState=function(a,b,c,d){var e=this.$target.scrollTop(),f=this.$element.offset(),g=this.$target.height();if(null!=c&&"top"==this.affixed)return c>e?"top":!1;if("bottom"==this.affixed)return null!=c?e+this.unpin<=f.top?!1:"bottom":a-d>=e+g?!1:"bottom";var h=null==this.affixed,i=h?e:f.top,j=h?g:b;return null!=c&&c>=e?"top":null!=d&&i+j>=a-d?"bottom":!1},c.prototype.getPinnedOffset=function(){if(this.pinnedOffset)return this.pinnedOffset;this.$element.removeClass(c.RESET).addClass("affix");var a=this.$target.scrollTop(),b=this.$element.offset();return this.pinnedOffset=b.top-a},c.prototype.checkPositionWithEventLoop=function(){setTimeout(a.proxy(this.checkPosition,this),1)},c.prototype.checkPosition=function(){if(this.$element.is(":visible")){var b=this.$element.height(),d=this.options.offset,e=d.top,f=d.bottom,g=Math.max(a(document).height(),a(document.body).height());"object"!=typeof d&&(f=e=d),"function"==typeof e&&(e=d.top(this.$element)),"function"==typeof f&&(f=d.bottom(this.$element));var h=this.getState(g,b,e,f);if(this.affixed!=h){null!=this.unpin&&this.$element.css("top","");var i="affix"+(h?"-"+h:""),j=a.Event(i+".bs.affix");if(this.$element.trigger(j),j.isDefaultPrevented())return;this.affixed=h,this.unpin="bottom"==h?this.getPinnedOffset():null,this.$element.removeClass(c.RESET).addClass(i).trigger(i.replace("affix","affixed")+".bs.affix")}"bottom"==h&&this.$element.offset({top:g-b-f})}};var d=a.fn.affix;a.fn.affix=b,a.fn.affix.Constructor=c,a.fn.affix.noConflict=function(){return a.fn.affix=d,this},a(window).on("load",function(){a('[data-spy="affix"]').each(function(){var c=a(this),d=c.data();d.offset=d.offset||{},null!=d.offsetBottom&&(d.offset.bottom=d.offsetBottom),null!=d.offsetTop&&(d.offset.top=d.offsetTop),b.call(c,d)})})}(jQuery); \ No newline at end of file diff --git a/revel/skeleton/public/js/jquery-2.2.4.min.js b/revel/skeleton/public/js/jquery-2.2.4.min.js deleted file mode 100644 index 4024b66..0000000 --- a/revel/skeleton/public/js/jquery-2.2.4.min.js +++ /dev/null @@ -1,4 +0,0 @@ -/*! jQuery v2.2.4 | (c) jQuery Foundation | jquery.org/license */ -!function(a,b){"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){var c=[],d=a.document,e=c.slice,f=c.concat,g=c.push,h=c.indexOf,i={},j=i.toString,k=i.hasOwnProperty,l={},m="2.2.4",n=function(a,b){return new n.fn.init(a,b)},o=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,p=/^-ms-/,q=/-([\da-z])/gi,r=function(a,b){return b.toUpperCase()};n.fn=n.prototype={jquery:m,constructor:n,selector:"",length:0,toArray:function(){return e.call(this)},get:function(a){return null!=a?0>a?this[a+this.length]:this[a]:e.call(this)},pushStack:function(a){var b=n.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a){return n.each(this,a)},map:function(a){return this.pushStack(n.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(e.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor()},push:g,sort:c.sort,splice:c.splice},n.extend=n.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||n.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(a=arguments[h]))for(b in a)c=g[b],d=a[b],g!==d&&(j&&d&&(n.isPlainObject(d)||(e=n.isArray(d)))?(e?(e=!1,f=c&&n.isArray(c)?c:[]):f=c&&n.isPlainObject(c)?c:{},g[b]=n.extend(j,f,d)):void 0!==d&&(g[b]=d));return g},n.extend({expando:"jQuery"+(m+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===n.type(a)},isArray:Array.isArray,isWindow:function(a){return null!=a&&a===a.window},isNumeric:function(a){var b=a&&a.toString();return!n.isArray(a)&&b-parseFloat(b)+1>=0},isPlainObject:function(a){var b;if("object"!==n.type(a)||a.nodeType||n.isWindow(a))return!1;if(a.constructor&&!k.call(a,"constructor")&&!k.call(a.constructor.prototype||{},"isPrototypeOf"))return!1;for(b in a);return void 0===b||k.call(a,b)},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?i[j.call(a)]||"object":typeof a},globalEval:function(a){var b,c=eval;a=n.trim(a),a&&(1===a.indexOf("use strict")?(b=d.createElement("script"),b.text=a,d.head.appendChild(b).parentNode.removeChild(b)):c(a))},camelCase:function(a){return a.replace(p,"ms-").replace(q,r)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b){var c,d=0;if(s(a)){for(c=a.length;c>d;d++)if(b.call(a[d],d,a[d])===!1)break}else for(d in a)if(b.call(a[d],d,a[d])===!1)break;return a},trim:function(a){return null==a?"":(a+"").replace(o,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(s(Object(a))?n.merge(c,"string"==typeof a?[a]:a):g.call(c,a)),c},inArray:function(a,b,c){return null==b?-1:h.call(b,a,c)},merge:function(a,b){for(var c=+b.length,d=0,e=a.length;c>d;d++)a[e++]=b[d];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,e,g=0,h=[];if(s(a))for(d=a.length;d>g;g++)e=b(a[g],g,c),null!=e&&h.push(e);else for(g in a)e=b(a[g],g,c),null!=e&&h.push(e);return f.apply([],h)},guid:1,proxy:function(a,b){var c,d,f;return"string"==typeof b&&(c=a[b],b=a,a=c),n.isFunction(a)?(d=e.call(arguments,2),f=function(){return a.apply(b||this,d.concat(e.call(arguments)))},f.guid=a.guid=a.guid||n.guid++,f):void 0},now:Date.now,support:l}),"function"==typeof Symbol&&(n.fn[Symbol.iterator]=c[Symbol.iterator]),n.each("Boolean Number String Function Array Date RegExp Object Error Symbol".split(" "),function(a,b){i["[object "+b+"]"]=b.toLowerCase()});function s(a){var b=!!a&&"length"in a&&a.length,c=n.type(a);return"function"===c||n.isWindow(a)?!1:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}var t=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+1*new Date,v=a.document,w=0,x=0,y=ga(),z=ga(),A=ga(),B=function(a,b){return a===b&&(l=!0),0},C=1<<31,D={}.hasOwnProperty,E=[],F=E.pop,G=E.push,H=E.push,I=E.slice,J=function(a,b){for(var c=0,d=a.length;d>c;c++)if(a[c]===b)return c;return-1},K="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",L="[\\x20\\t\\r\\n\\f]",M="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",N="\\["+L+"*("+M+")(?:"+L+"*([*^$|!~]?=)"+L+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+M+"))|)"+L+"*\\]",O=":("+M+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+N+")*)|.*)\\)|)",P=new RegExp(L+"+","g"),Q=new RegExp("^"+L+"+|((?:^|[^\\\\])(?:\\\\.)*)"+L+"+$","g"),R=new RegExp("^"+L+"*,"+L+"*"),S=new RegExp("^"+L+"*([>+~]|"+L+")"+L+"*"),T=new RegExp("="+L+"*([^\\]'\"]*?)"+L+"*\\]","g"),U=new RegExp(O),V=new RegExp("^"+M+"$"),W={ID:new RegExp("^#("+M+")"),CLASS:new RegExp("^\\.("+M+")"),TAG:new RegExp("^("+M+"|[*])"),ATTR:new RegExp("^"+N),PSEUDO:new RegExp("^"+O),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+L+"*(even|odd|(([+-]|)(\\d*)n|)"+L+"*(?:([+-]|)"+L+"*(\\d+)|))"+L+"*\\)|)","i"),bool:new RegExp("^(?:"+K+")$","i"),needsContext:new RegExp("^"+L+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+L+"*((?:-\\d)?\\d*)"+L+"*\\)|)(?=[^-]|$)","i")},X=/^(?:input|select|textarea|button)$/i,Y=/^h\d$/i,Z=/^[^{]+\{\s*\[native \w/,$=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,_=/[+~]/,aa=/'|\\/g,ba=new RegExp("\\\\([\\da-f]{1,6}"+L+"?|("+L+")|.)","ig"),ca=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:0>d?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)},da=function(){m()};try{H.apply(E=I.call(v.childNodes),v.childNodes),E[v.childNodes.length].nodeType}catch(ea){H={apply:E.length?function(a,b){G.apply(a,I.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function fa(a,b,d,e){var f,h,j,k,l,o,r,s,w=b&&b.ownerDocument,x=b?b.nodeType:9;if(d=d||[],"string"!=typeof a||!a||1!==x&&9!==x&&11!==x)return d;if(!e&&((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,p)){if(11!==x&&(o=$.exec(a)))if(f=o[1]){if(9===x){if(!(j=b.getElementById(f)))return d;if(j.id===f)return d.push(j),d}else if(w&&(j=w.getElementById(f))&&t(b,j)&&j.id===f)return d.push(j),d}else{if(o[2])return H.apply(d,b.getElementsByTagName(a)),d;if((f=o[3])&&c.getElementsByClassName&&b.getElementsByClassName)return H.apply(d,b.getElementsByClassName(f)),d}if(c.qsa&&!A[a+" "]&&(!q||!q.test(a))){if(1!==x)w=b,s=a;else if("object"!==b.nodeName.toLowerCase()){(k=b.getAttribute("id"))?k=k.replace(aa,"\\$&"):b.setAttribute("id",k=u),r=g(a),h=r.length,l=V.test(k)?"#"+k:"[id='"+k+"']";while(h--)r[h]=l+" "+qa(r[h]);s=r.join(","),w=_.test(a)&&oa(b.parentNode)||b}if(s)try{return H.apply(d,w.querySelectorAll(s)),d}catch(y){}finally{k===u&&b.removeAttribute("id")}}}return i(a.replace(Q,"$1"),b,d,e)}function ga(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function ha(a){return a[u]=!0,a}function ia(a){var b=n.createElement("div");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function ja(a,b){var c=a.split("|"),e=c.length;while(e--)d.attrHandle[c[e]]=b}function ka(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&(~b.sourceIndex||C)-(~a.sourceIndex||C);if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function la(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function ma(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function na(a){return ha(function(b){return b=+b,ha(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function oa(a){return a&&"undefined"!=typeof a.getElementsByTagName&&a}c=fa.support={},f=fa.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?"HTML"!==b.nodeName:!1},m=fa.setDocument=function(a){var b,e,g=a?a.ownerDocument||a:v;return g!==n&&9===g.nodeType&&g.documentElement?(n=g,o=n.documentElement,p=!f(n),(e=n.defaultView)&&e.top!==e&&(e.addEventListener?e.addEventListener("unload",da,!1):e.attachEvent&&e.attachEvent("onunload",da)),c.attributes=ia(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=ia(function(a){return a.appendChild(n.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=Z.test(n.getElementsByClassName),c.getById=ia(function(a){return o.appendChild(a).id=u,!n.getElementsByName||!n.getElementsByName(u).length}),c.getById?(d.find.ID=function(a,b){if("undefined"!=typeof b.getElementById&&p){var c=b.getElementById(a);return c?[c]:[]}},d.filter.ID=function(a){var b=a.replace(ba,ca);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(ba,ca);return function(a){var c="undefined"!=typeof a.getAttributeNode&&a.getAttributeNode("id");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return"undefined"!=typeof b.getElementsByTagName?b.getElementsByTagName(a):c.qsa?b.querySelectorAll(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){return"undefined"!=typeof b.getElementsByClassName&&p?b.getElementsByClassName(a):void 0},r=[],q=[],(c.qsa=Z.test(n.querySelectorAll))&&(ia(function(a){o.appendChild(a).innerHTML="",a.querySelectorAll("[msallowcapture^='']").length&&q.push("[*^$]="+L+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+L+"*(?:value|"+K+")"),a.querySelectorAll("[id~="+u+"-]").length||q.push("~="),a.querySelectorAll(":checked").length||q.push(":checked"),a.querySelectorAll("a#"+u+"+*").length||q.push(".#.+[+~]")}),ia(function(a){var b=n.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+L+"*[*^$|!~]?="),a.querySelectorAll(":enabled").length||q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=Z.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&ia(function(a){c.disconnectedMatch=s.call(a,"div"),s.call(a,"[s!='']:x"),r.push("!=",O)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=Z.test(o.compareDocumentPosition),t=b||Z.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===n||a.ownerDocument===v&&t(v,a)?-1:b===n||b.ownerDocument===v&&t(v,b)?1:k?J(k,a)-J(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,e=a.parentNode,f=b.parentNode,g=[a],h=[b];if(!e||!f)return a===n?-1:b===n?1:e?-1:f?1:k?J(k,a)-J(k,b):0;if(e===f)return ka(a,b);c=a;while(c=c.parentNode)g.unshift(c);c=b;while(c=c.parentNode)h.unshift(c);while(g[d]===h[d])d++;return d?ka(g[d],h[d]):g[d]===v?-1:h[d]===v?1:0},n):n},fa.matches=function(a,b){return fa(a,null,null,b)},fa.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(T,"='$1']"),c.matchesSelector&&p&&!A[b+" "]&&(!r||!r.test(b))&&(!q||!q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return fa(b,n,null,[a]).length>0},fa.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},fa.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&D.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},fa.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},fa.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=fa.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=fa.selectors={cacheLength:50,createPseudo:ha,match:W,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(ba,ca),a[3]=(a[3]||a[4]||a[5]||"").replace(ba,ca),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||fa.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&fa.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return W.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&U.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(ba,ca).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+L+")"+a+"("+L+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||"undefined"!=typeof a.getAttribute&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=fa.attr(d,a);return null==e?"!="===b:b?(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e.replace(P," ")+" ").indexOf(c)>-1:"|="===b?e===c||e.slice(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h,t=!1;if(q){if(f){while(p){m=b;while(m=m[p])if(h?m.nodeName.toLowerCase()===r:1===m.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){m=q,l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),j=k[a]||[],n=j[0]===w&&j[1],t=n&&j[2],m=n&&q.childNodes[n];while(m=++n&&m&&m[p]||(t=n=0)||o.pop())if(1===m.nodeType&&++t&&m===b){k[a]=[w,n,t];break}}else if(s&&(m=b,l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),j=k[a]||[],n=j[0]===w&&j[1],t=n),t===!1)while(m=++n&&m&&m[p]||(t=n=0)||o.pop())if((h?m.nodeName.toLowerCase()===r:1===m.nodeType)&&++t&&(s&&(l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),k[a]=[w,t]),m===b))break;return t-=e,t===d||t%d===0&&t/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||fa.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?ha(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=J(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:ha(function(a){var b=[],c=[],d=h(a.replace(Q,"$1"));return d[u]?ha(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),b[0]=null,!c.pop()}}),has:ha(function(a){return function(b){return fa(a,b).length>0}}),contains:ha(function(a){return a=a.replace(ba,ca),function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:ha(function(a){return V.test(a||"")||fa.error("unsupported lang: "+a),a=a.replace(ba,ca).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return Y.test(a.nodeName)},input:function(a){return X.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:na(function(){return[0]}),last:na(function(a,b){return[b-1]}),eq:na(function(a,b,c){return[0>c?c+b:c]}),even:na(function(a,b){for(var c=0;b>c;c+=2)a.push(c);return a}),odd:na(function(a,b){for(var c=1;b>c;c+=2)a.push(c);return a}),lt:na(function(a,b,c){for(var d=0>c?c+b:c;--d>=0;)a.push(d);return a}),gt:na(function(a,b,c){for(var d=0>c?c+b:c;++db;b++)d+=a[b].value;return d}function ra(a,b,c){var d=b.dir,e=c&&"parentNode"===d,f=x++;return b.first?function(b,c,f){while(b=b[d])if(1===b.nodeType||e)return a(b,c,f)}:function(b,c,g){var h,i,j,k=[w,f];if(g){while(b=b[d])if((1===b.nodeType||e)&&a(b,c,g))return!0}else while(b=b[d])if(1===b.nodeType||e){if(j=b[u]||(b[u]={}),i=j[b.uniqueID]||(j[b.uniqueID]={}),(h=i[d])&&h[0]===w&&h[1]===f)return k[2]=h[2];if(i[d]=k,k[2]=a(b,c,g))return!0}}}function sa(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function ta(a,b,c){for(var d=0,e=b.length;e>d;d++)fa(a,b[d],c);return c}function ua(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;i>h;h++)(f=a[h])&&(c&&!c(f,d,e)||(g.push(f),j&&b.push(h)));return g}function va(a,b,c,d,e,f){return d&&!d[u]&&(d=va(d)),e&&!e[u]&&(e=va(e,f)),ha(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||ta(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:ua(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=ua(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?J(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=ua(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):H.apply(g,r)})}function wa(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=ra(function(a){return a===b},h,!0),l=ra(function(a){return J(b,a)>-1},h,!0),m=[function(a,c,d){var e=!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d));return b=null,e}];f>i;i++)if(c=d.relative[a[i].type])m=[ra(sa(m),c)];else{if(c=d.filter[a[i].type].apply(null,a[i].matches),c[u]){for(e=++i;f>e;e++)if(d.relative[a[e].type])break;return va(i>1&&sa(m),i>1&&qa(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(Q,"$1"),c,e>i&&wa(a.slice(i,e)),f>e&&wa(a=a.slice(e)),f>e&&qa(a))}m.push(c)}return sa(m)}function xa(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,h,i,k){var l,o,q,r=0,s="0",t=f&&[],u=[],v=j,x=f||e&&d.find.TAG("*",k),y=w+=null==v?1:Math.random()||.1,z=x.length;for(k&&(j=g===n||g||k);s!==z&&null!=(l=x[s]);s++){if(e&&l){o=0,g||l.ownerDocument===n||(m(l),h=!p);while(q=a[o++])if(q(l,g||n,h)){i.push(l);break}k&&(w=y)}c&&((l=!q&&l)&&r--,f&&t.push(l))}if(r+=s,c&&s!==r){o=0;while(q=b[o++])q(t,u,g,h);if(f){if(r>0)while(s--)t[s]||u[s]||(u[s]=F.call(i));u=ua(u)}H.apply(i,u),k&&!f&&u.length>0&&r+b.length>1&&fa.uniqueSort(i)}return k&&(w=y,j=v),t};return c?ha(f):f}return h=fa.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=wa(b[c]),f[u]?d.push(f):e.push(f);f=A(a,xa(e,d)),f.selector=a}return f},i=fa.select=function(a,b,e,f){var i,j,k,l,m,n="function"==typeof a&&a,o=!f&&g(a=n.selector||a);if(e=e||[],1===o.length){if(j=o[0]=o[0].slice(0),j.length>2&&"ID"===(k=j[0]).type&&c.getById&&9===b.nodeType&&p&&d.relative[j[1].type]){if(b=(d.find.ID(k.matches[0].replace(ba,ca),b)||[])[0],!b)return e;n&&(b=b.parentNode),a=a.slice(j.shift().value.length)}i=W.needsContext.test(a)?0:j.length;while(i--){if(k=j[i],d.relative[l=k.type])break;if((m=d.find[l])&&(f=m(k.matches[0].replace(ba,ca),_.test(j[0].type)&&oa(b.parentNode)||b))){if(j.splice(i,1),a=f.length&&qa(j),!a)return H.apply(e,f),e;break}}}return(n||h(a,o))(f,b,!p,e,!b||_.test(a)&&oa(b.parentNode)||b),e},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=ia(function(a){return 1&a.compareDocumentPosition(n.createElement("div"))}),ia(function(a){return a.innerHTML="","#"===a.firstChild.getAttribute("href")})||ja("type|href|height|width",function(a,b,c){return c?void 0:a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&ia(function(a){return a.innerHTML="",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||ja("value",function(a,b,c){return c||"input"!==a.nodeName.toLowerCase()?void 0:a.defaultValue}),ia(function(a){return null==a.getAttribute("disabled")})||ja(K,function(a,b,c){var d;return c?void 0:a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),fa}(a);n.find=t,n.expr=t.selectors,n.expr[":"]=n.expr.pseudos,n.uniqueSort=n.unique=t.uniqueSort,n.text=t.getText,n.isXMLDoc=t.isXML,n.contains=t.contains;var u=function(a,b,c){var d=[],e=void 0!==c;while((a=a[b])&&9!==a.nodeType)if(1===a.nodeType){if(e&&n(a).is(c))break;d.push(a)}return d},v=function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c},w=n.expr.match.needsContext,x=/^<([\w-]+)\s*\/?>(?:<\/\1>|)$/,y=/^.[^:#\[\.,]*$/;function z(a,b,c){if(n.isFunction(b))return n.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return n.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(y.test(b))return n.filter(b,a,c);b=n.filter(b,a)}return n.grep(a,function(a){return h.call(b,a)>-1!==c})}n.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?n.find.matchesSelector(d,a)?[d]:[]:n.find.matches(a,n.grep(b,function(a){return 1===a.nodeType}))},n.fn.extend({find:function(a){var b,c=this.length,d=[],e=this;if("string"!=typeof a)return this.pushStack(n(a).filter(function(){for(b=0;c>b;b++)if(n.contains(e[b],this))return!0}));for(b=0;c>b;b++)n.find(a,e[b],d);return d=this.pushStack(c>1?n.unique(d):d),d.selector=this.selector?this.selector+" "+a:a,d},filter:function(a){return this.pushStack(z(this,a||[],!1))},not:function(a){return this.pushStack(z(this,a||[],!0))},is:function(a){return!!z(this,"string"==typeof a&&w.test(a)?n(a):a||[],!1).length}});var A,B=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,C=n.fn.init=function(a,b,c){var e,f;if(!a)return this;if(c=c||A,"string"==typeof a){if(e="<"===a[0]&&">"===a[a.length-1]&&a.length>=3?[null,a,null]:B.exec(a),!e||!e[1]&&b)return!b||b.jquery?(b||c).find(a):this.constructor(b).find(a);if(e[1]){if(b=b instanceof n?b[0]:b,n.merge(this,n.parseHTML(e[1],b&&b.nodeType?b.ownerDocument||b:d,!0)),x.test(e[1])&&n.isPlainObject(b))for(e in b)n.isFunction(this[e])?this[e](b[e]):this.attr(e,b[e]);return this}return f=d.getElementById(e[2]),f&&f.parentNode&&(this.length=1,this[0]=f),this.context=d,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):n.isFunction(a)?void 0!==c.ready?c.ready(a):a(n):(void 0!==a.selector&&(this.selector=a.selector,this.context=a.context),n.makeArray(a,this))};C.prototype=n.fn,A=n(d);var D=/^(?:parents|prev(?:Until|All))/,E={children:!0,contents:!0,next:!0,prev:!0};n.fn.extend({has:function(a){var b=n(a,this),c=b.length;return this.filter(function(){for(var a=0;c>a;a++)if(n.contains(this,b[a]))return!0})},closest:function(a,b){for(var c,d=0,e=this.length,f=[],g=w.test(a)||"string"!=typeof a?n(a,b||this.context):0;e>d;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&n.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?n.uniqueSort(f):f)},index:function(a){return a?"string"==typeof a?h.call(n(a),this[0]):h.call(this,a.jquery?a[0]:a):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(n.uniqueSort(n.merge(this.get(),n(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function F(a,b){while((a=a[b])&&1!==a.nodeType);return a}n.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return u(a,"parentNode")},parentsUntil:function(a,b,c){return u(a,"parentNode",c)},next:function(a){return F(a,"nextSibling")},prev:function(a){return F(a,"previousSibling")},nextAll:function(a){return u(a,"nextSibling")},prevAll:function(a){return u(a,"previousSibling")},nextUntil:function(a,b,c){return u(a,"nextSibling",c)},prevUntil:function(a,b,c){return u(a,"previousSibling",c)},siblings:function(a){return v((a.parentNode||{}).firstChild,a)},children:function(a){return v(a.firstChild)},contents:function(a){return a.contentDocument||n.merge([],a.childNodes)}},function(a,b){n.fn[a]=function(c,d){var e=n.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=n.filter(d,e)),this.length>1&&(E[a]||n.uniqueSort(e),D.test(a)&&e.reverse()),this.pushStack(e)}});var G=/\S+/g;function H(a){var b={};return n.each(a.match(G)||[],function(a,c){b[c]=!0}),b}n.Callbacks=function(a){a="string"==typeof a?H(a):n.extend({},a);var b,c,d,e,f=[],g=[],h=-1,i=function(){for(e=a.once,d=b=!0;g.length;h=-1){c=g.shift();while(++h-1)f.splice(c,1),h>=c&&h--}),this},has:function(a){return a?n.inArray(a,f)>-1:f.length>0},empty:function(){return f&&(f=[]),this},disable:function(){return e=g=[],f=c="",this},disabled:function(){return!f},lock:function(){return e=g=[],c||(f=c=""),this},locked:function(){return!!e},fireWith:function(a,c){return e||(c=c||[],c=[a,c.slice?c.slice():c],g.push(c),b||i()),this},fire:function(){return j.fireWith(this,arguments),this},fired:function(){return!!d}};return j},n.extend({Deferred:function(a){var b=[["resolve","done",n.Callbacks("once memory"),"resolved"],["reject","fail",n.Callbacks("once memory"),"rejected"],["notify","progress",n.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return n.Deferred(function(c){n.each(b,function(b,f){var g=n.isFunction(a[b])&&a[b];e[f[1]](function(){var a=g&&g.apply(this,arguments);a&&n.isFunction(a.promise)?a.promise().progress(c.notify).done(c.resolve).fail(c.reject):c[f[0]+"With"](this===d?c.promise():this,g?[a]:arguments)})}),a=null}).promise()},promise:function(a){return null!=a?n.extend(a,d):d}},e={};return d.pipe=d.then,n.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[1^a][2].disable,b[2][2].lock),e[f[0]]=function(){return e[f[0]+"With"](this===e?d:this,arguments),this},e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=e.call(arguments),d=c.length,f=1!==d||a&&n.isFunction(a.promise)?d:0,g=1===f?a:n.Deferred(),h=function(a,b,c){return function(d){b[a]=this,c[a]=arguments.length>1?e.call(arguments):d,c===i?g.notifyWith(b,c):--f||g.resolveWith(b,c)}},i,j,k;if(d>1)for(i=new Array(d),j=new Array(d),k=new Array(d);d>b;b++)c[b]&&n.isFunction(c[b].promise)?c[b].promise().progress(h(b,j,i)).done(h(b,k,c)).fail(g.reject):--f;return f||g.resolveWith(k,c),g.promise()}});var I;n.fn.ready=function(a){return n.ready.promise().done(a),this},n.extend({isReady:!1,readyWait:1,holdReady:function(a){a?n.readyWait++:n.ready(!0)},ready:function(a){(a===!0?--n.readyWait:n.isReady)||(n.isReady=!0,a!==!0&&--n.readyWait>0||(I.resolveWith(d,[n]),n.fn.triggerHandler&&(n(d).triggerHandler("ready"),n(d).off("ready"))))}});function J(){d.removeEventListener("DOMContentLoaded",J),a.removeEventListener("load",J),n.ready()}n.ready.promise=function(b){return I||(I=n.Deferred(),"complete"===d.readyState||"loading"!==d.readyState&&!d.documentElement.doScroll?a.setTimeout(n.ready):(d.addEventListener("DOMContentLoaded",J),a.addEventListener("load",J))),I.promise(b)},n.ready.promise();var K=function(a,b,c,d,e,f,g){var h=0,i=a.length,j=null==c;if("object"===n.type(c)){e=!0;for(h in c)K(a,b,h,c[h],!0,f,g)}else if(void 0!==d&&(e=!0,n.isFunction(d)||(g=!0),j&&(g?(b.call(a,d),b=null):(j=b,b=function(a,b,c){return j.call(n(a),c)})),b))for(;i>h;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f},L=function(a){return 1===a.nodeType||9===a.nodeType||!+a.nodeType};function M(){this.expando=n.expando+M.uid++}M.uid=1,M.prototype={register:function(a,b){var c=b||{};return a.nodeType?a[this.expando]=c:Object.defineProperty(a,this.expando,{value:c,writable:!0,configurable:!0}),a[this.expando]},cache:function(a){if(!L(a))return{};var b=a[this.expando];return b||(b={},L(a)&&(a.nodeType?a[this.expando]=b:Object.defineProperty(a,this.expando,{value:b,configurable:!0}))),b},set:function(a,b,c){var d,e=this.cache(a);if("string"==typeof b)e[b]=c;else for(d in b)e[d]=b[d];return e},get:function(a,b){return void 0===b?this.cache(a):a[this.expando]&&a[this.expando][b]},access:function(a,b,c){var d;return void 0===b||b&&"string"==typeof b&&void 0===c?(d=this.get(a,b),void 0!==d?d:this.get(a,n.camelCase(b))):(this.set(a,b,c),void 0!==c?c:b)},remove:function(a,b){var c,d,e,f=a[this.expando];if(void 0!==f){if(void 0===b)this.register(a);else{n.isArray(b)?d=b.concat(b.map(n.camelCase)):(e=n.camelCase(b),b in f?d=[b,e]:(d=e,d=d in f?[d]:d.match(G)||[])),c=d.length;while(c--)delete f[d[c]]}(void 0===b||n.isEmptyObject(f))&&(a.nodeType?a[this.expando]=void 0:delete a[this.expando])}},hasData:function(a){var b=a[this.expando];return void 0!==b&&!n.isEmptyObject(b)}};var N=new M,O=new M,P=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,Q=/[A-Z]/g;function R(a,b,c){var d;if(void 0===c&&1===a.nodeType)if(d="data-"+b.replace(Q,"-$&").toLowerCase(),c=a.getAttribute(d),"string"==typeof c){try{c="true"===c?!0:"false"===c?!1:"null"===c?null:+c+""===c?+c:P.test(c)?n.parseJSON(c):c; -}catch(e){}O.set(a,b,c)}else c=void 0;return c}n.extend({hasData:function(a){return O.hasData(a)||N.hasData(a)},data:function(a,b,c){return O.access(a,b,c)},removeData:function(a,b){O.remove(a,b)},_data:function(a,b,c){return N.access(a,b,c)},_removeData:function(a,b){N.remove(a,b)}}),n.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=O.get(f),1===f.nodeType&&!N.get(f,"hasDataAttrs"))){c=g.length;while(c--)g[c]&&(d=g[c].name,0===d.indexOf("data-")&&(d=n.camelCase(d.slice(5)),R(f,d,e[d])));N.set(f,"hasDataAttrs",!0)}return e}return"object"==typeof a?this.each(function(){O.set(this,a)}):K(this,function(b){var c,d;if(f&&void 0===b){if(c=O.get(f,a)||O.get(f,a.replace(Q,"-$&").toLowerCase()),void 0!==c)return c;if(d=n.camelCase(a),c=O.get(f,d),void 0!==c)return c;if(c=R(f,d,void 0),void 0!==c)return c}else d=n.camelCase(a),this.each(function(){var c=O.get(this,d);O.set(this,d,b),a.indexOf("-")>-1&&void 0!==c&&O.set(this,a,b)})},null,b,arguments.length>1,null,!0)},removeData:function(a){return this.each(function(){O.remove(this,a)})}}),n.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=N.get(a,b),c&&(!d||n.isArray(c)?d=N.access(a,b,n.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=n.queue(a,b),d=c.length,e=c.shift(),f=n._queueHooks(a,b),g=function(){n.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return N.get(a,c)||N.access(a,c,{empty:n.Callbacks("once memory").add(function(){N.remove(a,[b+"queue",c])})})}}),n.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.length",""],thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};$.optgroup=$.option,$.tbody=$.tfoot=$.colgroup=$.caption=$.thead,$.th=$.td;function _(a,b){var c="undefined"!=typeof a.getElementsByTagName?a.getElementsByTagName(b||"*"):"undefined"!=typeof a.querySelectorAll?a.querySelectorAll(b||"*"):[];return void 0===b||b&&n.nodeName(a,b)?n.merge([a],c):c}function aa(a,b){for(var c=0,d=a.length;d>c;c++)N.set(a[c],"globalEval",!b||N.get(b[c],"globalEval"))}var ba=/<|&#?\w+;/;function ca(a,b,c,d,e){for(var f,g,h,i,j,k,l=b.createDocumentFragment(),m=[],o=0,p=a.length;p>o;o++)if(f=a[o],f||0===f)if("object"===n.type(f))n.merge(m,f.nodeType?[f]:f);else if(ba.test(f)){g=g||l.appendChild(b.createElement("div")),h=(Y.exec(f)||["",""])[1].toLowerCase(),i=$[h]||$._default,g.innerHTML=i[1]+n.htmlPrefilter(f)+i[2],k=i[0];while(k--)g=g.lastChild;n.merge(m,g.childNodes),g=l.firstChild,g.textContent=""}else m.push(b.createTextNode(f));l.textContent="",o=0;while(f=m[o++])if(d&&n.inArray(f,d)>-1)e&&e.push(f);else if(j=n.contains(f.ownerDocument,f),g=_(l.appendChild(f),"script"),j&&aa(g),c){k=0;while(f=g[k++])Z.test(f.type||"")&&c.push(f)}return l}!function(){var a=d.createDocumentFragment(),b=a.appendChild(d.createElement("div")),c=d.createElement("input");c.setAttribute("type","radio"),c.setAttribute("checked","checked"),c.setAttribute("name","t"),b.appendChild(c),l.checkClone=b.cloneNode(!0).cloneNode(!0).lastChild.checked,b.innerHTML="",l.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue}();var da=/^key/,ea=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,fa=/^([^.]*)(?:\.(.+)|)/;function ga(){return!0}function ha(){return!1}function ia(){try{return d.activeElement}catch(a){}}function ja(a,b,c,d,e,f){var g,h;if("object"==typeof b){"string"!=typeof c&&(d=d||c,c=void 0);for(h in b)ja(a,h,c,d,b[h],f);return a}if(null==d&&null==e?(e=c,d=c=void 0):null==e&&("string"==typeof c?(e=d,d=void 0):(e=d,d=c,c=void 0)),e===!1)e=ha;else if(!e)return a;return 1===f&&(g=e,e=function(a){return n().off(a),g.apply(this,arguments)},e.guid=g.guid||(g.guid=n.guid++)),a.each(function(){n.event.add(this,b,e,d,c)})}n.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=N.get(a);if(r){c.handler&&(f=c,c=f.handler,e=f.selector),c.guid||(c.guid=n.guid++),(i=r.events)||(i=r.events={}),(g=r.handle)||(g=r.handle=function(b){return"undefined"!=typeof n&&n.event.triggered!==b.type?n.event.dispatch.apply(a,arguments):void 0}),b=(b||"").match(G)||[""],j=b.length;while(j--)h=fa.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o&&(l=n.event.special[o]||{},o=(e?l.delegateType:l.bindType)||o,l=n.event.special[o]||{},k=n.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&n.expr.match.needsContext.test(e),namespace:p.join(".")},f),(m=i[o])||(m=i[o]=[],m.delegateCount=0,l.setup&&l.setup.call(a,d,p,g)!==!1||a.addEventListener&&a.addEventListener(o,g)),l.add&&(l.add.call(a,k),k.handler.guid||(k.handler.guid=c.guid)),e?m.splice(m.delegateCount++,0,k):m.push(k),n.event.global[o]=!0)}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=N.hasData(a)&&N.get(a);if(r&&(i=r.events)){b=(b||"").match(G)||[""],j=b.length;while(j--)if(h=fa.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o){l=n.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,m=i[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),g=f=m.length;while(f--)k=m[f],!e&&q!==k.origType||c&&c.guid!==k.guid||h&&!h.test(k.namespace)||d&&d!==k.selector&&("**"!==d||!k.selector)||(m.splice(f,1),k.selector&&m.delegateCount--,l.remove&&l.remove.call(a,k));g&&!m.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||n.removeEvent(a,o,r.handle),delete i[o])}else for(o in i)n.event.remove(a,o+b[j],c,d,!0);n.isEmptyObject(i)&&N.remove(a,"handle events")}},dispatch:function(a){a=n.event.fix(a);var b,c,d,f,g,h=[],i=e.call(arguments),j=(N.get(this,"events")||{})[a.type]||[],k=n.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=n.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,c=0;while((g=f.handlers[c++])&&!a.isImmediatePropagationStopped())a.rnamespace&&!a.rnamespace.test(g.namespace)||(a.handleObj=g,a.data=g.data,d=((n.event.special[g.origType]||{}).handle||g.handler).apply(f.elem,i),void 0!==d&&(a.result=d)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&("click"!==a.type||isNaN(a.button)||a.button<1))for(;i!==this;i=i.parentNode||this)if(1===i.nodeType&&(i.disabled!==!0||"click"!==a.type)){for(d=[],c=0;h>c;c++)f=b[c],e=f.selector+" ",void 0===d[e]&&(d[e]=f.needsContext?n(e,this).index(i)>-1:n.find(e,this,null,[i]).length),d[e]&&d.push(f);d.length&&g.push({elem:i,handlers:d})}return h]*)\/>/gi,la=/\s*$/g;function pa(a,b){return n.nodeName(a,"table")&&n.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function qa(a){return a.type=(null!==a.getAttribute("type"))+"/"+a.type,a}function ra(a){var b=na.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function sa(a,b){var c,d,e,f,g,h,i,j;if(1===b.nodeType){if(N.hasData(a)&&(f=N.access(a),g=N.set(b,f),j=f.events)){delete g.handle,g.events={};for(e in j)for(c=0,d=j[e].length;d>c;c++)n.event.add(b,e,j[e][c])}O.hasData(a)&&(h=O.access(a),i=n.extend({},h),O.set(b,i))}}function ta(a,b){var c=b.nodeName.toLowerCase();"input"===c&&X.test(a.type)?b.checked=a.checked:"input"!==c&&"textarea"!==c||(b.defaultValue=a.defaultValue)}function ua(a,b,c,d){b=f.apply([],b);var e,g,h,i,j,k,m=0,o=a.length,p=o-1,q=b[0],r=n.isFunction(q);if(r||o>1&&"string"==typeof q&&!l.checkClone&&ma.test(q))return a.each(function(e){var f=a.eq(e);r&&(b[0]=q.call(this,e,f.html())),ua(f,b,c,d)});if(o&&(e=ca(b,a[0].ownerDocument,!1,a,d),g=e.firstChild,1===e.childNodes.length&&(e=g),g||d)){for(h=n.map(_(e,"script"),qa),i=h.length;o>m;m++)j=e,m!==p&&(j=n.clone(j,!0,!0),i&&n.merge(h,_(j,"script"))),c.call(a[m],j,m);if(i)for(k=h[h.length-1].ownerDocument,n.map(h,ra),m=0;i>m;m++)j=h[m],Z.test(j.type||"")&&!N.access(j,"globalEval")&&n.contains(k,j)&&(j.src?n._evalUrl&&n._evalUrl(j.src):n.globalEval(j.textContent.replace(oa,"")))}return a}function va(a,b,c){for(var d,e=b?n.filter(b,a):a,f=0;null!=(d=e[f]);f++)c||1!==d.nodeType||n.cleanData(_(d)),d.parentNode&&(c&&n.contains(d.ownerDocument,d)&&aa(_(d,"script")),d.parentNode.removeChild(d));return a}n.extend({htmlPrefilter:function(a){return a.replace(ka,"<$1>")},clone:function(a,b,c){var d,e,f,g,h=a.cloneNode(!0),i=n.contains(a.ownerDocument,a);if(!(l.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||n.isXMLDoc(a)))for(g=_(h),f=_(a),d=0,e=f.length;e>d;d++)ta(f[d],g[d]);if(b)if(c)for(f=f||_(a),g=g||_(h),d=0,e=f.length;e>d;d++)sa(f[d],g[d]);else sa(a,h);return g=_(h,"script"),g.length>0&&aa(g,!i&&_(a,"script")),h},cleanData:function(a){for(var b,c,d,e=n.event.special,f=0;void 0!==(c=a[f]);f++)if(L(c)){if(b=c[N.expando]){if(b.events)for(d in b.events)e[d]?n.event.remove(c,d):n.removeEvent(c,d,b.handle);c[N.expando]=void 0}c[O.expando]&&(c[O.expando]=void 0)}}}),n.fn.extend({domManip:ua,detach:function(a){return va(this,a,!0)},remove:function(a){return va(this,a)},text:function(a){return K(this,function(a){return void 0===a?n.text(this):this.empty().each(function(){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||(this.textContent=a)})},null,a,arguments.length)},append:function(){return ua(this,arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=pa(this,a);b.appendChild(a)}})},prepend:function(){return ua(this,arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=pa(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return ua(this,arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return ua(this,arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},empty:function(){for(var a,b=0;null!=(a=this[b]);b++)1===a.nodeType&&(n.cleanData(_(a,!1)),a.textContent="");return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return n.clone(this,a,b)})},html:function(a){return K(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a&&1===b.nodeType)return b.innerHTML;if("string"==typeof a&&!la.test(a)&&!$[(Y.exec(a)||["",""])[1].toLowerCase()]){a=n.htmlPrefilter(a);try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(n.cleanData(_(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=[];return ua(this,arguments,function(b){var c=this.parentNode;n.inArray(this,a)<0&&(n.cleanData(_(this)),c&&c.replaceChild(b,this))},a)}}),n.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){n.fn[a]=function(a){for(var c,d=[],e=n(a),f=e.length-1,h=0;f>=h;h++)c=h===f?this:this.clone(!0),n(e[h])[b](c),g.apply(d,c.get());return this.pushStack(d)}});var wa,xa={HTML:"block",BODY:"block"};function ya(a,b){var c=n(b.createElement(a)).appendTo(b.body),d=n.css(c[0],"display");return c.detach(),d}function za(a){var b=d,c=xa[a];return c||(c=ya(a,b),"none"!==c&&c||(wa=(wa||n("