diff --git a/Dockerfile b/Dockerfile index ede3cc9..d93bfa1 100644 --- a/Dockerfile +++ b/Dockerfile @@ -30,7 +30,7 @@ RUN GOOS=darwin GARCH=amd64 go build \ -o /dist/promutil \ -a \ -ldflags "-s -w -extldflags \"-fno-PIC -static\" -X github.com/kadaan/promutil/version.Version=$VERSION -X github.com/kadaan/promutil/version.Revision=$REVISION -X github.com/kadaan/promutil/version.Branch=$BRANCH -X github.com/kadaan/promutil/version.BuildUser=$USER -X github.com/kadaan/promutil/version.BuildHost=$HOST -X github.com/kadaan/promutil/version.BuildDate=$BUILD_DATE" \ - -tags 'osusergo netgo' \ + -tags 'osusergo netgo jsoniter' \ -installsuffix netgo && \ tar -czf "/archives/promutil_darwin.tar.gz" -C "/dist" . @@ -39,7 +39,7 @@ RUN GOOS=linux GARCH=amd64 go build \ -o /dist/promutil \ -a \ -ldflags "-s -w -X github.com/kadaan/promutil/version.Version=$VERSION -X github.com/kadaan/promutil/version.Revision=$REVISION -X github.com/kadaan/promutil/version.Branch=$BRANCH -X github.com/kadaan/promutil/version.BuildUser=$USER -X github.com/kadaan/promutil/version.BuildHost=$HOST -X github.com/kadaan/promutil/version.BuildDate=$BUILD_DATE" \ - -tags 'osusergo netgo static_build' \ + -tags 'osusergo netgo jsoniter static_build' \ -installsuffix netgo && \ tar -czf "/archives/promutil_linux.tar.gz" -C "/dist" . diff --git a/cmd/web.go b/cmd/web.go index 31fedd1..9942d76 100644 --- a/cmd/web.go +++ b/cmd/web.go @@ -2,6 +2,7 @@ package cmd import ( "github.com/kadaan/promutil/config" + "github.com/kadaan/promutil/lib/block" "github.com/kadaan/promutil/lib/command" "github.com/kadaan/promutil/lib/web" ) @@ -17,5 +18,6 @@ func init() { fb.ListenAddress(&cfg.ListenAddress, "the listen address") fb.SampleInterval(&cfg.SampleInterval, "interval at which samples will be taken within a range") fb.Host(&cfg.Host, "remote prometheus host") + fb.Parallelism(&cfg.Parallelism, block.MaxParallelism, "parallelism for backfill") }) } diff --git a/config/common.go b/config/common.go index fb3c7bb..2e97b8e 100644 --- a/config/common.go +++ b/config/common.go @@ -36,6 +36,7 @@ var ( defaultRuleGroupFilters = []*regexp.Regexp{regexp.MustCompile(".+")} defaultRuleNameFilters = []*regexp.Regexp{regexp.MustCompile(".+")} yamlFileExtensions = []string{"yml", "yaml"} + defaultListenAddress = ListenAddress{Host: "", Port: 8080} ) func NewFlagBuilder(cmd *cobra.Command) FlagBuilder { @@ -241,6 +242,6 @@ func (fb *flagBuilder) Matchers(dest *map[string][]*labels.Matcher, usage string func (fb *flagBuilder) ListenAddress(dest *ListenAddress, usage string) Flag { return fb.newFlag(listenAddressKey, func(flagSet *pflag.FlagSet) { - flagSet.Var(NewListenAddressValue(dest, ListenAddress{Host: "", Port: 8080}), listenAddressKey, usage) + flagSet.Var(NewListenAddressValue(dest, defaultListenAddress), listenAddressKey, usage) }) } diff --git a/config/web.go b/config/web.go index 2ba3226..28973f6 100644 --- a/config/web.go +++ b/config/web.go @@ -5,13 +5,10 @@ import ( "time" ) -const ( - DefaultListenAddress = ":8080" -) - // WebConfig represents the configuration of the web command. type WebConfig struct { ListenAddress ListenAddress Host *url.URL SampleInterval time.Duration + Parallelism uint8 } diff --git a/lib/block/planner.go b/lib/block/planner.go index f07db19..f88526d 100644 --- a/lib/block/planner.go +++ b/lib/block/planner.go @@ -146,12 +146,12 @@ func (p *planner[V]) Plan(transform func(int64, int64, int64) []PlanEntry[V]) [] stepDuration := int64(p.config.SampleInterval() / (time.Millisecond / time.Nanosecond)) for ; blockStart <= endInMs; blockStart = blockStart + p.config.BlockDuration() { blockEnd := blockStart + p.config.BlockDuration() - 1 - currStart := p.max(blockStart/int64(time.Second/time.Millisecond), p.config.StartTime().Unix()) + currStart := common.MaxInt64(blockStart/int64(time.Second/time.Millisecond), p.config.StartTime().Unix()) startWithAlignment := p.evalTimestamp(time.Unix(currStart, 0).UTC().UnixNano(), stepDuration) for startWithAlignment.Unix() < currStart { startWithAlignment = startWithAlignment.Add(p.config.SampleInterval()) } - end := time.Unix(p.min(blockEnd/int64(time.Second/time.Millisecond), p.config.EndTime().Unix()), 0).UTC() + end := time.Unix(common.MinInt64(blockEnd/int64(time.Second/time.Millisecond), p.config.EndTime().Unix()), 0).UTC() if end.Equal(startWithAlignment) || end.Before(startWithAlignment) { break } @@ -181,20 +181,6 @@ func (p *planner[V]) planBlock(blockStart time.Time, blockEnd time.Time, stepDur return plan } -func (p *planner[V]) max(x, y int64) int64 { - if x > y { - return x - } - return y -} - -func (p *planner[V]) min(x, y int64) int64 { - if x < y { - return x - } - return y -} - func (p *planner[V]) evalTimestamp(startTime int64, stepDuration int64) time.Time { var ( offset = stepDuration @@ -437,7 +423,7 @@ func (p *plannedBlockWriter[V]) Run() error { go func() { select { - case <-s.C: + case <-s.C(): klog.V(0).Infof("Stopping producer, consumers, and db") cancel() } diff --git a/lib/command/command.go b/lib/command/command.go index 4eacd91..f6ad583 100644 --- a/lib/command/command.go +++ b/lib/command/command.go @@ -10,9 +10,13 @@ import ( "github.com/spf13/cobra" "github.com/spf13/pflag" "github.com/spf13/viper" + "io" "k8s.io/klog/v2" "log" "os" + "runtime" + "runtime/pprof" + "runtime/trace" ) var ( @@ -22,6 +26,7 @@ var ( type RootCommand interface { Execute() addCommand(cmd *cobra.Command) + startProfiler() (io.Closer, error) } func NewRootCommand(short string, long string) RootCommand { @@ -42,15 +47,68 @@ func NewRootCommand(short string, long string) RootCommand { r.addVersionCommand(r.cmd) r.addCompletionCommand(r.cmd) cobra.OnInitialize(r.initConfig) + r.cmd.PersistentFlags().StringVar(&r.cpuProfile, "cpuProfile", "", "Cpu profile result file") + r.cmd.PersistentFlags().StringVar(&r.memoryProfile, "memoryProfile", "", "Memory profile result file") + r.cmd.PersistentFlags().StringVar(&r.traceProfile, "traceProfile", "", "Trace profile result file") r.cmd.PersistentFlags().CountVarP(&r.verbosity, "verbose", "v", "enables verbose logging (multiple times increases verbosity)") r.cmd.PersistentFlags().StringVar(&r.cfgFile, "config", "", "config file (default is ."+version.Name+".config)") return r } type rootCommand struct { - verbosity int - cfgFile string - cmd *cobra.Command + cpuProfile string + memoryProfile string + traceProfile string + verbosity int + cfgFile string + cmd *cobra.Command +} + +func (r *rootCommand) startProfiler() (io.Closer, error) { + p := profiler{} + if r.traceProfile != "" { + f, err := os.Create(r.traceProfile) + if err != nil { + return &p, errors.Wrap(err, "could not create Trace profile") + } + p.fileClosers = append(p.fileClosers, f) + if err = trace.Start(f); err != nil { + return &p, errors.Wrap(err, "could not start Trace profile") + } + p.methodClosers = append(p.methodClosers, func() error { + trace.Stop() + return nil + }) + } + if r.cpuProfile != "" { + f, err := os.Create(r.cpuProfile) + if err != nil { + return &p, errors.Wrap(err, "could not create CPU profile") + } + p.fileClosers = append(p.fileClosers, f) + if err = pprof.StartCPUProfile(f); err != nil { + return &p, errors.Wrap(err, "could not start CPU profile") + } + p.methodClosers = append(p.methodClosers, func() error { + pprof.StopCPUProfile() + return nil + }) + } + if r.memoryProfile != "" { + f, err := os.Create(r.memoryProfile) + if err != nil { + return &p, errors.Wrap(err, "could not create memory profile") + } + p.fileClosers = append(p.fileClosers, f) + p.methodClosers = append(p.methodClosers, func() error { + runtime.GC() + if err = pprof.WriteHeapProfile(f); err != nil { + return errors.Wrap(err, "could not write memory profile") + } + return nil + }) + } + return &p, nil } func (r *rootCommand) addCommand(cmd *cobra.Command) { @@ -188,7 +246,17 @@ func NewCommand[C any](root RootCommand, use string, short string, long string, Short: short, Long: long, RunE: func(cmd *cobra.Command, args []string) error { - if err := task.Run(cfg); err != nil { + p, err := root.startProfiler() + defer func(profiler io.Closer) { + errP := profiler.Close() + if errP != nil { + klog.Errorf("failed to close profiler: %w", errP) + } + }(p) + if err != nil { + return errors.Wrap(err, "failed to start profiler") + } + if err = task.Run(cfg); err != nil { return errors.Wrap(err, "%s failed", use) } return nil @@ -204,3 +272,26 @@ func NewCommand[C any](root RootCommand, use string, short string, long string, type Task[C any] interface { Run(cfg *C) error } + +type profiler struct { + fileClosers []io.Closer + methodClosers []func() error +} + +func (p *profiler) Close() error { + var errs []error + for _, methodCloser := range p.methodClosers { + if err := methodCloser(); err != nil { + errs = append(errs, err) + } + } + for _, fileCloser := range p.fileClosers { + if err := fileCloser.Close(); err != nil { + errs = append(errs, err) + } + } + if len(errs) > 0 { + return errors.NewMulti(errs, "failed to close profiler") + } + return nil +} diff --git a/lib/common/canceller.go b/lib/common/canceller.go index 5a834d9..67069b8 100644 --- a/lib/common/canceller.go +++ b/lib/common/canceller.go @@ -3,22 +3,35 @@ package common import "sync" type Canceller interface { + C() chan struct{} + Cancelled() bool Cancel() } type canceller struct { - C chan struct{} - once sync.Once + cancelled bool + c chan struct{} + once sync.Once } func NewCanceller() *canceller { return &canceller{ - C: make(chan struct{}), + cancelled: false, + c: make(chan struct{}), } } +func (s *canceller) C() chan struct{} { + return s.c +} + +func (s *canceller) Cancelled() bool { + return s.cancelled +} + func (s *canceller) Cancel() { s.once.Do(func() { - close(s.C) + s.cancelled = true + close(s.c) }) } diff --git a/lib/common/common.go b/lib/common/common.go index 825fbed..a21d79d 100644 --- a/lib/common/common.go +++ b/lib/common/common.go @@ -101,3 +101,31 @@ func JoinUrl(base *url.URL, paths ...string) (*url.URL, error) { p := path.Join(paths...) return url.Parse(fmt.Sprintf("%s/%s", strings.TrimRight(s, "/"), strings.TrimLeft(p, "/"))) } + +func MaxInt64(x int64, y int64) int64 { + if x > y { + return x + } + return y +} + +func MinInt64(x int64, y int64) int64 { + if x < y { + return x + } + return y +} + +func MaxUInt8(x uint8, y uint8) uint8 { + if x > y { + return x + } + return y +} + +func MinTime(x time.Time, y time.Time) time.Time { + if x.After(y) { + return y + } + return x +} diff --git a/lib/remote/queryable.go b/lib/remote/queryable.go index 2313c8c..cad034c 100644 --- a/lib/remote/queryable.go +++ b/lib/remote/queryable.go @@ -7,6 +7,7 @@ import ( "github.com/cespare/xxhash/v2" "github.com/kadaan/promutil/lib/common" "github.com/kadaan/promutil/lib/errors" + "github.com/kadaan/tracerr" "github.com/prometheus/client_golang/api" v1 "github.com/prometheus/client_golang/api/prometheus/v1" "github.com/prometheus/common/model" @@ -14,28 +15,72 @@ import ( "github.com/prometheus/prometheus/model/timestamp" "github.com/prometheus/prometheus/promql" "github.com/prometheus/prometheus/rules" - "math" + "io" "net/url" "sort" + "sync" "time" - //"time" ) -func NewQueryable(address *url.URL) (Queryable, error) { +const ( + maxChunkDuration = 30 * time.Minute +) + +func NewQueryable(address *url.URL, parallelism uint8) (Queryable, error) { client, err := api.NewClient(api.Config{ Address: address.String(), }) if err != nil { return nil, errors.Wrap(err, "failed to create queryable provider") } + ctx, cancel := context.WithCancel(context.Background()) + var cg sync.WaitGroup + promApi := v1.NewAPI(client) + inputChan := make(chan plan) + for i := uint8(0); i < common.MaxUInt8(parallelism, uint8(1)); i++ { + qr := querier{ + ctx: ctx, + cg: &cg, + promApi: promApi, + input: inputChan, + stopOnce: &sync.Once{}, + } + cg.Add(1) + go qr.run() + } return &queryable{ - client: client, + cg: &cg, + inputChan: inputChan, + cancel: cancel, + }, nil +} + +type queryable struct { + cg *sync.WaitGroup + inputChan chan plan + cancel context.CancelFunc +} + +func (q *queryable) Close() error { + q.cancel() + q.cg.Wait() + return nil +} + +func (q *queryable) QueryFuncProvider(minTimestamp time.Time, maxTimestamp time.Time, step time.Duration) (QueryFuncProvider, error) { + return &queryFuncProvider{ + minTimestamp: minTimestamp, + maxTimestamp: maxTimestamp, + step: step, + inputChan: q.inputChan, + queryResultCache: map[string]map[time.Duration][]*queryCacheEntry{}, }, nil } type RangeQueryFunc func(ctx context.Context, qs string, start time.Time, end time.Time, interval time.Duration) (promql.Matrix, error) type Queryable interface { + io.Closer QueryFuncProvider(minTimestamp time.Time, maxTimestamp time.Time, step time.Duration) (QueryFuncProvider, error) } @@ -50,15 +95,14 @@ type queryCacheEntry struct { query string matrix *promql.Matrix interval time.Duration - stats []seriesStats cached bool } type queryFuncProvider struct { - promApi v1.API minTimestamp time.Time maxTimestamp time.Time step time.Duration + inputChan chan plan queryResultCache map[string]map[time.Duration][]*queryCacheEntry } @@ -132,17 +176,17 @@ func (q *queryFuncProvider) InstantQueryFunc(allowArbitraryQueries bool) rules.Q func (q *queryFuncProvider) RangeQueryFunc() RangeQueryFunc { return func(ctx context.Context, qs string, start time.Time, end time.Time, interval time.Duration) (promql.Matrix, error) { - result, err := q.query(ctx, qs, start, end, interval, true, true) + r, err := q.query(ctx, qs, start, end, interval, true, true) if err != nil { return nil, err } - if result.minTimestamp.Equal(start) && result.maxTimestamp.Equal(end) { - return *result.matrix, nil + if r.minTimestamp.Equal(start) && r.maxTimestamp.Equal(end) { + return *r.matrix, nil } minTs := start.UnixMilli() maxTs := end.UnixMilli() var matrix promql.Matrix - for _, series := range *result.matrix { + for _, series := range *r.matrix { var points []promql.Point for _, point := range series.Points { if point.T >= minTs && point.T <= maxTs { @@ -160,50 +204,63 @@ func (q *queryFuncProvider) RangeQueryFunc() RangeQueryFunc { } } -type seriesStats struct { - MinTimestamp int64 - MaxTimestamp int64 +type plan struct { + ctx context.Context + wg *sync.WaitGroup + queryRange v1.Range + queryExpr string + output chan<- result + stopOnce *sync.Once + canceller common.Canceller } -func (q *queryFuncProvider) query(ctx context.Context, query string, start time.Time, end time.Time, interval time.Duration, addToCache bool, allowArbitraryQueries bool) (*queryCacheEntry, error) { - if queryCache, ok := q.queryResultCache[query]; ok { - if intervalCache, ok2 := queryCache[interval]; ok2 { - for _, entry := range intervalCache { - if start.Before(entry.minTimestamp) || - start.After(entry.maxTimestamp) || - end.Before(entry.minTimestamp) || - end.After(entry.maxTimestamp) { - // Skip because the request query is not a subset of this query - } else { - return entry, nil +type result struct { + cancelled bool + wg *sync.WaitGroup + err tracerr.Error + series []*promql.Series +} + +type querier struct { + ctx context.Context + cg *sync.WaitGroup + promApi v1.API + input <-chan plan + stopOnce *sync.Once +} + +func (q *querier) run() { + for { + select { + case <-q.ctx.Done(): + q.stopOnce.Do(func() { + q.cg.Done() + }) + return + case p, ok := <-q.input: + if !ok { + p.stopOnce.Do(func() { + q.cg.Done() + }) + return + } + if p.canceller.Cancelled() { + p.output <- result{ + cancelled: true, + wg: p.wg, } + continue } + q.execute(p) } } +} - if !allowArbitraryQueries { - var matrix promql.Matrix - entry := &queryCacheEntry{ - minTimestamp: start, - maxTimestamp: end, - interval: interval, - query: query, - matrix: &matrix, - cached: false, - } - return entry, nil - } - - rng := v1.Range{ - Start: start, - End: end, - Step: interval, - } - +func (q *querier) execute(p plan) { var value *model.Value const attempts = 5 err := backoff.Retry(func() error { - r, _, e := q.promApi.QueryRange(ctx, query, rng) + r, _, e := q.promApi.QueryRange(p.ctx, p.queryExpr, p.queryRange) if e != nil { return e } @@ -211,36 +268,24 @@ func (q *queryFuncProvider) query(ctx context.Context, query string, start time. return nil }, backoff.WithMaxRetries(backoff.NewExponentialBackOff(), attempts)) if err != nil { - return nil, errors.Wrap(err, "failed to query '%s' from %d to %d after %d attempts", query, rng.Start, rng.End, attempts) + p.output <- result{ + wg: p.wg, + err: errors.Wrap(err, "failed to query '%s' from %d to %d after %d attempts", p.queryExpr, p.queryRange.Start, p.queryRange.End, attempts), + } + return } - var stats []seriesStats - var matrix promql.Matrix + switch v := (*value).(type) { case model.Matrix: + var series []*promql.Series for _, ss := range v { - stat := seriesStats{ - MinTimestamp: math.MaxInt64, - MaxTimestamp: math.MinInt64, - } var points []promql.Point for _, s := range ss.Values { - ts := common.TimeMilliseconds(s.Timestamp) - if ts < stat.MinTimestamp { - stat.MinTimestamp = ts - } - if ts > stat.MaxTimestamp { - stat.MaxTimestamp = ts - } points = append(points, promql.Point{ - T: ts, + T: common.TimeMilliseconds(s.Timestamp), V: float64(s.Value), }) } - for _, s := range matrix { - sort.Slice(s.Points, func(i, j int) bool { - return s.Points[i].T-s.Points[j].T < 0 - }) - } var metric labels.Labels for k, v := range ss.Metric { metric = append(metric, labels.Label{ @@ -249,26 +294,135 @@ func (q *queryFuncProvider) query(ctx context.Context, query string, start time. }) } sort.Sort(metric) - sort.Slice(points, func(i, j int) bool { - return points[i].T-points[j].T < 0 - }) - matrix = append(matrix, promql.Series{ + series = append(series, &promql.Series{ Metric: metric, Points: points, }) - stats = append(stats, stat) + } + p.output <- result{ + wg: p.wg, + series: series, } default: - return nil, errors.New("query range result is not a matrix") + p.output <- result{ + wg: p.wg, + err: errors.New("query range result is not a matrix"), + } + } +} + +func (q *queryFuncProvider) query(ctx context.Context, query string, start time.Time, end time.Time, interval time.Duration, addToCache bool, allowArbitraryQueries bool) (*queryCacheEntry, error) { + if queryCache, ok := q.queryResultCache[query]; ok { + if intervalCache, ok2 := queryCache[interval]; ok2 { + for _, entry := range intervalCache { + if start.Before(entry.minTimestamp) || + start.After(entry.maxTimestamp) || + end.Before(entry.minTimestamp) || + end.After(entry.maxTimestamp) { + // Skip because the request query is not a subset of this query + } else { + return entry, nil + } + } + } + } + + if !allowArbitraryQueries { + var matrix promql.Matrix + entry := &queryCacheEntry{ + minTimestamp: start, + maxTimestamp: end, + interval: interval, + query: query, + matrix: &matrix, + cached: false, + } + return entry, nil + } + + pCtx, cancel := context.WithCancel(ctx) + canceller := common.NewCanceller() + outputChan := make(chan result) + defer close(outputChan) + + var wg sync.WaitGroup + var err tracerr.Error + metricSeriesMap := make(map[uint64]*promql.Series) + go func(canceller common.Canceller) { + for { + select { + case s, ok := <-outputChan: + if !ok { + return + } + if s.err != nil { + err = s.err + canceller.Cancel() + } else if !s.cancelled { + for _, ss := range s.series { + metricHash := ss.Metric.Hash() + if series, exists := metricSeriesMap[metricHash]; !exists { + metricSeriesMap[metricHash] = ss + } else { + series.Points = append(series.Points, ss.Points...) + } + } + } + s.wg.Done() + } + } + }(canceller) + + chunkStart := start + for ; !chunkStart.After(end); chunkStart = chunkStart.Add(maxChunkDuration) { + chunkEnd := common.MinTime(chunkStart.Add(maxChunkDuration).Add(-1*time.Nanosecond), end) + wg.Add(1) + q.inputChan <- plan{ + canceller: canceller, + ctx: pCtx, + wg: &wg, + queryRange: v1.Range{ + Start: chunkStart, + End: chunkEnd, + Step: interval, + }, + queryExpr: query, + output: outputChan, + stopOnce: &sync.Once{}, + } + } + + go func() { + select { + case <-ctx.Done(): + canceller.Cancel() + cancel() + case <-canceller.C(): + cancel() + } + }() + + wg.Wait() + cancel() + + if err != nil { + return nil, err + } + + var matrix promql.Matrix + for _, s := range metricSeriesMap { + sort.Slice(s.Points, func(i, j int) bool { + return s.Points[i].T-s.Points[j].T < 0 + }) + matrix = append(matrix, *s) } entry := &queryCacheEntry{ - minTimestamp: rng.Start, - maxTimestamp: rng.End, + minTimestamp: start, + maxTimestamp: end, interval: interval, query: query, matrix: &matrix, - stats: stats, cached: false, } @@ -277,26 +431,11 @@ func (q *queryFuncProvider) query(ctx context.Context, query string, start time. if _, exists := q.queryResultCache[query]; !exists { q.queryResultCache[query] = make(map[time.Duration][]*queryCacheEntry) } - if _, exists := q.queryResultCache[query][rng.Step]; !exists { - q.queryResultCache[query][rng.Step] = make([]*queryCacheEntry, 0) + if _, exists := q.queryResultCache[query][interval]; !exists { + q.queryResultCache[query][interval] = make([]*queryCacheEntry, 0) } - q.queryResultCache[query][rng.Step] = append(q.queryResultCache[query][rng.Step], entry) + q.queryResultCache[query][interval] = append(q.queryResultCache[query][interval], entry) } return entry, nil } - -type queryable struct { - client api.Client -} - -func (q *queryable) QueryFuncProvider(minTimestamp time.Time, maxTimestamp time.Time, step time.Duration) (QueryFuncProvider, error) { - promApi := v1.NewAPI(q.client) - return &queryFuncProvider{ - promApi: promApi, - minTimestamp: minTimestamp, - maxTimestamp: maxTimestamp, - step: step, - queryResultCache: map[string]map[time.Duration][]*queryCacheEntry{}, - }, nil -} diff --git a/lib/web/alertTester.go b/lib/web/alertTester.go index ae99461..d84d612 100644 --- a/lib/web/alertTester.go +++ b/lib/web/alertTester.go @@ -1,12 +1,12 @@ package web import ( - "bytes" "context" "fmt" "github.com/cespare/xxhash/v2" "github.com/gin-gonic/gin" kitLog "github.com/go-kit/kit/log" + jsoniter "github.com/json-iterator/go" "github.com/kadaan/promutil/config" "github.com/kadaan/promutil/lib/common" "github.com/kadaan/promutil/lib/errors" @@ -18,11 +18,15 @@ import ( "github.com/prometheus/prometheus/promql/parser" "github.com/prometheus/prometheus/rules" "github.com/prometheus/prometheus/util/stats" + htmlTemplate "html/template" + "math" "net/http" "net/url" + "sort" + "strconv" "strings" - textTemplate "text/template" "time" + "unsafe" ) const ( @@ -30,52 +34,112 @@ const ( alertTestingRoute = "/alerts_testing" alertRuleTestingRoute = "/alert-rule-testing" alertForStateMetricName = "ALERTS_FOR_STATE" - alertHtmlSnippet = `name: {{ .Alert }} -expr: {{ .Expr }} -for: {{ .For }} -{{- if .Labels }} -labels: - {{- range $key, $value := .Labels }} - {{ $key }}: {{ $value }} - {{- end }} -{{- end }} -{{- if .Annotations }} -annotations: - {{- range $key, $value := .Annotations }} - {{ $key }}: {{ $value }} - {{- end }} -{{- end }}` + // alertHtmlSnippet = `name: {{ .Alert }} + //expr: {{ .Expr }} + //for: {{ .For }} + //{{- if .Labels }} + //labels: + // {{- range $key, $value := .Labels }} + // {{ $key }}: {{ $value }} + // {{- end }} + //{{- end }} + //{{- if .Annotations }} + //annotations: + // {{- range $key, $value := .Annotations }} + // {{ $key }}: {{ $value }} + // {{- end }} + //{{- end }}` ) -type timestamp int64 +func init() { + jsoniter.RegisterTypeEncoderFunc("float64", marshalValueJSON, marshalValueJSONIsEmpty) + jsoniter.RegisterTypeEncoderFunc("time.Time", marshalTimeJSON, marshalTimeJSONIsEmpty) + jsoniter.RegisterTypeEncoderFunc("promql.Point", marshalPointJSON, marshalPointJSONIsEmpty) +} + +func marshalPointJSON(ptr unsafe.Pointer, stream *jsoniter.Stream) { + p := *((*promql.Point)(ptr)) + stream.WriteArrayStart() + marshalTimestamp(p.T, stream) + stream.WriteMore() + marshalValue(p.V, stream) + stream.WriteArrayEnd() +} -func (t timestamp) MarshalJSON() ([]byte, error) { - buffer := bytes.Buffer{} - ts := int64(t) - if ts < 0 { - buffer.WriteString("-") - ts = -ts +func marshalPointJSONIsEmpty(_ unsafe.Pointer) bool { + return false +} + +func marshalTimeJSON(ptr unsafe.Pointer, stream *jsoniter.Stream) { + p := *((*time.Time)(ptr)) + if p.IsZero() { + stream.WriteNil() + } else { + marshalTimestamp(p.UnixMilli(), stream) } - buffer.WriteString(fmt.Sprintf("%d", ts/1000)) - fraction := ts % 1000 +} + +func marshalTimeJSONIsEmpty(_ unsafe.Pointer) bool { + return false +} + +func marshalTimestamp(t int64, stream *jsoniter.Stream) { + // Write out the timestamp as a float divided by 1000. + // This is ~3x faster than converting to a float. + if t < 0 { + stream.WriteRaw(`-`) + t = -t + } + stream.WriteInt64(t / 1000) + fraction := t % 1000 if fraction != 0 { - buffer.WriteString(".") + stream.WriteRaw(`.`) if fraction < 100 { - buffer.WriteString("0") + stream.WriteRaw(`0`) } if fraction < 10 { - buffer.WriteString("0") + stream.WriteRaw(`0`) + } + stream.WriteInt64(fraction) + } +} + +func marshalValueJSON(ptr unsafe.Pointer, stream *jsoniter.Stream) { + p := *((*float64)(ptr)) + marshalValue(p, stream) +} + +func marshalValueJSONIsEmpty(_ unsafe.Pointer) bool { + return false +} + +func marshalValue(v float64, stream *jsoniter.Stream) { + if math.IsNaN(v) { + stream.WriteString("NaN") + } else { + stream.WriteRaw(`"`) + // Taken from https://github.com/json-iterator/go/blob/master/stream_float.go#L71 as a workaround + // to https://github.com/json-iterator/go/issues/365 (jsoniter, to follow json standard, doesn't allow inf/nan). + buf := stream.Buffer() + abs := math.Abs(v) + valueFmt := byte('f') + // Note: Must use float32 comparisons for underlying float32 value to get precise cutoffs right. + if abs != 0 { + if abs < 1e-6 || abs >= 1e21 { + valueFmt = 'e' + } } - buffer.WriteString(fmt.Sprintf("%d", fraction)) + buf = strconv.AppendFloat(buf, v, valueFmt, -1, 64) + stream.SetBuffer(buf) + stream.WriteRaw(`"`) } - return buffer.Bytes(), nil } type alertsTestResult struct { IsError bool `json:"isError"` Errors []string `json:"errors"` - Start timestamp `json:"start"` - End timestamp `json:"end"` + Start time.Time `json:"start"` + End time.Time `json:"end"` Step int64 `json:"step"` AlertStateToRowClass map[rules.AlertState]string `json:"alertStateToRowClass"` AlertStateToName map[rules.AlertState]string `json:"alertStateToName"` @@ -109,12 +173,20 @@ func newAlertsTestResult() alertsTestResult { } type ruleResult struct { - Group string `json:"group"` - Name string `json:"name"` + Definition *alertDefinition `json:"definition"` Alerts *[]rules.Alert `json:"alerts"` MatrixResult *queryData `json:"matrixResult"` ExprQueryResult *queryDataWithExpr `json:"exprQueryResult"` - HTMLSnippet string `json:"htmlSnippet"` +} + +type alertDefinition struct { + Group string `json:"group"` + Name string `json:"name"` + Expr string `json:"expr"` + ExprTableUrl string `json:"exprTableUrl"` + For string `json:"for"` + Labels []map[string]string `json:"labels"` + Annotations []map[string]string `json:"annotations"` } type queryData struct { @@ -130,21 +202,21 @@ type queryDataWithExpr struct { } type alertTester struct { - templateExecutor TemplateExecutor - queryable remote.Queryable - config *config.WebConfig - alertHtmlSnippetTemplate *textTemplate.Template + templateExecutor TemplateExecutor + queryable remote.Queryable + config *config.WebConfig + //alertHtmlSnippetTemplate *textTemplate.Template } func NewAlertTester(config *config.WebConfig) (Route, error) { - alertHtmlSnippetTemplate := textTemplate.New("alertHtmlSnippet") - var err error - if alertHtmlSnippetTemplate, err = alertHtmlSnippetTemplate.Parse(alertHtmlSnippet); err != nil { - return nil, errors.Wrap(err, "failed to parse alert html snippet") - } + //alertHtmlSnippetTemplate := textTemplate.New("alertHtmlSnippet") + //var err error + //if alertHtmlSnippetTemplate, err = alertHtmlSnippetTemplate.Parse(alertHtmlSnippet); err != nil { + // return nil, errors.Wrap(err, "failed to parse alert html snippet") + //} return &alertTester{ - config: config, - alertHtmlSnippetTemplate: alertHtmlSnippetTemplate, + config: config, + //alertHtmlSnippetTemplate: alertHtmlSnippetTemplate, }, nil } @@ -180,15 +252,15 @@ func (t *alertTester) alertsTesting(requestContext *gin.Context) { if cfg, err := t.parseAlertsTestingBody(requestContext.Request); err != nil { result.addErrors(err) } else { - result.Start = timestamp(cfg.Start.UnixMilli()) - result.End = timestamp(cfg.End.UnixMilli()) + result.Start = time.UnixMilli(cfg.Start.UnixMilli()) + result.End = time.UnixMilli(cfg.End.UnixMilli()) result.Step = cfg.Step.Milliseconds() for _, group := range cfg.RuleGroups.Groups { for _, rule := range group.Rules { if rule.Alert.Value == "" { continue } - htmlSnippet, alerts, matrixResult, exprQueryResult, errA := t.evaluateAlertRule( + alertDefinition, alerts, matrixResult, exprQueryResult, errA := t.evaluateAlertRule( requestContext.Request.Context(), t.queryable, cfg.Start, @@ -197,10 +269,8 @@ func (t *alertTester) alertsTesting(requestContext *gin.Context) { group, rule) r := ruleResult{ - Group: group.Name, - Name: rule.Alert.Value, + Definition: alertDefinition, Alerts: alerts, - HTMLSnippet: htmlSnippet, MatrixResult: matrixResult, ExprQueryResult: exprQueryResult, } @@ -247,12 +317,6 @@ func (t *alertTester) parseAlertsTestingBody(r *http.Request) (*alertsTestingCon } } - // For safety, limit the number of returned points per timeseries. - // This is sufficient for 60s resolution for a week or 1h resolution for a year. - if end.Sub(start)/step > 11000 { - return nil, errors.New("failed to parse alert testing request: exceeded maximum resolution of 11,000 points") - } - configStringUnescaped, err := url.QueryUnescape(configString) if err != nil { return nil, errors.Wrap(err, "failed to parse alert testing request: could not unescape rule config") @@ -271,10 +335,10 @@ func (t *alertTester) parseAlertsTestingBody(r *http.Request) (*alertsTestingCon }, nil } -func (t *alertTester) evaluateAlertRule(ctx context.Context, queryable remote.Queryable, minTimestamp time.Time, maxTimestamp time.Time, step time.Duration, group rulefmt.RuleGroup, rule rulefmt.RuleNode) (string, *[]rules.Alert, *queryData, *queryDataWithExpr, error) { +func (t *alertTester) evaluateAlertRule(ctx context.Context, queryable remote.Queryable, minTimestamp time.Time, maxTimestamp time.Time, step time.Duration, group rulefmt.RuleGroup, rule rulefmt.RuleNode) (*alertDefinition, *[]rules.Alert, *queryData, *queryDataWithExpr, error) { expr, err := parser.ParseExpr(rule.Expr.Value) if err != nil { - return "", nil, nil, nil, errors.Wrap(err, "failed to parse the expression %q", rule.Expr) + return nil, nil, nil, nil, errors.Wrap(err, "failed to parse the expression %q", rule.Expr) } interval := time.Duration(group.Interval) if interval <= 0 { @@ -284,8 +348,8 @@ func (t *alertTester) evaluateAlertRule(ctx context.Context, queryable remote.Qu rule.Alert.Value, expr, time.Duration(rule.For), - labels.FromMap(rule.Labels), - labels.FromMap(rule.Annotations), + labels.Labels{}, + labels.Labels{}, labels.Labels{}, "", true, @@ -294,7 +358,7 @@ func (t *alertTester) evaluateAlertRule(ctx context.Context, queryable remote.Qu provider, err := queryable.QueryFuncProvider(minTimestamp, maxTimestamp, interval) if err != nil { - return "", nil, nil, nil, errors.Wrap(err, "failed to create queryable") + return nil, nil, nil, nil, errors.Wrap(err, "failed to create queryable") } maxSamples := int((maxTimestamp.UnixMilli() - minTimestamp.UnixMilli()) / step.Milliseconds()) @@ -306,12 +370,12 @@ func (t *alertTester) evaluateAlertRule(ctx context.Context, queryable remote.Qu maxTimestamp, interval) if err != nil { - return "", nil, nil, nil, errors.Wrap(err, "failed to query %s from %d to %d", rule.Expr.Value, minTimestamp, maxTimestamp) + return nil, nil, nil, nil, errors.Wrap(err, "failed to query %s from %d to %d", rule.Expr.Value, minTimestamp, maxTimestamp) } queryMatrix = common.DownsampleMatrix(queryMatrix, maxSamples, true) - activeAlertsByLabels := make(map[uint64][]*rules.Alert) + importantAlertTimestampSet := make(map[time.Time]interface{}) queryFunc := provider.InstantQueryFunc(false) seriesHashMap := make(map[uint64]*promql.Series) @@ -330,7 +394,7 @@ func (t *alertTester) evaluateAlertRule(ctx context.Context, queryable remote.Qu nil, group.Limit) if errA != nil { - return "", nil, nil, nil, errors.Wrap(errA, "failed to evaluate rule %s at %d", rule.Expr.Value, ts) + return nil, nil, nil, nil, errors.Wrap(errA, "failed to evaluate rule %s at %d", rule.Expr.Value, ts) } for _, smpl := range vec { series, ok := seriesHashMap[smpl.Metric.Hash()] @@ -340,6 +404,67 @@ func (t *alertTester) evaluateAlertRule(ctx context.Context, queryable remote.Qu } series.Points = append(series.Points, smpl.Point) } + alertingRule.ForEachActiveAlert(func(activeAlert *rules.Alert) { + if !activeAlert.ActiveAt.IsZero() { + importantAlertTimestampSet[activeAlert.ActiveAt] = nil + } + if !activeAlert.FiredAt.IsZero() { + importantAlertTimestampSet[activeAlert.FiredAt] = nil + } + if !activeAlert.ResolvedAt.IsZero() { + importantAlertTimestampSet[activeAlert.ResolvedAt] = nil + } + }) + } + + var matrix promql.Matrix + for _, series := range seriesHashMap { + if series.Metric.Get(labels.MetricName) == alertForStateMetricName { + continue + } + p := 0 + for p < len(matrix) { + if matrix[p].Metric.Hash() >= series.Metric.Hash() { + break + } + p++ + } + matrix = append(matrix[:p], append(promql.Matrix{*series}, matrix[p:]...)...) + } + + matrix = common.DownsampleMatrix(matrix, maxSamples, false) + + var importantAlertTimestamps []time.Time + for ts := range importantAlertTimestampSet { + importantAlertTimestamps = append(importantAlertTimestamps, ts) + } + sort.Slice(importantAlertTimestamps, func(i, j int) bool { + return importantAlertTimestamps[i].Before(importantAlertTimestamps[j]) + }) + + activeAlertsByLabels := make(map[uint64][]*rules.Alert) + alertQueryFunc := provider.InstantQueryFunc(true) + alertingRule = rules.NewAlertingRule( + rule.Alert.Value, + expr, + time.Duration(rule.For), + labels.FromMap(rule.Labels), + labels.FromMap(rule.Annotations), + labels.Labels{}, + "", + true, + kitLog.NewNopLogger(), + ) + for _, ts := range importantAlertTimestamps { + _, errA := alertingRule.Eval( + ctx, + ts, + alertQueryFunc, + nil, + group.Limit) + if errA != nil { + return nil, nil, nil, nil, errors.Wrap(errA, "failed to evaluate rule %s at %d", rule.Expr.Value, ts) + } alertingRule.ForEachActiveAlert(func(activeAlert *rules.Alert) { aaHash := t.activeAlertHash(activeAlert) if existingAlerts, exists := activeAlertsByLabels[aaHash]; !exists { @@ -377,68 +502,17 @@ func (t *alertTester) evaluateAlertRule(ctx context.Context, queryable remote.Qu }) } - var matrix promql.Matrix - for _, series := range seriesHashMap { - if series.Metric.Get(labels.MetricName) == alertForStateMetricName { - continue - } - p := 0 - for p < len(matrix) { - if matrix[p].Metric.Hash() >= series.Metric.Hash() { - break - } - p++ - } - matrix = append(matrix[:p], append(promql.Matrix{*series}, matrix[p:]...)...) - } - - matrix = common.DownsampleMatrix(matrix, maxSamples, false) - - htmlSnippet, err := t.htmlSnippetWithoutLinks(alertingRule) - if err != nil { - return "", nil, nil, nil, err - } - var activeAlertList []rules.Alert - alertQueryFunc := provider.InstantQueryFunc(true) for _, activeAlertsByLabel := range activeAlertsByLabels { for _, activeAlert := range activeAlertsByLabel { - var ts time.Time - if activeAlert.State == rules.StatePending { - ts = activeAlert.ActiveAt - } else { - ts = activeAlert.FiredAt - } - alertingRule = rules.NewAlertingRule( - rule.Alert.Value, - expr, - time.Duration(rule.For), - labels.FromMap(rule.Labels), - labels.FromMap(rule.Annotations), - labels.Labels{}, - "", - true, - kitLog.NewNopLogger(), - ) - _, errA := alertingRule.Eval( - ctx, - ts, - alertQueryFunc, - nil, - group.Limit) - if errA != nil { - return "", nil, nil, nil, errors.Wrap(errA, "failed to evaluate rule %s at %d", rule.Expr.Value, ts) - } - alertingRule.ForEachActiveAlert(func(alert *rules.Alert) { - if alert.ActiveAt == ts && activeAlert.Labels.Hash() == alert.Labels.Hash() { - (*activeAlert).Annotations = (*alert).Annotations - } - }) activeAlertList = append(activeAlertList, *activeAlert) } } + sort.Slice(activeAlertList, func(i, j int) bool { + return activeAlertList[i].ActiveAt.Before(activeAlertList[j].ActiveAt) + }) - return htmlSnippet, + return t.toAlertDefinition(group, alertingRule, minTimestamp, maxTimestamp), &activeAlertList, &queryData{ Result: matrix, @@ -459,26 +533,32 @@ func (t *alertTester) activeAlertHash(alert *rules.Alert) uint64 { return xxhash.Sum64(buf) } -func (t *alertTester) htmlSnippetWithoutLinks(r *rules.AlertingRule) (string, error) { - lbls := make(map[string]string, len(r.Labels())) - for _, l := range r.Labels() { - lbls[l.Name] = l.Value +func (t *alertTester) toAlertDefinition(group rulefmt.RuleGroup, rule *rules.AlertingRule, startTime time.Time, endTime time.Time) *alertDefinition { + lbls := make([]map[string]string, len(rule.Labels())) + for i, l := range rule.Labels() { + lbls[i] = map[string]string{"name": l.Name, "value": l.Value} } - annotations := make(map[string]string, len(r.Annotations())) - for _, l := range r.Annotations() { - annotations[l.Name] = l.Value + annotations := make([]map[string]string, len(rule.Annotations())) + for i, a := range rule.Annotations() { + annotations[i] = map[string]string{"name": a.Name, "value": a.Value} } - ar := rulefmt.Rule{ - Alert: r.Name(), - Expr: r.Query().String(), - For: model.Duration(r.HoldDuration()), - Labels: lbls, - Annotations: annotations, + return &alertDefinition{ + Group: group.Name, + Name: rule.Name(), + Expr: rule.Query().String(), + ExprTableUrl: t.graphLinkForExpression(rule.Query().String(), startTime, endTime), + For: model.Duration(rule.HoldDuration()).String(), + Labels: lbls, + Annotations: annotations, } +} - var tpl bytes.Buffer - if err := t.alertHtmlSnippetTemplate.Execute(&tpl, ar); err != nil { - return "", errors.Wrap(err, "failed to execute alert html snippet template") - } - return tpl.String(), nil +func (t *alertTester) graphLinkForExpression(expr string, startTime time.Time, endTime time.Time) string { + escapedExpression := url.QueryEscape(expr) + return fmt.Sprintf("%s/graph?g0.expr=%s&g0.tab=0&g0.range_input=%s&g0.end_input=%s&g0.moment_input=%s", + t.config.Host.String(), + escapedExpression, + model.Duration(endTime.Sub(startTime)).String(), + htmlTemplate.HTMLEscapeString(startTime.Format("2006-01-02 15:04:05")), + htmlTemplate.HTMLEscapeString(endTime.Format("2006-01-02 15:04:05"))) } diff --git a/lib/web/server.go b/lib/web/server.go index 4fa633f..17c62e2 100644 --- a/lib/web/server.go +++ b/lib/web/server.go @@ -65,16 +65,18 @@ type server struct { config config.WebConfig httpServer http.Server routes []Route + queryable remote.Queryable } func (s *server) createServer() error { - queryable, err := remote.NewQueryable(s.config.Host) + queryable, err := remote.NewQueryable(s.config.Host, s.config.Parallelism) if err != nil { return err } options := s.newOptions() tmplExecutor := NewTemplateExecutor(options) router := s.createRouter(tmplExecutor, queryable) + s.queryable = queryable s.httpServer = http.Server{ Addr: s.config.ListenAddress.String(), Handler: router, @@ -108,6 +110,7 @@ func (s *server) Stop() { cancel() s.state = stopped }() + s.queryable.Close() if err := s.httpServer.Shutdown(ctx); err != nil { log.Panicf("Server shutdown failed:%s", err) } diff --git a/lib/web/ui/static/assets/css/alerts.css b/lib/web/ui/static/assets/css/alerts.css index a3f8378..f08c26e 100644 --- a/lib/web/ui/static/assets/css/alerts.css +++ b/lib/web/ui/static/assets/css/alerts.css @@ -26,4 +26,3 @@ div.show-annotations button { div.show-annotations.is-checked { color: #286090; } - diff --git a/lib/web/ui/static/assets/css/alertsTest.css b/lib/web/ui/static/assets/css/alertsTest.css index 501393f..486bb39 100644 --- a/lib/web/ui/static/assets/css/alertsTest.css +++ b/lib/web/ui/static/assets/css/alertsTest.css @@ -48,7 +48,16 @@ div.show-hide-all button { } #ruleTextArea { + height: 350px; min-width: 100px; + flex: 1 1 auto; +} + +#ruleTestInfo { + height: 100%; + background: white; + overflow: auto; + flex: 0 5 28.8%; } #dev_end,#inc_end,#dec_range,#inc_range,#range_input,#evaluate { @@ -64,7 +73,7 @@ div.show-hide-all button { } .prometheus_input_group .input { - width: 100px; + width: 70px; height: 30px; padding: 6px 12px; font-size: 14px; @@ -81,7 +90,7 @@ div.show-hide-all button { } .prometheus_input_group .date_input { - width: 200px; + width: 150px; } .alert_annotations_list { @@ -100,10 +109,145 @@ div.show-hide-all button { border-style: none !important; } -.alert_when_list_key { +.alert_value { + display: flex; + flex-direction: row; + justify-content: right; + gap: 5px; +} + +.alert_when_list { + display: flex; + flex-direction: row; + justify-content: space-between; + gap: 5px; +} + +.alert_when_list_key, .alert_value_key, .alert_range_info_key { font-weight: bold; } -.alert_when_list_key, .alert_when_list_value { +.alert_when_list_key, .alert_when_list_value, .alert_value_key, .alert_value_value, .alert_range_info_key, .alert_range_info_value { font-size: 75%; + white-space: nowrap; +} + +.rickshaw_annotation_timeline .annotation.active .content { + width: min-content; + border-width: 1px !important; + border: #000; + border-style: solid; +} + +.alert_popup { + display: flex; + flex-direction: column; + min-width: 250px; +} + +.alert_popup_header { + flex: 0 1 auto; + display: flex; + flex-direction: row; + align-items: center; + justify-content: space-between; + margin-bottom: 5px; } + +.alert_popup_name, .alert_popup_status { + flex: 0 1 auto; + margin-right: 10px; +} + +.alert_popup_value { + flex: 1 1 auto; +} + +.alert_popup_body { + flex: 1 1 auto; + display: flex; + flex-direction: row; + flex-wrap: wrap; +} + +.alert_popup_label { + margin: 2px; +} + +.rickshaw_annotation_timeline .annotation:hover .content { + display: block; + z-index: 50; + width: min-content; + border-width: 1px !important; + border: #000; + border-style: solid; +} + +.rickshaw_annotation_timeline .annotation.active, .rickshaw_annotation_timeline .annotation:hover { + cursor: pointer; +} + +.alert_range_info { + flex: 1 1 auto; + display: flex; + flex-direction: row; + justify-content: end; + margin-right: 40px; +} + +.alert_range_info_element { + display: flex; + flex-direction: row; + flex: 0 1 auto; +} + +.alert_range_info_key { + flex: 0 1 auto; + margin-left: 20px; + margin-right: 5px; +} + +.alert_range_info_value { + flex: 1 1 auto; +} + +#result_control_wrapper { + display: flex; + flex-direction: row; + flex-wrap: wrap-reverse; + align-items: center; + white-space: nowrap; + row-gap: 10px; + width: 100%; +} + +.result_controls { + flex: 9999 1 auto; +} + +.alert_definition { + display: block; + padding: 9.5px; + margin: 0 0 10px; + font-size: 13px; + line-height: 1.42857143; + color: #333; + background-color: #f5f5f5; + border: 1px solid #ccc; + border-radius: 4px; + font-family: Menlo,Monaco,Consolas,"Courier New",monospace; + overflow-x: scroll; + white-space: nowrap; +} + +.alert_definition_subelement { + margin-left: 1.5em; +} + +.alert_definition_group { + width: fit-content; +} + +.table-fixed { + table-layout: fixed; +} \ No newline at end of file diff --git a/lib/web/ui/static/assets/css/graph.css b/lib/web/ui/static/assets/css/graph.css index f3c37ca..7ac1235 100644 --- a/lib/web/ui/static/assets/css/graph.css +++ b/lib/web/ui/static/assets/css/graph.css @@ -68,7 +68,7 @@ div.page-options { .legend { display: inline-block; vertical-align: top; - margin: 0 0 0 60px; + margin: 10px 0 0 60px; } .graph_area { @@ -160,3 +160,12 @@ input[name="end_input"], input[name="range_input"] { background-color: #222222; border-radius: 0; } + +.slider { + margin-top: 10px; +} + +.slider, .timeline { + margin-left: 60px; + margin-right: 40px; +} diff --git a/lib/web/ui/static/assets/js/alert_testing/graph_template.handlebar b/lib/web/ui/static/assets/js/alert_testing/graph_template.handlebar index 05ec807..1e2cfaa 100644 --- a/lib/web/ui/static/assets/js/alert_testing/graph_template.handlebar +++ b/lib/web/ui/static/assets/js/alert_testing/graph_template.handlebar @@ -1,115 +1,138 @@
- +
- + diff --git a/lib/web/ui/static/assets/js/alert_testing/index.js b/lib/web/ui/static/assets/js/alert_testing/index.js index 5f1b0f1..b3d7b3d 100644 --- a/lib/web/ui/static/assets/js/alert_testing/index.js +++ b/lib/web/ui/static/assets/js/alert_testing/index.js @@ -1,4 +1,5 @@ let graphTemplate; +let popupTemplate; let alertStateToRowClass; let alertStateToName; let endDate = null; @@ -29,9 +30,19 @@ function mustacheFormatMap(map) { return formatted } +function isTimestampZero(timestamp) { + if (timestamp === null) { + return true; + } + return moment.utc(new Date(timestamp)).unix() === 0; +} + function mustacheFormatDate(timestamp) { + if (timestamp === null) { + return ""; + } const date = moment.utc(new Date(timestamp)); - if (date.valueOf() === -62135596800000) { + if (date.unix() === 0) { return ""; } return date.format('YYYY-MM-DD HH:mm:ss[Z]'); @@ -104,7 +115,7 @@ Control.timeFactors = { }; Control.stepValues = [ - "1s", "10s", "1m", "5m", "15m", "30m", "1h", "2h", "6h", "12h", "1d" + "1s", "10s", "1m", "5m", "15m", "30m", "1h", "2h", "6h", "12h", "1d", "2d", "1w", "2w", "4w", "8w", "1y", "2y" ]; Control.prototype.initialize = function() { @@ -147,6 +158,11 @@ Control.prototype.initialize = function() { controlWrapper.find("button[name=inc_end]").click(function() { self.increaseEnd(); }); controlWrapper.find("button[name=dec_end]").click(function() { self.decreaseEnd(); }); + self.alertRangeInfo = $(".alert_range_info").hide(); + self.alertRangeInfoStart = self.alertRangeInfo.find("#alert_range_info_start"); + self.alertRangeInfoEnd = self.alertRangeInfo.find("#alert_range_info_end"); + self.alertRangeInfoStep = self.alertRangeInfo.find("#alert_range_info_step"); + self.evaluateBtn = controlWrapper.find(".evaluate"); self.evaluateBtn.click(function() { self.evaluate(); @@ -155,10 +171,11 @@ Control.prototype.initialize = function() { Control.prototype.evaluate = function() { const self = this; + self.alertRangeInfo.hide(); const endTime = self.getOrSetEndDate().valueOf() / 1000; // TODO: shouldn't valueof only work when it's a moment? const rangeSeconds = self.parseDuration(self.rangeInput.val()) * 1000; const startTime = endTime - rangeSeconds / 1000; - const resolution = Math.max(Math.floor(rangeSeconds / 250000), 1); + const resolution = self.parseDuration("15s"); const text = ace.edit("ruleTextArea").getValue(); const data = { config: encodeURIComponent(text), @@ -166,21 +183,95 @@ Control.prototype.evaluate = function() { end: endTime, step: resolution, }; - evaluate(data); + self.doEvaluate(data); +} + +Control.prototype.doEvaluate = function(data) { + const self = this; + const time = data.end * 1000; + if (time === 0) { + $("#ruleTestInfo").html("Testing for current time"); + $(".evaluation_message").html("Testing for current time"); + } else { + $("#ruleTestInfo").html("Testing for: " + mustacheFormatDate(time)); + $(".evaluation_message").html("Testing for: " + mustacheFormatDate(time)); + } + $.ajax({ + method: 'POST', + url: PATH_PREFIX + "/alerts_testing", + dataType: "json", + contentType: "application/x-www-form-urlencoded", + data: $.param(data), + success: function(json) { + if (json.isError) { + let errStr = "Error message:
" + const len = json.errors.length + for(let i = 0; i < len; i++) { + errStr += "(" + (i+1) + ") " + json.errors[i] + '
' + } + $("#ruleTestInfo").html(redHtml(errStr)); + } else { + if (time === 0) { + endDate = null; + } else { + endDate = new Date(time); + } + $("#ruleTestInfo").html(greenHtml("Evaluated")); + $(".evaluation_message").html(""); + alertStateToRowClass = json.alertStateToRowClass; + alertStateToName = json.alertStateToName; + } + self.replaceRules(json); + }, + error: function(jqXHR, textStatus, errorThrown) { + let errorMessage = errorThrown; + if ((errorMessage ?? "") === "") { + errorMessage = "Cannot connect to Promutil API"; + } + $("#ruleTestInfo").html(redHtml("ERROR: "+errorMessage)); + } + }); } +Control.prototype.replaceRules = function(json) { + const self = this; + const graphContainer = $("#graph_container"); + graphContainer.empty(); + Graph.numGraphs = 0; + + self.alertRangeInfoStart.text(mustacheFormatDate(json.start*1000)); + self.alertRangeInfoEnd.text(mustacheFormatDate(json.end*1000)); + self.alertRangeInfoStep.text(moment.duration(json.step).humanize()); + self.alertRangeInfo.show(); + + for(let i in json.ruleResults) { + const graph = new Graph( + graphContainer, + { + start: json.start, + end: json.end, + step: json.step, + data: json.ruleResults[i] + } + ); + $(window).resize(function() { + graph.resizeGraph(); + }); + } + + $('[data-toggle="popover"]').popover(); +}; + Control.prototype.increaseRange = function() { const self = this; const rangeSeconds = self.parseDuration(self.rangeInput.val()); - if (rangeSeconds < Control.timeFactors["d"]) { - for (let i = 0; i < Control.stepValues.length; i++) { - if (rangeSeconds < self.parseDuration(Control.stepValues[i])) { - self.rangeInput.val(Control.stepValues[i]); - break; - } + for (let i = 0; i < Control.stepValues.length; i++) { + if (rangeSeconds < self.parseDuration(Control.stepValues[i])) { + self.rangeInput.val(Control.stepValues[i]); + break; } - self.evaluate(); } + self.evaluate(); }; Control.prototype.decreaseRange = function() { @@ -203,12 +294,7 @@ Control.prototype.parseDuration = function(rangeText) { } const value = parseInt(matches[1]); const unit = matches[2]; - - const duration = value * Control.timeFactors[unit]; - if (duration > Control.timeFactors["d"]) { - return Control.timeFactors["d"]; - } - return duration; + return value * Control.timeFactors[unit]; }; Control.prototype.increaseEnd = function() { @@ -282,25 +368,44 @@ Graph.prototype.initialize = function() { 'buildVersion': BUILD_VERSION, 'ruleName': self.json.data.name, 'activeAlerts': self.json.data.alerts, - 'htmlSnippet': self.json.data.htmlSnippet, + 'definition': self.json.data.definition, }; if(self.json.data.alerts) { options.activeAlertsLength = self.json.data.alerts.length; } else { options.activeAlertsLength = 0 } + let maxState = 0; + self.activeAlerts = []; for(let i in options.activeAlerts) { + const activeAt = options.activeAlerts[i].ActiveAt; + const firedAt = options.activeAlerts[i].FiredAt; + const resolvedAt = options.activeAlerts[i].ResolvedAt; + options.activeAlerts[i].id = `activeAlert${self.id}.${i}`; + options.activeAlerts[i].name = `Alert ${i}`; options.activeAlerts[i].Labels = mustacheFormatMap(options.activeAlerts[i].Labels); options.activeAlerts[i].Annotations = mustacheFormatMap(options.activeAlerts[i].Annotations); options.activeAlerts[i].stateName = alertStateToName[options.activeAlerts[i].State]; options.activeAlerts[i].stateClass = alertStateToRowClass[options.activeAlerts[i].State]; - options.activeAlerts[i].ActiveAt = mustacheFormatDate(options.activeAlerts[i].ActiveAt); - options.activeAlerts[i].FiredAt = mustacheFormatDate(options.activeAlerts[i].FiredAt); - options.activeAlerts[i].ResolvedAt = mustacheFormatDate(options.activeAlerts[i].ResolvedAt); + options.activeAlerts[i].ActiveAt = mustacheFormatDate(activeAt*1000); + options.activeAlerts[i].FiredAt = mustacheFormatDate(firedAt*1000); + options.activeAlerts[i].ResolvedAt = mustacheFormatDate(resolvedAt*1000); + if (options.activeAlerts[i].State === 2 && options.activeAlerts[i].ResolvedAt === "") { + options.activeAlerts[i].ResolvedAt = "Never"; + } if (options.activeAlerts[i].State > maxState) { maxState = options.activeAlerts[i].State; } + + const activeAlert = {start: activeAt, value: Mustache.render(popupTemplate, options.activeAlerts[i])}; + if (!isTimestampZero(resolvedAt)) { + activeAlert.end = resolvedAt; + } else if (!isTimestampZero(firedAt)) { + activeAlert.end = self.json.end; + } + self.activeAlerts.push(activeAlert); + } options.maxState = alertStateToRowClass[maxState] @@ -317,7 +422,9 @@ Graph.prototype.initialize = function() { self.stackedBtn = self.queryForm.find(".stacked_btn"); self.stacked = self.queryForm.find("input[name=stacked]"); - self.error = graphWrapper.find(".error").hide(); + self.errorWrapper = self.el.find("#error_wrapper" + self.id).hide(); + self.error = self.errorWrapper.find(".error"); + self.resultWrapper = self.el.find("#result_wrapper" + self.id).hide(); self.spinner = graphWrapper.find(".spinner"); self.evalStats = graphWrapper.find(".eval_stats"); @@ -326,12 +433,16 @@ Graph.prototype.initialize = function() { self.graphRef.graph = self.graphRef.graphArea.find(".graph"); self.graphRef.yAxis = self.graphRef.graphArea.find(".y_axis"); self.graphRef.legend = graphWrapper.find(".legend"); + self.graphRef.slider = graphWrapper.find(".slider"); + self.graphRef.timeline = graphWrapper.find(".timeline"); const alertGraphWrapper = self.el.find("#alert_graph_wrapper" + self.id); self.alertGraphRef.graphArea = alertGraphWrapper.find(".graph_area"); self.alertGraphRef.graph = self.alertGraphRef.graphArea.find(".graph"); self.alertGraphRef.yAxis = self.alertGraphRef.graphArea.find(".y_axis"); self.alertGraphRef.legend = alertGraphWrapper.find(".legend"); + self.alertGraphRef.slider = alertGraphWrapper.find(".slider"); + self.alertGraphRef.timeline = alertGraphWrapper.find(".timeline"); self.isStacked = function() { return self.stacked.val() === '1'; @@ -385,13 +496,15 @@ Graph.prototype.initGraphUpdate = function() { Graph.prototype.showError = function(msg) { const self = this; self.error.text(msg); - self.error.show(); + self.errorWrapper.show(); + self.resultWrapper.hide(); }; Graph.prototype.clearError = function() { const self = this; self.error.text(''); - self.error.hide(); + self.errorWrapper.hide(); + self.resultWrapper.show(); }; Graph.prototype.renderLabels = function(labels) { @@ -565,7 +678,9 @@ Graph.prototype.updateGraph = function(graphRef) { const yAxis = new Rickshaw.Graph.Axis.Y({ graph: graphRef.rickshawGraph, orientation: "left", - tickFormat: this.formatKMBT, + tickFormat: function(y) { + return self.formatKMBT(y); + }, element: graphRef.yAxis[0], }); @@ -583,8 +698,8 @@ Graph.prototype.updateGraph = function(graphRef) { }); const legend = new Rickshaw.Graph.Legend({ - element: graphRef.legend[0], graph: graphRef.rickshawGraph, + element: graphRef.legend[0] }); const highlighter = new Rickshaw.Graph.Behavior.Series.Highlight( { @@ -596,6 +711,42 @@ Graph.prototype.updateGraph = function(graphRef) { graph: graphRef.rickshawGraph, legend: legend }); + + const slider = new Rickshaw.Graph.RangeSlider({ + graph: graphRef.rickshawGraph, + element: graphRef.slider[0] + }); + + const annotator = new Rickshaw.Graph.Annotate({ + graph: graphRef.rickshawGraph, + element: graphRef.timeline[0] + }); + if (self.activeAlerts.length > 0) { + self.activeAlerts.forEach(function (activeAlert) { + annotator.add(activeAlert.start, activeAlert.value, activeAlert.end ?? null); + }) + } + annotator.update(); + + Rickshaw.keys(annotator.data).forEach(function(time) { + const annotation = annotator.data[time]; + annotation.element.addEventListener("click", function(e) { + if (annotation !== annotator.active) { + if (annotator.active) { + annotator.active.element.classList.toggle("active"); + annotator.active.line.classList.toggle("active"); + annotator.active.boxes.forEach(function(box) { + if (box.rangeElement) { + box.rangeElement.classList.toggle("active"); + } + }); + } + annotator.active = annotation; + } else { + annotator.active = null; + } + }, false); + }); } Graph.prototype.resizeGraph = function() { @@ -627,46 +778,106 @@ Graph.prototype.handleGraphResponse = function(graphRef, json) { self.updateGraph(graphRef); }; +Graph.prototype.toFixedUnit = function(value, decimals, unit) { + const self = this; + const fixedValue = self.toFixed(value, decimals); + if (fixedValue === '') { + return ''; + } + return fixedValue + unit; +} + +Graph.prototype.toFixed = function(value, decimals) { + const self = this; + if (value === null) { + return ''; + } + + if (value === Number.NEGATIVE_INFINITY || value === Number.POSITIVE_INFINITY) { + return value.toLocaleString(); + } + + if (decimals === null || decimals === undefined) { + decimals = self.getDecimalsForValue(value); + } + + const factor = decimals ? Math.pow(10, Math.max(0, decimals)) : 1; + const formatted = String(Math.round(value * factor) / factor); + + // if exponent return directly + if (formatted.indexOf('e') !== -1 || value === 0) { + return formatted; + } + + const decimalPos = formatted.indexOf('.'); + const precision = decimalPos === -1 ? 0 : formatted.length - decimalPos - 1; + if (precision < decimals) { + return (precision ? formatted : formatted + '.') + String(factor).slice(1, decimals - precision + 1); + } + + return formatted; +} + +Graph.prototype.getDecimalsForValue = function(value) { + const log10 = Math.floor(Math.log(Math.abs(value)) / Math.LN10); + let dec = -log10 + 1; + const magn = Math.pow(10, -dec); + const norm = value / magn; // norm is between 1.0 and 10.0 + + // special case for 2.5, requires an extra decimal + if (norm > 2.25) { + ++dec; + } + + if (value % 1 === 0) { + dec = 0; + } + + return Math.max(0, dec); +} + Graph.prototype.formatKMBT = function(y) { + const self = this; + const decimals = 5; var abs_y = Math.abs(y); if (abs_y >= 1e24) { - return (y / 1e24).toString() + "Y"; + return self.toFixedUnit(y / 1e24, decimals, "Y"); } else if (abs_y >= 1e21) { - return (y / 1e21).toString() + "Z"; + return self.toFixedUnit(y / 1e21, decimals, "Z"); } else if (abs_y >= 1e18) { - return (y / 1e18).toString() + "E"; + return self.toFixedUnit(y / 1e18, decimals, "E"); } else if (abs_y >= 1e15) { - return (y / 1e15).toString() + "P"; + return self.toFixedUnit(y / 1e15, decimals, "P"); } else if (abs_y >= 1e12) { - return (y / 1e12).toString() + "T"; + return self.toFixedUnit(y / 1e12, decimals, "T"); } else if (abs_y >= 1e9) { - return (y / 1e9).toString() + "G"; + return self.toFixedUnit(y / 1e9, decimals, "G"); } else if (abs_y >= 1e6) { - return (y / 1e6).toString() + "M"; + return self.toFixedUnit(y / 1e6, decimals, "M"); } else if (abs_y >= 1e3) { - return (y / 1e3).toString() + "k"; + return self.toFixedUnit(y / 1e3, decimals, "k"); } else if (abs_y >= 1) { - return y + return self.toFixed(y,decimals); } else if (abs_y === 0) { - return y + return self.toFixed(y, decimals); } else if (abs_y <= 1e-24) { - return (y / 1e-24).toString() + "y"; + return self.toFixedUnit(y / 1e-24, decimals, "y"); } else if (abs_y <= 1e-21) { - return (y / 1e-21).toString() + "z"; + return self.toFixedUnit(y / 1e-21, decimals, "z"); } else if (abs_y <= 1e-18) { - return (y / 1e-18).toString() + "a"; + return self.toFixedUnit(y / 1e-18, decimals, "a"); } else if (abs_y <= 1e-15) { - return (y / 1e-15).toString() + "f"; + return self.toFixedUnit(y / 1e-15, decimals, "f"); } else if (abs_y <= 1e-12) { - return (y / 1e-12).toString() + "p"; + return self.toFixedUnit(y / 1e-12, decimals, "p"); } else if (abs_y <= 1e-9) { - return (y / 1e-9).toString() + "n"; + return self.toFixedUnit(y / 1e-9, decimals, "n"); } else if (abs_y <= 1e-6) { - return (y / 1e-6).toString() + "µ"; + return self.toFixedUnit(y / 1e-6, decimals, "µ"); } else if (abs_y <=1e-3) { - return (y / 1e-3).toString() + "m"; + return self.toFixedUnit(y / 1e-3, decimals, "m"); } else if (abs_y <= 1) { - return y + return self.toFixed(y, decimals); } } @@ -678,82 +889,33 @@ function redHtml(text) { return '
' + text + '
'; } -var replaceRules = function(json) { - const graphContainer = $("#graph_container"); - graphContainer.empty(); - Graph.numGraphs = 0; - - for(let i in json.ruleResults) { - const graph = new Graph( - graphContainer, - { - start: json.start, - end: json.end, - step: json.step, - data: json.ruleResults[i] - } - ); - $(window).resize(function() { - graph.resizeGraph(); - }); - } - - $('[data-toggle="popover"]').popover(); -}; - -function evaluate(data) { - const time = data.end * 1000; - if (time === 0) { - $("#ruleTestInfo").html("Testing for current time"); - $(".evaluation_message").html("Testing for current time"); - } else { - $("#ruleTestInfo").html("Testing for: " + mustacheFormatDate(time)); - $(".evaluation_message").html("Testing for: " + mustacheFormatDate(time)); - } - $.ajax({ - method: 'POST', - url: PATH_PREFIX + "/alerts_testing", - dataType: "json", - contentType: "application/x-www-form-urlencoded", - data: $.param(data), - success: function(json) { - if (json.isError) { - let errStr = "Error message:
" - const len = json.errors.length - for(let i = 0; i < len; i++) { - errStr += "(" + (i+1) + ") " + json.errors[i] + '
' - } - $("#ruleTestInfo").html(redHtml(errStr)); - } else { - if (time === 0) { - endDate = null; - } else { - endDate = new Date(time); - } - $("#ruleTestInfo").html(greenHtml("Evaluated")); - $(".evaluation_message").html(""); - alertStateToRowClass = json.alertStateToRowClass; - alertStateToName = json.alertStateToName; - } - replaceRules(json); - }, - error: function(jqXHR, textStatus, errorThrown) { - $("#ruleTestInfo").html(redHtml("ERROR: "+errorThrown)); - } - }); -} - function initEditor() { $("#ruleTextArea").html("# Enter your entire alert rule file here"); + ace.require("ace/ext/language_tools"); + ace.config.setModuleUrl('ace/mode/yaml_worker', 'https://cdnjs.cloudflare.com/ajax/libs/ace/1.8.1/worker-yaml.min.js') const e = ace.edit("ruleTextArea"); + e.session.setMode("ace/mode/yaml"); + e.session.setUseWrapMode(true); e.setTheme("ace/theme/xcode"); - e.getSession().setMode("ace/mode/yaml"); e.setFontSize("10pt"); - e.setOption("wrap", true); + e.setOptions({ + useWorker: true, + enableAutoIndent: true, + enableLiveAutocompletion: true + }); e.focus(); } function init() { + moment.relativeTimeThreshold('ss', 60); + moment.updateLocale('en', { + relativeTime : { + s: function (number, withoutSuffix, key, isFuture){ + return number + ' seconds'; + } + } + }); + $.ajaxSetup({ cache: false }); @@ -766,17 +928,25 @@ function init() { $(".alert_details").hide(); }); + $.ajax({ - url: PATH_PREFIX + "/static/js/alert_testing/graph_template.handlebar?v=" + BUILD_VERSION, + url: PATH_PREFIX + "/static/js/alert_testing/popup_template.handlebar?v=" + BUILD_VERSION, success: function(data) { - graphTemplate = data; + popupTemplate = data; Mustache.parse(data); - const control = new Control( - { - end_input: endDate, + $.ajax({ + url: PATH_PREFIX + "/static/js/alert_testing/graph_template.handlebar?v=" + BUILD_VERSION, + success: function(data) { + graphTemplate = data; + Mustache.parse(data); + const control = new Control( + { + end_input: endDate, + } + ); + initEditor(); } - ); - initEditor(); + }); } }); } diff --git a/lib/web/ui/static/assets/js/alert_testing/popup_template.handlebar b/lib/web/ui/static/assets/js/alert_testing/popup_template.handlebar new file mode 100644 index 0000000..c737629 --- /dev/null +++ b/lib/web/ui/static/assets/js/alert_testing/popup_template.handlebar @@ -0,0 +1,16 @@ +
+
+
+ {{name}} +
+
+ {{stateName}} +
+
{{Value}}
+
+
+ {{#Labels}} + {{key}}="{{value}}" + {{/Labels}} +
+
\ No newline at end of file diff --git a/lib/web/ui/static/assets/vendor/js/jquery.ui.min.css b/lib/web/ui/static/assets/vendor/js/jquery.ui.min.css new file mode 100644 index 0000000..cf977e2 --- /dev/null +++ b/lib/web/ui/static/assets/vendor/js/jquery.ui.min.css @@ -0,0 +1,7 @@ +/*! jQuery UI - v1.13.2 - 2022-07-14 +* http://jqueryui.com +* Includes: core.css, accordion.css, autocomplete.css, menu.css, button.css, controlgroup.css, checkboxradio.css, datepicker.css, dialog.css, draggable.css, resizable.css, progressbar.css, selectable.css, selectmenu.css, slider.css, sortable.css, spinner.css, tabs.css, tooltip.css, theme.css +* To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Arial%2CHelvetica%2Csans-serif&fsDefault=1em&fwDefault=normal&cornerRadius=3px&bgColorHeader=e9e9e9&bgTextureHeader=flat&borderColorHeader=dddddd&fcHeader=333333&iconColorHeader=444444&bgColorContent=ffffff&bgTextureContent=flat&borderColorContent=dddddd&fcContent=333333&iconColorContent=444444&bgColorDefault=f6f6f6&bgTextureDefault=flat&borderColorDefault=c5c5c5&fcDefault=454545&iconColorDefault=777777&bgColorHover=ededed&bgTextureHover=flat&borderColorHover=cccccc&fcHover=2b2b2b&iconColorHover=555555&bgColorActive=007fff&bgTextureActive=flat&borderColorActive=003eff&fcActive=ffffff&iconColorActive=ffffff&bgColorHighlight=fffa90&bgTextureHighlight=flat&borderColorHighlight=dad55e&fcHighlight=777620&iconColorHighlight=777620&bgColorError=fddfdf&bgTextureError=flat&borderColorError=f1a899&fcError=5f3f3f&iconColorError=cc0000&bgColorOverlay=aaaaaa&bgTextureOverlay=flat&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=666666&bgTextureShadow=flat&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=5px&offsetTopShadow=0px&offsetLeftShadow=0px&cornerRadiusShadow=8px +* Copyright jQuery Foundation and other contributors; Licensed MIT */ + +.ui-helper-hidden{display:none}.ui-helper-hidden-accessible{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.ui-helper-reset{margin:0;padding:0;border:0;outline:0;line-height:1.3;text-decoration:none;font-size:100%;list-style:none}.ui-helper-clearfix:before,.ui-helper-clearfix:after{content:"";display:table;border-collapse:collapse}.ui-helper-clearfix:after{clear:both}.ui-helper-zfix{width:100%;height:100%;top:0;left:0;position:absolute;opacity:0;-ms-filter:"alpha(opacity=0)"}.ui-front{z-index:100}.ui-state-disabled{cursor:default!important;pointer-events:none}.ui-icon{display:inline-block;vertical-align:middle;margin-top:-.25em;position:relative;text-indent:-99999px;overflow:hidden;background-repeat:no-repeat}.ui-widget-icon-block{left:50%;margin-left:-8px;display:block}.ui-widget-overlay{position:fixed;top:0;left:0;width:100%;height:100%}.ui-accordion .ui-accordion-header{display:block;cursor:pointer;position:relative;margin:2px 0 0 0;padding:.5em .5em .5em .7em;font-size:100%}.ui-accordion .ui-accordion-content{padding:1em 2.2em;border-top:0;overflow:auto}.ui-autocomplete{position:absolute;top:0;left:0;cursor:default}.ui-menu{list-style:none;padding:0;margin:0;display:block;outline:0}.ui-menu .ui-menu{position:absolute}.ui-menu .ui-menu-item{margin:0;cursor:pointer;list-style-image:url("data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7")}.ui-menu .ui-menu-item-wrapper{position:relative;padding:3px 1em 3px .4em}.ui-menu .ui-menu-divider{margin:5px 0;height:0;font-size:0;line-height:0;border-width:1px 0 0 0}.ui-menu .ui-state-focus,.ui-menu .ui-state-active{margin:-1px}.ui-menu-icons{position:relative}.ui-menu-icons .ui-menu-item-wrapper{padding-left:2em}.ui-menu .ui-icon{position:absolute;top:0;bottom:0;left:.2em;margin:auto 0}.ui-menu .ui-menu-icon{left:auto;right:0}.ui-button{padding:.4em 1em;display:inline-block;position:relative;line-height:normal;margin-right:.1em;cursor:pointer;vertical-align:middle;text-align:center;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;overflow:visible}.ui-button,.ui-button:link,.ui-button:visited,.ui-button:hover,.ui-button:active{text-decoration:none}.ui-button-icon-only{width:2em;box-sizing:border-box;text-indent:-9999px;white-space:nowrap}input.ui-button.ui-button-icon-only{text-indent:0}.ui-button-icon-only .ui-icon{position:absolute;top:50%;left:50%;margin-top:-8px;margin-left:-8px}.ui-button.ui-icon-notext .ui-icon{padding:0;width:2.1em;height:2.1em;text-indent:-9999px;white-space:nowrap}input.ui-button.ui-icon-notext .ui-icon{width:auto;height:auto;text-indent:0;white-space:normal;padding:.4em 1em}input.ui-button::-moz-focus-inner,button.ui-button::-moz-focus-inner{border:0;padding:0}.ui-controlgroup{vertical-align:middle;display:inline-block}.ui-controlgroup > .ui-controlgroup-item{float:left;margin-left:0;margin-right:0}.ui-controlgroup > .ui-controlgroup-item:focus,.ui-controlgroup > .ui-controlgroup-item.ui-visual-focus{z-index:9999}.ui-controlgroup-vertical > .ui-controlgroup-item{display:block;float:none;width:100%;margin-top:0;margin-bottom:0;text-align:left}.ui-controlgroup-vertical .ui-controlgroup-item{box-sizing:border-box}.ui-controlgroup .ui-controlgroup-label{padding:.4em 1em}.ui-controlgroup .ui-controlgroup-label span{font-size:80%}.ui-controlgroup-horizontal .ui-controlgroup-label + .ui-controlgroup-item{border-left:none}.ui-controlgroup-vertical .ui-controlgroup-label + .ui-controlgroup-item{border-top:none}.ui-controlgroup-horizontal .ui-controlgroup-label.ui-widget-content{border-right:none}.ui-controlgroup-vertical .ui-controlgroup-label.ui-widget-content{border-bottom:none}.ui-controlgroup-vertical .ui-spinner-input{width:75%;width:calc( 100% - 2.4em )}.ui-controlgroup-vertical .ui-spinner .ui-spinner-up{border-top-style:solid}.ui-checkboxradio-label .ui-icon-background{box-shadow:inset 1px 1px 1px #ccc;border-radius:.12em;border:none}.ui-checkboxradio-radio-label .ui-icon-background{width:16px;height:16px;border-radius:1em;overflow:visible;border:none}.ui-checkboxradio-radio-label.ui-checkboxradio-checked .ui-icon,.ui-checkboxradio-radio-label.ui-checkboxradio-checked:hover .ui-icon{background-image:none;width:8px;height:8px;border-width:4px;border-style:solid}.ui-checkboxradio-disabled{pointer-events:none}.ui-datepicker{width:17em;padding:.2em .2em 0;display:none}.ui-datepicker .ui-datepicker-header{position:relative;padding:.2em 0}.ui-datepicker .ui-datepicker-prev,.ui-datepicker .ui-datepicker-next{position:absolute;top:2px;width:1.8em;height:1.8em}.ui-datepicker .ui-datepicker-prev-hover,.ui-datepicker .ui-datepicker-next-hover{top:1px}.ui-datepicker .ui-datepicker-prev{left:2px}.ui-datepicker .ui-datepicker-next{right:2px}.ui-datepicker .ui-datepicker-prev-hover{left:1px}.ui-datepicker .ui-datepicker-next-hover{right:1px}.ui-datepicker .ui-datepicker-prev span,.ui-datepicker .ui-datepicker-next span{display:block;position:absolute;left:50%;margin-left:-8px;top:50%;margin-top:-8px}.ui-datepicker .ui-datepicker-title{margin:0 2.3em;line-height:1.8em;text-align:center}.ui-datepicker .ui-datepicker-title select{font-size:1em;margin:1px 0}.ui-datepicker select.ui-datepicker-month,.ui-datepicker select.ui-datepicker-year{width:45%}.ui-datepicker table{width:100%;font-size:.9em;border-collapse:collapse;margin:0 0 .4em}.ui-datepicker th{padding:.7em .3em;text-align:center;font-weight:bold;border:0}.ui-datepicker td{border:0;padding:1px}.ui-datepicker td span,.ui-datepicker td a{display:block;padding:.2em;text-align:right;text-decoration:none}.ui-datepicker .ui-datepicker-buttonpane{background-image:none;margin:.7em 0 0 0;padding:0 .2em;border-left:0;border-right:0;border-bottom:0}.ui-datepicker .ui-datepicker-buttonpane button{float:right;margin:.5em .2em .4em;cursor:pointer;padding:.2em .6em .3em .6em;width:auto;overflow:visible}.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current{float:left}.ui-datepicker.ui-datepicker-multi{width:auto}.ui-datepicker-multi .ui-datepicker-group{float:left}.ui-datepicker-multi .ui-datepicker-group table{width:95%;margin:0 auto .4em}.ui-datepicker-multi-2 .ui-datepicker-group{width:50%}.ui-datepicker-multi-3 .ui-datepicker-group{width:33.3%}.ui-datepicker-multi-4 .ui-datepicker-group{width:25%}.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header,.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header{border-left-width:0}.ui-datepicker-multi .ui-datepicker-buttonpane{clear:left}.ui-datepicker-row-break{clear:both;width:100%;font-size:0}.ui-datepicker-rtl{direction:rtl}.ui-datepicker-rtl .ui-datepicker-prev{right:2px;left:auto}.ui-datepicker-rtl .ui-datepicker-next{left:2px;right:auto}.ui-datepicker-rtl .ui-datepicker-prev:hover{right:1px;left:auto}.ui-datepicker-rtl .ui-datepicker-next:hover{left:1px;right:auto}.ui-datepicker-rtl .ui-datepicker-buttonpane{clear:right}.ui-datepicker-rtl .ui-datepicker-buttonpane button{float:left}.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current,.ui-datepicker-rtl .ui-datepicker-group{float:right}.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header,.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header{border-right-width:0;border-left-width:1px}.ui-datepicker .ui-icon{display:block;text-indent:-99999px;overflow:hidden;background-repeat:no-repeat;left:.5em;top:.3em}.ui-dialog{position:absolute;top:0;left:0;padding:.2em;outline:0}.ui-dialog .ui-dialog-titlebar{padding:.4em 1em;position:relative}.ui-dialog .ui-dialog-title{float:left;margin:.1em 0;white-space:nowrap;width:90%;overflow:hidden;text-overflow:ellipsis}.ui-dialog .ui-dialog-titlebar-close{position:absolute;right:.3em;top:50%;width:20px;margin:-10px 0 0 0;padding:1px;height:20px}.ui-dialog .ui-dialog-content{position:relative;border:0;padding:.5em 1em;background:none;overflow:auto}.ui-dialog .ui-dialog-buttonpane{text-align:left;border-width:1px 0 0 0;background-image:none;margin-top:.5em;padding:.3em 1em .5em .4em}.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset{float:right}.ui-dialog .ui-dialog-buttonpane button{margin:.5em .4em .5em 0;cursor:pointer}.ui-dialog .ui-resizable-n{height:2px;top:0}.ui-dialog .ui-resizable-e{width:2px;right:0}.ui-dialog .ui-resizable-s{height:2px;bottom:0}.ui-dialog .ui-resizable-w{width:2px;left:0}.ui-dialog .ui-resizable-se,.ui-dialog .ui-resizable-sw,.ui-dialog .ui-resizable-ne,.ui-dialog .ui-resizable-nw{width:7px;height:7px}.ui-dialog .ui-resizable-se{right:0;bottom:0}.ui-dialog .ui-resizable-sw{left:0;bottom:0}.ui-dialog .ui-resizable-ne{right:0;top:0}.ui-dialog .ui-resizable-nw{left:0;top:0}.ui-draggable .ui-dialog-titlebar{cursor:move}.ui-draggable-handle{-ms-touch-action:none;touch-action:none}.ui-resizable{position:relative}.ui-resizable-handle{position:absolute;font-size:0.1px;display:block;-ms-touch-action:none;touch-action:none}.ui-resizable-disabled .ui-resizable-handle,.ui-resizable-autohide .ui-resizable-handle{display:none}.ui-resizable-n{cursor:n-resize;height:7px;width:100%;top:-5px;left:0}.ui-resizable-s{cursor:s-resize;height:7px;width:100%;bottom:-5px;left:0}.ui-resizable-e{cursor:e-resize;width:7px;right:-5px;top:0;height:100%}.ui-resizable-w{cursor:w-resize;width:7px;left:-5px;top:0;height:100%}.ui-resizable-se{cursor:se-resize;width:12px;height:12px;right:1px;bottom:1px}.ui-resizable-sw{cursor:sw-resize;width:9px;height:9px;left:-5px;bottom:-5px}.ui-resizable-nw{cursor:nw-resize;width:9px;height:9px;left:-5px;top:-5px}.ui-resizable-ne{cursor:ne-resize;width:9px;height:9px;right:-5px;top:-5px}.ui-progressbar{height:2em;text-align:left;overflow:hidden}.ui-progressbar .ui-progressbar-value{margin:-1px;height:100%}.ui-progressbar .ui-progressbar-overlay{background:url("data:image/gif;base64,R0lGODlhKAAoAIABAAAAAP///yH/C05FVFNDQVBFMi4wAwEAAAAh+QQJAQABACwAAAAAKAAoAAACkYwNqXrdC52DS06a7MFZI+4FHBCKoDeWKXqymPqGqxvJrXZbMx7Ttc+w9XgU2FB3lOyQRWET2IFGiU9m1frDVpxZZc6bfHwv4c1YXP6k1Vdy292Fb6UkuvFtXpvWSzA+HycXJHUXiGYIiMg2R6W459gnWGfHNdjIqDWVqemH2ekpObkpOlppWUqZiqr6edqqWQAAIfkECQEAAQAsAAAAACgAKAAAApSMgZnGfaqcg1E2uuzDmmHUBR8Qil95hiPKqWn3aqtLsS18y7G1SzNeowWBENtQd+T1JktP05nzPTdJZlR6vUxNWWjV+vUWhWNkWFwxl9VpZRedYcflIOLafaa28XdsH/ynlcc1uPVDZxQIR0K25+cICCmoqCe5mGhZOfeYSUh5yJcJyrkZWWpaR8doJ2o4NYq62lAAACH5BAkBAAEALAAAAAAoACgAAAKVDI4Yy22ZnINRNqosw0Bv7i1gyHUkFj7oSaWlu3ovC8GxNso5fluz3qLVhBVeT/Lz7ZTHyxL5dDalQWPVOsQWtRnuwXaFTj9jVVh8pma9JjZ4zYSj5ZOyma7uuolffh+IR5aW97cHuBUXKGKXlKjn+DiHWMcYJah4N0lYCMlJOXipGRr5qdgoSTrqWSq6WFl2ypoaUAAAIfkECQEAAQAsAAAAACgAKAAAApaEb6HLgd/iO7FNWtcFWe+ufODGjRfoiJ2akShbueb0wtI50zm02pbvwfWEMWBQ1zKGlLIhskiEPm9R6vRXxV4ZzWT2yHOGpWMyorblKlNp8HmHEb/lCXjcW7bmtXP8Xt229OVWR1fod2eWqNfHuMjXCPkIGNileOiImVmCOEmoSfn3yXlJWmoHGhqp6ilYuWYpmTqKUgAAIfkECQEAAQAsAAAAACgAKAAAApiEH6kb58biQ3FNWtMFWW3eNVcojuFGfqnZqSebuS06w5V80/X02pKe8zFwP6EFWOT1lDFk8rGERh1TTNOocQ61Hm4Xm2VexUHpzjymViHrFbiELsefVrn6XKfnt2Q9G/+Xdie499XHd2g4h7ioOGhXGJboGAnXSBnoBwKYyfioubZJ2Hn0RuRZaflZOil56Zp6iioKSXpUAAAh+QQJAQABACwAAAAAKAAoAAACkoQRqRvnxuI7kU1a1UU5bd5tnSeOZXhmn5lWK3qNTWvRdQxP8qvaC+/yaYQzXO7BMvaUEmJRd3TsiMAgswmNYrSgZdYrTX6tSHGZO73ezuAw2uxuQ+BbeZfMxsexY35+/Qe4J1inV0g4x3WHuMhIl2jXOKT2Q+VU5fgoSUI52VfZyfkJGkha6jmY+aaYdirq+lQAACH5BAkBAAEALAAAAAAoACgAAAKWBIKpYe0L3YNKToqswUlvznigd4wiR4KhZrKt9Upqip61i9E3vMvxRdHlbEFiEXfk9YARYxOZZD6VQ2pUunBmtRXo1Lf8hMVVcNl8JafV38aM2/Fu5V16Bn63r6xt97j09+MXSFi4BniGFae3hzbH9+hYBzkpuUh5aZmHuanZOZgIuvbGiNeomCnaxxap2upaCZsq+1kAACH5BAkBAAEALAAAAAAoACgAAAKXjI8By5zf4kOxTVrXNVlv1X0d8IGZGKLnNpYtm8Lr9cqVeuOSvfOW79D9aDHizNhDJidFZhNydEahOaDH6nomtJjp1tutKoNWkvA6JqfRVLHU/QUfau9l2x7G54d1fl995xcIGAdXqMfBNadoYrhH+Mg2KBlpVpbluCiXmMnZ2Sh4GBqJ+ckIOqqJ6LmKSllZmsoq6wpQAAAh+QQJAQABACwAAAAAKAAoAAAClYx/oLvoxuJDkU1a1YUZbJ59nSd2ZXhWqbRa2/gF8Gu2DY3iqs7yrq+xBYEkYvFSM8aSSObE+ZgRl1BHFZNr7pRCavZ5BW2142hY3AN/zWtsmf12p9XxxFl2lpLn1rseztfXZjdIWIf2s5dItwjYKBgo9yg5pHgzJXTEeGlZuenpyPmpGQoKOWkYmSpaSnqKileI2FAAACH5BAkBAAEALAAAAAAoACgAAAKVjB+gu+jG4kORTVrVhRlsnn2dJ3ZleFaptFrb+CXmO9OozeL5VfP99HvAWhpiUdcwkpBH3825AwYdU8xTqlLGhtCosArKMpvfa1mMRae9VvWZfeB2XfPkeLmm18lUcBj+p5dnN8jXZ3YIGEhYuOUn45aoCDkp16hl5IjYJvjWKcnoGQpqyPlpOhr3aElaqrq56Bq7VAAAOw==");height:100%;-ms-filter:"alpha(opacity=25)";opacity:0.25}.ui-progressbar-indeterminate .ui-progressbar-value{background-image:none}.ui-selectable{-ms-touch-action:none;touch-action:none}.ui-selectable-helper{position:absolute;z-index:100;border:1px dotted black}.ui-selectmenu-menu{padding:0;margin:0;position:absolute;top:0;left:0;display:none}.ui-selectmenu-menu .ui-menu{overflow:auto;overflow-x:hidden;padding-bottom:1px}.ui-selectmenu-menu .ui-menu .ui-selectmenu-optgroup{font-size:1em;font-weight:bold;line-height:1.5;padding:2px 0.4em;margin:0.5em 0 0 0;height:auto;border:0}.ui-selectmenu-open{display:block}.ui-selectmenu-text{display:block;margin-right:20px;overflow:hidden;text-overflow:ellipsis}.ui-selectmenu-button.ui-button{text-align:left;white-space:nowrap;width:14em}.ui-selectmenu-icon.ui-icon{float:right;margin-top:0}.ui-slider{position:relative;text-align:left}.ui-slider .ui-slider-handle{position:absolute;z-index:2;width:1.2em;height:1.2em;cursor:pointer;-ms-touch-action:none;touch-action:none}.ui-slider .ui-slider-range{position:absolute;z-index:1;font-size:.7em;display:block;border:0;background-position:0 0}.ui-slider.ui-state-disabled .ui-slider-handle,.ui-slider.ui-state-disabled .ui-slider-range{filter:inherit}.ui-slider-horizontal{height:.8em}.ui-slider-horizontal .ui-slider-handle{top:-.3em;margin-left:-.6em}.ui-slider-horizontal .ui-slider-range{top:0;height:100%}.ui-slider-horizontal .ui-slider-range-min{left:0}.ui-slider-horizontal .ui-slider-range-max{right:0}.ui-slider-vertical{width:.8em;height:100px}.ui-slider-vertical .ui-slider-handle{left:-.3em;margin-left:0;margin-bottom:-.6em}.ui-slider-vertical .ui-slider-range{left:0;width:100%}.ui-slider-vertical .ui-slider-range-min{bottom:0}.ui-slider-vertical .ui-slider-range-max{top:0}.ui-sortable-handle{-ms-touch-action:none;touch-action:none}.ui-spinner{position:relative;display:inline-block;overflow:hidden;padding:0;vertical-align:middle}.ui-spinner-input{border:none;background:none;color:inherit;padding:.222em 0;margin:.2em 0;vertical-align:middle;margin-left:.4em;margin-right:2em}.ui-spinner-button{width:1.6em;height:50%;font-size:.5em;padding:0;margin:0;text-align:center;position:absolute;cursor:default;display:block;overflow:hidden;right:0}.ui-spinner a.ui-spinner-button{border-top-style:none;border-bottom-style:none;border-right-style:none}.ui-spinner-up{top:0}.ui-spinner-down{bottom:0}.ui-tabs{position:relative;padding:.2em}.ui-tabs .ui-tabs-nav{margin:0;padding:.2em .2em 0}.ui-tabs .ui-tabs-nav li{list-style:none;float:left;position:relative;top:0;margin:1px .2em 0 0;border-bottom-width:0;padding:0;white-space:nowrap}.ui-tabs .ui-tabs-nav .ui-tabs-anchor{float:left;padding:.5em 1em;text-decoration:none}.ui-tabs .ui-tabs-nav li.ui-tabs-active{margin-bottom:-1px;padding-bottom:1px}.ui-tabs .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor,.ui-tabs .ui-tabs-nav li.ui-state-disabled .ui-tabs-anchor,.ui-tabs .ui-tabs-nav li.ui-tabs-loading .ui-tabs-anchor{cursor:text}.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor{cursor:pointer}.ui-tabs .ui-tabs-panel{display:block;border-width:0;padding:1em 1.4em;background:none}.ui-tooltip{padding:8px;position:absolute;z-index:9999;max-width:300px}body .ui-tooltip{border-width:2px}.ui-widget{font-family:Arial,Helvetica,sans-serif;font-size:1em}.ui-widget .ui-widget{font-size:1em}.ui-widget input,.ui-widget select,.ui-widget textarea,.ui-widget button{font-family:Arial,Helvetica,sans-serif;font-size:1em}.ui-widget.ui-widget-content{border:1px solid #c5c5c5}.ui-widget-content{border:1px solid #ddd;background:#fff;color:#333}.ui-widget-content a{color:#333}.ui-widget-header{border:1px solid #ddd;background:#e9e9e9;color:#333;font-weight:bold}.ui-widget-header a{color:#333}.ui-state-default,.ui-widget-content .ui-state-default,.ui-widget-header .ui-state-default,.ui-button,html .ui-button.ui-state-disabled:hover,html .ui-button.ui-state-disabled:active{border:1px solid #c5c5c5;background:#f6f6f6;font-weight:normal;color:#454545}.ui-state-default a,.ui-state-default a:link,.ui-state-default a:visited,a.ui-button,a:link.ui-button,a:visited.ui-button,.ui-button{color:#454545;text-decoration:none}.ui-state-hover,.ui-widget-content .ui-state-hover,.ui-widget-header .ui-state-hover,.ui-state-focus,.ui-widget-content .ui-state-focus,.ui-widget-header .ui-state-focus,.ui-button:hover,.ui-button:focus{border:1px solid #ccc;background:#ededed;font-weight:normal;color:#2b2b2b}.ui-state-hover a,.ui-state-hover a:hover,.ui-state-hover a:link,.ui-state-hover a:visited,.ui-state-focus a,.ui-state-focus a:hover,.ui-state-focus a:link,.ui-state-focus a:visited,a.ui-button:hover,a.ui-button:focus{color:#2b2b2b;text-decoration:none}.ui-visual-focus{box-shadow:0 0 3px 1px rgb(94,158,214)}.ui-state-active,.ui-widget-content .ui-state-active,.ui-widget-header .ui-state-active,a.ui-button:active,.ui-button:active,.ui-button.ui-state-active:hover{border:1px solid #003eff;background:#007fff;font-weight:normal;color:#fff}.ui-icon-background,.ui-state-active .ui-icon-background{border:#003eff;background-color:#fff}.ui-state-active a,.ui-state-active a:link,.ui-state-active a:visited{color:#fff;text-decoration:none}.ui-state-highlight,.ui-widget-content .ui-state-highlight,.ui-widget-header .ui-state-highlight{border:1px solid #dad55e;background:#fffa90;color:#777620}.ui-state-checked{border:1px solid #dad55e;background:#fffa90}.ui-state-highlight a,.ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a{color:#777620}.ui-state-error,.ui-widget-content .ui-state-error,.ui-widget-header .ui-state-error{border:1px solid #f1a899;background:#fddfdf;color:#5f3f3f}.ui-state-error a,.ui-widget-content .ui-state-error a,.ui-widget-header .ui-state-error a{color:#5f3f3f}.ui-state-error-text,.ui-widget-content .ui-state-error-text,.ui-widget-header .ui-state-error-text{color:#5f3f3f}.ui-priority-primary,.ui-widget-content .ui-priority-primary,.ui-widget-header .ui-priority-primary{font-weight:bold}.ui-priority-secondary,.ui-widget-content .ui-priority-secondary,.ui-widget-header .ui-priority-secondary{opacity:.7;-ms-filter:"alpha(opacity=70)";font-weight:normal}.ui-state-disabled,.ui-widget-content .ui-state-disabled,.ui-widget-header .ui-state-disabled{opacity:.35;-ms-filter:"alpha(opacity=35)";background-image:none}.ui-state-disabled .ui-icon{-ms-filter:"alpha(opacity=35)"}.ui-icon{width:16px;height:16px}.ui-icon,.ui-widget-content .ui-icon{background-image:url("images/ui-icons_444444_256x240.png")}.ui-widget-header .ui-icon{background-image:url("images/ui-icons_444444_256x240.png")}.ui-state-hover .ui-icon,.ui-state-focus .ui-icon,.ui-button:hover .ui-icon,.ui-button:focus .ui-icon{background-image:url("images/ui-icons_555555_256x240.png")}.ui-state-active .ui-icon,.ui-button:active .ui-icon{background-image:url("images/ui-icons_ffffff_256x240.png")}.ui-state-highlight .ui-icon,.ui-button .ui-state-highlight.ui-icon{background-image:url("images/ui-icons_777620_256x240.png")}.ui-state-error .ui-icon,.ui-state-error-text .ui-icon{background-image:url("images/ui-icons_cc0000_256x240.png")}.ui-button .ui-icon{background-image:url("images/ui-icons_777777_256x240.png")}.ui-icon-blank.ui-icon-blank.ui-icon-blank{background-image:none}.ui-icon-caret-1-n{background-position:0 0}.ui-icon-caret-1-ne{background-position:-16px 0}.ui-icon-caret-1-e{background-position:-32px 0}.ui-icon-caret-1-se{background-position:-48px 0}.ui-icon-caret-1-s{background-position:-65px 0}.ui-icon-caret-1-sw{background-position:-80px 0}.ui-icon-caret-1-w{background-position:-96px 0}.ui-icon-caret-1-nw{background-position:-112px 0}.ui-icon-caret-2-n-s{background-position:-128px 0}.ui-icon-caret-2-e-w{background-position:-144px 0}.ui-icon-triangle-1-n{background-position:0 -16px}.ui-icon-triangle-1-ne{background-position:-16px -16px}.ui-icon-triangle-1-e{background-position:-32px -16px}.ui-icon-triangle-1-se{background-position:-48px -16px}.ui-icon-triangle-1-s{background-position:-65px -16px}.ui-icon-triangle-1-sw{background-position:-80px -16px}.ui-icon-triangle-1-w{background-position:-96px -16px}.ui-icon-triangle-1-nw{background-position:-112px -16px}.ui-icon-triangle-2-n-s{background-position:-128px -16px}.ui-icon-triangle-2-e-w{background-position:-144px -16px}.ui-icon-arrow-1-n{background-position:0 -32px}.ui-icon-arrow-1-ne{background-position:-16px -32px}.ui-icon-arrow-1-e{background-position:-32px -32px}.ui-icon-arrow-1-se{background-position:-48px -32px}.ui-icon-arrow-1-s{background-position:-65px -32px}.ui-icon-arrow-1-sw{background-position:-80px -32px}.ui-icon-arrow-1-w{background-position:-96px -32px}.ui-icon-arrow-1-nw{background-position:-112px -32px}.ui-icon-arrow-2-n-s{background-position:-128px -32px}.ui-icon-arrow-2-ne-sw{background-position:-144px -32px}.ui-icon-arrow-2-e-w{background-position:-160px -32px}.ui-icon-arrow-2-se-nw{background-position:-176px -32px}.ui-icon-arrowstop-1-n{background-position:-192px -32px}.ui-icon-arrowstop-1-e{background-position:-208px -32px}.ui-icon-arrowstop-1-s{background-position:-224px -32px}.ui-icon-arrowstop-1-w{background-position:-240px -32px}.ui-icon-arrowthick-1-n{background-position:1px -48px}.ui-icon-arrowthick-1-ne{background-position:-16px -48px}.ui-icon-arrowthick-1-e{background-position:-32px -48px}.ui-icon-arrowthick-1-se{background-position:-48px -48px}.ui-icon-arrowthick-1-s{background-position:-64px -48px}.ui-icon-arrowthick-1-sw{background-position:-80px -48px}.ui-icon-arrowthick-1-w{background-position:-96px -48px}.ui-icon-arrowthick-1-nw{background-position:-112px -48px}.ui-icon-arrowthick-2-n-s{background-position:-128px -48px}.ui-icon-arrowthick-2-ne-sw{background-position:-144px -48px}.ui-icon-arrowthick-2-e-w{background-position:-160px -48px}.ui-icon-arrowthick-2-se-nw{background-position:-176px -48px}.ui-icon-arrowthickstop-1-n{background-position:-192px -48px}.ui-icon-arrowthickstop-1-e{background-position:-208px -48px}.ui-icon-arrowthickstop-1-s{background-position:-224px -48px}.ui-icon-arrowthickstop-1-w{background-position:-240px -48px}.ui-icon-arrowreturnthick-1-w{background-position:0 -64px}.ui-icon-arrowreturnthick-1-n{background-position:-16px -64px}.ui-icon-arrowreturnthick-1-e{background-position:-32px -64px}.ui-icon-arrowreturnthick-1-s{background-position:-48px -64px}.ui-icon-arrowreturn-1-w{background-position:-64px -64px}.ui-icon-arrowreturn-1-n{background-position:-80px -64px}.ui-icon-arrowreturn-1-e{background-position:-96px -64px}.ui-icon-arrowreturn-1-s{background-position:-112px -64px}.ui-icon-arrowrefresh-1-w{background-position:-128px -64px}.ui-icon-arrowrefresh-1-n{background-position:-144px -64px}.ui-icon-arrowrefresh-1-e{background-position:-160px -64px}.ui-icon-arrowrefresh-1-s{background-position:-176px -64px}.ui-icon-arrow-4{background-position:0 -80px}.ui-icon-arrow-4-diag{background-position:-16px -80px}.ui-icon-extlink{background-position:-32px -80px}.ui-icon-newwin{background-position:-48px -80px}.ui-icon-refresh{background-position:-64px -80px}.ui-icon-shuffle{background-position:-80px -80px}.ui-icon-transfer-e-w{background-position:-96px -80px}.ui-icon-transferthick-e-w{background-position:-112px -80px}.ui-icon-folder-collapsed{background-position:0 -96px}.ui-icon-folder-open{background-position:-16px -96px}.ui-icon-document{background-position:-32px -96px}.ui-icon-document-b{background-position:-48px -96px}.ui-icon-note{background-position:-64px -96px}.ui-icon-mail-closed{background-position:-80px -96px}.ui-icon-mail-open{background-position:-96px -96px}.ui-icon-suitcase{background-position:-112px -96px}.ui-icon-comment{background-position:-128px -96px}.ui-icon-person{background-position:-144px -96px}.ui-icon-print{background-position:-160px -96px}.ui-icon-trash{background-position:-176px -96px}.ui-icon-locked{background-position:-192px -96px}.ui-icon-unlocked{background-position:-208px -96px}.ui-icon-bookmark{background-position:-224px -96px}.ui-icon-tag{background-position:-240px -96px}.ui-icon-home{background-position:0 -112px}.ui-icon-flag{background-position:-16px -112px}.ui-icon-calendar{background-position:-32px -112px}.ui-icon-cart{background-position:-48px -112px}.ui-icon-pencil{background-position:-64px -112px}.ui-icon-clock{background-position:-80px -112px}.ui-icon-disk{background-position:-96px -112px}.ui-icon-calculator{background-position:-112px -112px}.ui-icon-zoomin{background-position:-128px -112px}.ui-icon-zoomout{background-position:-144px -112px}.ui-icon-search{background-position:-160px -112px}.ui-icon-wrench{background-position:-176px -112px}.ui-icon-gear{background-position:-192px -112px}.ui-icon-heart{background-position:-208px -112px}.ui-icon-star{background-position:-224px -112px}.ui-icon-link{background-position:-240px -112px}.ui-icon-cancel{background-position:0 -128px}.ui-icon-plus{background-position:-16px -128px}.ui-icon-plusthick{background-position:-32px -128px}.ui-icon-minus{background-position:-48px -128px}.ui-icon-minusthick{background-position:-64px -128px}.ui-icon-close{background-position:-80px -128px}.ui-icon-closethick{background-position:-96px -128px}.ui-icon-key{background-position:-112px -128px}.ui-icon-lightbulb{background-position:-128px -128px}.ui-icon-scissors{background-position:-144px -128px}.ui-icon-clipboard{background-position:-160px -128px}.ui-icon-copy{background-position:-176px -128px}.ui-icon-contact{background-position:-192px -128px}.ui-icon-image{background-position:-208px -128px}.ui-icon-video{background-position:-224px -128px}.ui-icon-script{background-position:-240px -128px}.ui-icon-alert{background-position:0 -144px}.ui-icon-info{background-position:-16px -144px}.ui-icon-notice{background-position:-32px -144px}.ui-icon-help{background-position:-48px -144px}.ui-icon-check{background-position:-64px -144px}.ui-icon-bullet{background-position:-80px -144px}.ui-icon-radio-on{background-position:-96px -144px}.ui-icon-radio-off{background-position:-112px -144px}.ui-icon-pin-w{background-position:-128px -144px}.ui-icon-pin-s{background-position:-144px -144px}.ui-icon-play{background-position:0 -160px}.ui-icon-pause{background-position:-16px -160px}.ui-icon-seek-next{background-position:-32px -160px}.ui-icon-seek-prev{background-position:-48px -160px}.ui-icon-seek-end{background-position:-64px -160px}.ui-icon-seek-start{background-position:-80px -160px}.ui-icon-seek-first{background-position:-80px -160px}.ui-icon-stop{background-position:-96px -160px}.ui-icon-eject{background-position:-112px -160px}.ui-icon-volume-off{background-position:-128px -160px}.ui-icon-volume-on{background-position:-144px -160px}.ui-icon-power{background-position:0 -176px}.ui-icon-signal-diag{background-position:-16px -176px}.ui-icon-signal{background-position:-32px -176px}.ui-icon-battery-0{background-position:-48px -176px}.ui-icon-battery-1{background-position:-64px -176px}.ui-icon-battery-2{background-position:-80px -176px}.ui-icon-battery-3{background-position:-96px -176px}.ui-icon-circle-plus{background-position:0 -192px}.ui-icon-circle-minus{background-position:-16px -192px}.ui-icon-circle-close{background-position:-32px -192px}.ui-icon-circle-triangle-e{background-position:-48px -192px}.ui-icon-circle-triangle-s{background-position:-64px -192px}.ui-icon-circle-triangle-w{background-position:-80px -192px}.ui-icon-circle-triangle-n{background-position:-96px -192px}.ui-icon-circle-arrow-e{background-position:-112px -192px}.ui-icon-circle-arrow-s{background-position:-128px -192px}.ui-icon-circle-arrow-w{background-position:-144px -192px}.ui-icon-circle-arrow-n{background-position:-160px -192px}.ui-icon-circle-zoomin{background-position:-176px -192px}.ui-icon-circle-zoomout{background-position:-192px -192px}.ui-icon-circle-check{background-position:-208px -192px}.ui-icon-circlesmall-plus{background-position:0 -208px}.ui-icon-circlesmall-minus{background-position:-16px -208px}.ui-icon-circlesmall-close{background-position:-32px -208px}.ui-icon-squaresmall-plus{background-position:-48px -208px}.ui-icon-squaresmall-minus{background-position:-64px -208px}.ui-icon-squaresmall-close{background-position:-80px -208px}.ui-icon-grip-dotted-vertical{background-position:0 -224px}.ui-icon-grip-dotted-horizontal{background-position:-16px -224px}.ui-icon-grip-solid-vertical{background-position:-32px -224px}.ui-icon-grip-solid-horizontal{background-position:-48px -224px}.ui-icon-gripsmall-diagonal-se{background-position:-64px -224px}.ui-icon-grip-diagonal-se{background-position:-80px -224px}.ui-corner-all,.ui-corner-top,.ui-corner-left,.ui-corner-tl{border-top-left-radius:3px}.ui-corner-all,.ui-corner-top,.ui-corner-right,.ui-corner-tr{border-top-right-radius:3px}.ui-corner-all,.ui-corner-bottom,.ui-corner-left,.ui-corner-bl{border-bottom-left-radius:3px}.ui-corner-all,.ui-corner-bottom,.ui-corner-right,.ui-corner-br{border-bottom-right-radius:3px}.ui-widget-overlay{background:#aaa;opacity:.3;-ms-filter:Alpha(Opacity=30)}.ui-widget-shadow{-webkit-box-shadow:0 0 5px #666;box-shadow:0 0 5px #666} \ No newline at end of file diff --git a/lib/web/ui/static/assets/vendor/js/jquery.ui.min.js b/lib/web/ui/static/assets/vendor/js/jquery.ui.min.js new file mode 100644 index 0000000..50b036f --- /dev/null +++ b/lib/web/ui/static/assets/vendor/js/jquery.ui.min.js @@ -0,0 +1,6 @@ +/*! jQuery UI - v1.13.2 - 2022-07-14 +* http://jqueryui.com +* Includes: widget.js, position.js, data.js, disable-selection.js, effect.js, effects/effect-blind.js, effects/effect-bounce.js, effects/effect-clip.js, effects/effect-drop.js, effects/effect-explode.js, effects/effect-fade.js, effects/effect-fold.js, effects/effect-highlight.js, effects/effect-puff.js, effects/effect-pulsate.js, effects/effect-scale.js, effects/effect-shake.js, effects/effect-size.js, effects/effect-slide.js, effects/effect-transfer.js, focusable.js, form-reset-mixin.js, jquery-patch.js, keycode.js, labels.js, scroll-parent.js, tabbable.js, unique-id.js, widgets/accordion.js, widgets/autocomplete.js, widgets/button.js, widgets/checkboxradio.js, widgets/controlgroup.js, widgets/datepicker.js, widgets/dialog.js, widgets/draggable.js, widgets/droppable.js, widgets/menu.js, widgets/mouse.js, widgets/progressbar.js, widgets/resizable.js, widgets/selectable.js, widgets/selectmenu.js, widgets/slider.js, widgets/sortable.js, widgets/spinner.js, widgets/tabs.js, widgets/tooltip.js +* Copyright jQuery Foundation and other contributors; Licensed MIT */ + +!function(t){"use strict";"function"==typeof define&&define.amd?define(["jquery"],t):t(jQuery)}(function(V){"use strict";V.ui=V.ui||{};V.ui.version="1.13.2";var n,i=0,a=Array.prototype.hasOwnProperty,r=Array.prototype.slice;V.cleanData=(n=V.cleanData,function(t){for(var e,i,s=0;null!=(i=t[s]);s++)(e=V._data(i,"events"))&&e.remove&&V(i).triggerHandler("remove");n(t)}),V.widget=function(t,i,e){var s,n,o,a={},r=t.split(".")[0],l=r+"-"+(t=t.split(".")[1]);return e||(e=i,i=V.Widget),Array.isArray(e)&&(e=V.extend.apply(null,[{}].concat(e))),V.expr.pseudos[l.toLowerCase()]=function(t){return!!V.data(t,l)},V[r]=V[r]||{},s=V[r][t],n=V[r][t]=function(t,e){if(!this||!this._createWidget)return new n(t,e);arguments.length&&this._createWidget(t,e)},V.extend(n,s,{version:e.version,_proto:V.extend({},e),_childConstructors:[]}),(o=new i).options=V.widget.extend({},o.options),V.each(e,function(e,s){function n(){return i.prototype[e].apply(this,arguments)}function o(t){return i.prototype[e].apply(this,t)}a[e]="function"==typeof s?function(){var t,e=this._super,i=this._superApply;return this._super=n,this._superApply=o,t=s.apply(this,arguments),this._super=e,this._superApply=i,t}:s}),n.prototype=V.widget.extend(o,{widgetEventPrefix:s&&o.widgetEventPrefix||t},a,{constructor:n,namespace:r,widgetName:t,widgetFullName:l}),s?(V.each(s._childConstructors,function(t,e){var i=e.prototype;V.widget(i.namespace+"."+i.widgetName,n,e._proto)}),delete s._childConstructors):i._childConstructors.push(n),V.widget.bridge(t,n),n},V.widget.extend=function(t){for(var e,i,s=r.call(arguments,1),n=0,o=s.length;n",options:{classes:{},disabled:!1,create:null},_createWidget:function(t,e){e=V(e||this.defaultElement||this)[0],this.element=V(e),this.uuid=i++,this.eventNamespace="."+this.widgetName+this.uuid,this.bindings=V(),this.hoverable=V(),this.focusable=V(),this.classesElementLookup={},e!==this&&(V.data(e,this.widgetFullName,this),this._on(!0,this.element,{remove:function(t){t.target===e&&this.destroy()}}),this.document=V(e.style?e.ownerDocument:e.document||e),this.window=V(this.document[0].defaultView||this.document[0].parentWindow)),this.options=V.widget.extend({},this.options,this._getCreateOptions(),t),this._create(),this.options.disabled&&this._setOptionDisabled(this.options.disabled),this._trigger("create",null,this._getCreateEventData()),this._init()},_getCreateOptions:function(){return{}},_getCreateEventData:V.noop,_create:V.noop,_init:V.noop,destroy:function(){var i=this;this._destroy(),V.each(this.classesElementLookup,function(t,e){i._removeClass(e,t)}),this.element.off(this.eventNamespace).removeData(this.widgetFullName),this.widget().off(this.eventNamespace).removeAttr("aria-disabled"),this.bindings.off(this.eventNamespace)},_destroy:V.noop,widget:function(){return this.element},option:function(t,e){var i,s,n,o=t;if(0===arguments.length)return V.widget.extend({},this.options);if("string"==typeof t)if(o={},t=(i=t.split(".")).shift(),i.length){for(s=o[t]=V.widget.extend({},this.options[t]),n=0;n
"),i=e.children()[0];return V("body").append(e),t=i.offsetWidth,e.css("overflow","scroll"),t===(i=i.offsetWidth)&&(i=e[0].clientWidth),e.remove(),s=t-i},getScrollInfo:function(t){var e=t.isWindow||t.isDocument?"":t.element.css("overflow-x"),i=t.isWindow||t.isDocument?"":t.element.css("overflow-y"),e="scroll"===e||"auto"===e&&t.widthx(k(s),k(n))?o.important="horizontal":o.important="vertical",u.using.call(this,t,o)}),a.offset(V.extend(h,{using:t}))})},V.ui.position={fit:{left:function(t,e){var i=e.within,s=i.isWindow?i.scrollLeft:i.offset.left,n=i.width,o=t.left-e.collisionPosition.marginLeft,a=s-o,r=o+e.collisionWidth-n-s;e.collisionWidth>n?0n?0")[0],w=d.each;function P(t){return null==t?t+"":"object"==typeof t?p[e.call(t)]||"object":typeof t}function M(t,e,i){var s=v[e.type]||{};return null==t?i||!e.def?null:e.def:(t=s.floor?~~t:parseFloat(t),isNaN(t)?e.def:s.mod?(t+s.mod)%s.mod:Math.min(s.max,Math.max(0,t)))}function S(s){var n=m(),o=n._rgba=[];return s=s.toLowerCase(),w(g,function(t,e){var i=e.re.exec(s),i=i&&e.parse(i),e=e.space||"rgba";if(i)return i=n[e](i),n[_[e].cache]=i[_[e].cache],o=n._rgba=i._rgba,!1}),o.length?("0,0,0,0"===o.join()&&d.extend(o,B.transparent),n):B[s]}function H(t,e,i){return 6*(i=(i+1)%1)<1?t+(e-t)*i*6:2*i<1?e:3*i<2?t+(e-t)*(2/3-i)*6:t}y.style.cssText="background-color:rgba(1,1,1,.5)",b.rgba=-1o.mod/2?s+=o.mod:s-n>o.mod/2&&(s-=o.mod)),l[i]=M((n-s)*a+s,e)))}),this[e](l)},blend:function(t){if(1===this._rgba[3])return this;var e=this._rgba.slice(),i=e.pop(),s=m(t)._rgba;return m(d.map(e,function(t,e){return(1-i)*s[e]+i*t}))},toRgbaString:function(){var t="rgba(",e=d.map(this._rgba,function(t,e){return null!=t?t:2").addClass("ui-effects-wrapper").css({fontSize:"100%",background:"transparent",border:"none",margin:0,padding:0}),e={width:i.width(),height:i.height()},n=document.activeElement;try{n.id}catch(t){n=document.body}return i.wrap(t),i[0]!==n&&!V.contains(i[0],n)||V(n).trigger("focus"),t=i.parent(),"static"===i.css("position")?(t.css({position:"relative"}),i.css({position:"relative"})):(V.extend(s,{position:i.css("position"),zIndex:i.css("z-index")}),V.each(["top","left","bottom","right"],function(t,e){s[e]=i.css(e),isNaN(parseInt(s[e],10))&&(s[e]="auto")}),i.css({position:"relative",top:0,left:0,right:"auto",bottom:"auto"})),i.css(e),t.css(s).show()},removeWrapper:function(t){var e=document.activeElement;return t.parent().is(".ui-effects-wrapper")&&(t.parent().replaceWith(t),t[0]!==e&&!V.contains(t[0],e)||V(e).trigger("focus")),t}}),V.extend(V.effects,{version:"1.13.2",define:function(t,e,i){return i||(i=e,e="effect"),V.effects.effect[t]=i,V.effects.effect[t].mode=e,i},scaledDimensions:function(t,e,i){if(0===e)return{height:0,width:0,outerHeight:0,outerWidth:0};var s="horizontal"!==i?(e||100)/100:1,e="vertical"!==i?(e||100)/100:1;return{height:t.height()*e,width:t.width()*s,outerHeight:t.outerHeight()*e,outerWidth:t.outerWidth()*s}},clipToBox:function(t){return{width:t.clip.right-t.clip.left,height:t.clip.bottom-t.clip.top,left:t.clip.left,top:t.clip.top}},unshift:function(t,e,i){var s=t.queue();1").insertAfter(t).css({display:/^(inline|ruby)/.test(t.css("display"))?"inline-block":"block",visibility:"hidden",marginTop:t.css("marginTop"),marginBottom:t.css("marginBottom"),marginLeft:t.css("marginLeft"),marginRight:t.css("marginRight"),float:t.css("float")}).outerWidth(t.outerWidth()).outerHeight(t.outerHeight()).addClass("ui-effects-placeholder"),t.data(j+"placeholder",e)),t.css({position:i,left:s.left,top:s.top}),e},removePlaceholder:function(t){var e=j+"placeholder",i=t.data(e);i&&(i.remove(),t.removeData(e))},cleanUp:function(t){V.effects.restoreStyle(t),V.effects.removePlaceholder(t)},setTransition:function(s,t,n,o){return o=o||{},V.each(t,function(t,e){var i=s.cssUnit(e);0");l.appendTo("body").addClass(t.className).css({top:s.top-a,left:s.left-r,height:i.innerHeight(),width:i.innerWidth(),position:n?"fixed":"absolute"}).animate(o,t.duration,t.easing,function(){l.remove(),"function"==typeof e&&e()})}}),V.fx.step.clip=function(t){t.clipInit||(t.start=V(t.elem).cssClip(),"string"==typeof t.end&&(t.end=G(t.end,t.elem)),t.clipInit=!0),V(t.elem).cssClip({top:t.pos*(t.end.top-t.start.top)+t.start.top,right:t.pos*(t.end.right-t.start.right)+t.start.right,bottom:t.pos*(t.end.bottom-t.start.bottom)+t.start.bottom,left:t.pos*(t.end.left-t.start.left)+t.start.left})},Y={},V.each(["Quad","Cubic","Quart","Quint","Expo"],function(e,t){Y[t]=function(t){return Math.pow(t,e+2)}}),V.extend(Y,{Sine:function(t){return 1-Math.cos(t*Math.PI/2)},Circ:function(t){return 1-Math.sqrt(1-t*t)},Elastic:function(t){return 0===t||1===t?t:-Math.pow(2,8*(t-1))*Math.sin((80*(t-1)-7.5)*Math.PI/15)},Back:function(t){return t*t*(3*t-2)},Bounce:function(t){for(var e,i=4;t<((e=Math.pow(2,--i))-1)/11;);return 1/Math.pow(4,3-i)-7.5625*Math.pow((3*e-2)/22-t,2)}}),V.each(Y,function(t,e){V.easing["easeIn"+t]=e,V.easing["easeOut"+t]=function(t){return 1-e(1-t)},V.easing["easeInOut"+t]=function(t){return t<.5?e(2*t)/2:1-e(-2*t+2)/2}});y=V.effects,V.effects.define("blind","hide",function(t,e){var i={up:["bottom","top"],vertical:["bottom","top"],down:["top","bottom"],left:["right","left"],horizontal:["right","left"],right:["left","right"]},s=V(this),n=t.direction||"up",o=s.cssClip(),a={clip:V.extend({},o)},r=V.effects.createPlaceholder(s);a.clip[i[n][0]]=a.clip[i[n][1]],"show"===t.mode&&(s.cssClip(a.clip),r&&r.css(V.effects.clipToBox(a)),a.clip=o),r&&r.animate(V.effects.clipToBox(a),t.duration,t.easing),s.animate(a,{queue:!1,duration:t.duration,easing:t.easing,complete:e})}),V.effects.define("bounce",function(t,e){var i,s,n=V(this),o=t.mode,a="hide"===o,r="show"===o,l=t.direction||"up",h=t.distance,c=t.times||5,o=2*c+(r||a?1:0),u=t.duration/o,d=t.easing,p="up"===l||"down"===l?"top":"left",f="up"===l||"left"===l,g=0,t=n.queue().length;for(V.effects.createPlaceholder(n),l=n.css(p),h=h||n["top"==p?"outerHeight":"outerWidth"]()/3,r&&((s={opacity:1})[p]=l,n.css("opacity",0).css(p,f?2*-h:2*h).animate(s,u,d)),a&&(h/=Math.pow(2,c-1)),(s={})[p]=l;g").css({position:"absolute",visibility:"visible",left:-s*p,top:-i*f}).parent().addClass("ui-effects-explode").css({position:"absolute",overflow:"hidden",width:p,height:f,left:n+(u?a*p:0),top:o+(u?r*f:0),opacity:u?0:1}).animate({left:n+(u?0:a*p),top:o+(u?0:r*f),opacity:u?1:0},t.duration||500,t.easing,m)}),V.effects.define("fade","toggle",function(t,e){var i="show"===t.mode;V(this).css("opacity",i?0:1).animate({opacity:i?1:0},{queue:!1,duration:t.duration,easing:t.easing,complete:e})}),V.effects.define("fold","hide",function(e,t){var i=V(this),s=e.mode,n="show"===s,o="hide"===s,a=e.size||15,r=/([0-9]+)%/.exec(a),l=!!e.horizFirst?["right","bottom"]:["bottom","right"],h=e.duration/2,c=V.effects.createPlaceholder(i),u=i.cssClip(),d={clip:V.extend({},u)},p={clip:V.extend({},u)},f=[u[l[0]],u[l[1]]],s=i.queue().length;r&&(a=parseInt(r[1],10)/100*f[o?0:1]),d.clip[l[0]]=a,p.clip[l[0]]=a,p.clip[l[1]]=0,n&&(i.cssClip(p.clip),c&&c.css(V.effects.clipToBox(p)),p.clip=u),i.queue(function(t){c&&c.animate(V.effects.clipToBox(d),h,e.easing).animate(V.effects.clipToBox(p),h,e.easing),t()}).animate(d,h,e.easing).animate(p,h,e.easing).queue(t),V.effects.unshift(i,s,4)}),V.effects.define("highlight","show",function(t,e){var i=V(this),s={backgroundColor:i.css("backgroundColor")};"hide"===t.mode&&(s.opacity=0),V.effects.saveStyle(i),i.css({backgroundImage:"none",backgroundColor:t.color||"#ffff99"}).animate(s,{queue:!1,duration:t.duration,easing:t.easing,complete:e})}),V.effects.define("size",function(s,e){var n,i=V(this),t=["fontSize"],o=["borderTopWidth","borderBottomWidth","paddingTop","paddingBottom"],a=["borderLeftWidth","borderRightWidth","paddingLeft","paddingRight"],r=s.mode,l="effect"!==r,h=s.scale||"both",c=s.origin||["middle","center"],u=i.css("position"),d=i.position(),p=V.effects.scaledDimensions(i),f=s.from||p,g=s.to||V.effects.scaledDimensions(i,0);V.effects.createPlaceholder(i),"show"===r&&(r=f,f=g,g=r),n={from:{y:f.height/p.height,x:f.width/p.width},to:{y:g.height/p.height,x:g.width/p.width}},"box"!==h&&"both"!==h||(n.from.y!==n.to.y&&(f=V.effects.setTransition(i,o,n.from.y,f),g=V.effects.setTransition(i,o,n.to.y,g)),n.from.x!==n.to.x&&(f=V.effects.setTransition(i,a,n.from.x,f),g=V.effects.setTransition(i,a,n.to.x,g))),"content"!==h&&"both"!==h||n.from.y!==n.to.y&&(f=V.effects.setTransition(i,t,n.from.y,f),g=V.effects.setTransition(i,t,n.to.y,g)),c&&(c=V.effects.getBaseline(c,p),f.top=(p.outerHeight-f.outerHeight)*c.y+d.top,f.left=(p.outerWidth-f.outerWidth)*c.x+d.left,g.top=(p.outerHeight-g.outerHeight)*c.y+d.top,g.left=(p.outerWidth-g.outerWidth)*c.x+d.left),delete f.outerHeight,delete f.outerWidth,i.css(f),"content"!==h&&"both"!==h||(o=o.concat(["marginTop","marginBottom"]).concat(t),a=a.concat(["marginLeft","marginRight"]),i.find("*[width]").each(function(){var t=V(this),e=V.effects.scaledDimensions(t),i={height:e.height*n.from.y,width:e.width*n.from.x,outerHeight:e.outerHeight*n.from.y,outerWidth:e.outerWidth*n.from.x},e={height:e.height*n.to.y,width:e.width*n.to.x,outerHeight:e.height*n.to.y,outerWidth:e.width*n.to.x};n.from.y!==n.to.y&&(i=V.effects.setTransition(t,o,n.from.y,i),e=V.effects.setTransition(t,o,n.to.y,e)),n.from.x!==n.to.x&&(i=V.effects.setTransition(t,a,n.from.x,i),e=V.effects.setTransition(t,a,n.to.x,e)),l&&V.effects.saveStyle(t),t.css(i),t.animate(e,s.duration,s.easing,function(){l&&V.effects.restoreStyle(t)})})),i.animate(g,{queue:!1,duration:s.duration,easing:s.easing,complete:function(){var t=i.offset();0===g.opacity&&i.css("opacity",f.opacity),l||(i.css("position","static"===u?"relative":u).offset(t),V.effects.saveStyle(i)),e()}})}),V.effects.define("scale",function(t,e){var i=V(this),s=t.mode,s=parseInt(t.percent,10)||(0===parseInt(t.percent,10)||"effect"!==s?0:100),s=V.extend(!0,{from:V.effects.scaledDimensions(i),to:V.effects.scaledDimensions(i,s,t.direction||"both"),origin:t.origin||["middle","center"]},t);t.fade&&(s.from.opacity=1,s.to.opacity=0),V.effects.effect.size.call(this,s,e)}),V.effects.define("puff","hide",function(t,e){t=V.extend(!0,{},t,{fade:!0,percent:parseInt(t.percent,10)||150});V.effects.effect.scale.call(this,t,e)}),V.effects.define("pulsate","show",function(t,e){var i=V(this),s=t.mode,n="show"===s,o=2*(t.times||5)+(n||"hide"===s?1:0),a=t.duration/o,r=0,l=1,s=i.queue().length;for(!n&&i.is(":visible")||(i.css("opacity",0).show(),r=1);l li > :first-child").add(t.find("> :not(li)").even())},heightStyle:"auto",icons:{activeHeader:"ui-icon-triangle-1-s",header:"ui-icon-triangle-1-e"},activate:null,beforeActivate:null},hideProps:{borderTopWidth:"hide",borderBottomWidth:"hide",paddingTop:"hide",paddingBottom:"hide",height:"hide"},showProps:{borderTopWidth:"show",borderBottomWidth:"show",paddingTop:"show",paddingBottom:"show",height:"show"},_create:function(){var t=this.options;this.prevShow=this.prevHide=V(),this._addClass("ui-accordion","ui-widget ui-helper-reset"),this.element.attr("role","tablist"),t.collapsible||!1!==t.active&&null!=t.active||(t.active=0),this._processPanels(),t.active<0&&(t.active+=this.headers.length),this._refresh()},_getCreateEventData:function(){return{header:this.active,panel:this.active.length?this.active.next():V()}},_createIcons:function(){var t,e=this.options.icons;e&&(t=V(""),this._addClass(t,"ui-accordion-header-icon","ui-icon "+e.header),t.prependTo(this.headers),t=this.active.children(".ui-accordion-header-icon"),this._removeClass(t,e.header)._addClass(t,null,e.activeHeader)._addClass(this.headers,"ui-accordion-icons"))},_destroyIcons:function(){this._removeClass(this.headers,"ui-accordion-icons"),this.headers.children(".ui-accordion-header-icon").remove()},_destroy:function(){var t;this.element.removeAttr("role"),this.headers.removeAttr("role aria-expanded aria-selected aria-controls tabIndex").removeUniqueId(),this._destroyIcons(),t=this.headers.next().css("display","").removeAttr("role aria-hidden aria-labelledby").removeUniqueId(),"content"!==this.options.heightStyle&&t.css("height","")},_setOption:function(t,e){"active"!==t?("event"===t&&(this.options.event&&this._off(this.headers,this.options.event),this._setupEvents(e)),this._super(t,e),"collapsible"!==t||e||!1!==this.options.active||this._activate(0),"icons"===t&&(this._destroyIcons(),e&&this._createIcons())):this._activate(e)},_setOptionDisabled:function(t){this._super(t),this.element.attr("aria-disabled",t),this._toggleClass(null,"ui-state-disabled",!!t),this._toggleClass(this.headers.add(this.headers.next()),null,"ui-state-disabled",!!t)},_keydown:function(t){if(!t.altKey&&!t.ctrlKey){var e=V.ui.keyCode,i=this.headers.length,s=this.headers.index(t.target),n=!1;switch(t.keyCode){case e.RIGHT:case e.DOWN:n=this.headers[(s+1)%i];break;case e.LEFT:case e.UP:n=this.headers[(s-1+i)%i];break;case e.SPACE:case e.ENTER:this._eventHandler(t);break;case e.HOME:n=this.headers[0];break;case e.END:n=this.headers[i-1]}n&&(V(t.target).attr("tabIndex",-1),V(n).attr("tabIndex",0),V(n).trigger("focus"),t.preventDefault())}},_panelKeyDown:function(t){t.keyCode===V.ui.keyCode.UP&&t.ctrlKey&&V(t.currentTarget).prev().trigger("focus")},refresh:function(){var t=this.options;this._processPanels(),!1===t.active&&!0===t.collapsible||!this.headers.length?(t.active=!1,this.active=V()):!1===t.active?this._activate(0):this.active.length&&!V.contains(this.element[0],this.active[0])?this.headers.length===this.headers.find(".ui-state-disabled").length?(t.active=!1,this.active=V()):this._activate(Math.max(0,t.active-1)):t.active=this.headers.index(this.active),this._destroyIcons(),this._refresh()},_processPanels:function(){var t=this.headers,e=this.panels;"function"==typeof this.options.header?this.headers=this.options.header(this.element):this.headers=this.element.find(this.options.header),this._addClass(this.headers,"ui-accordion-header ui-accordion-header-collapsed","ui-state-default"),this.panels=this.headers.next().filter(":not(.ui-accordion-content-active)").hide(),this._addClass(this.panels,"ui-accordion-content","ui-helper-reset ui-widget-content"),e&&(this._off(t.not(this.headers)),this._off(e.not(this.panels)))},_refresh:function(){var i,t=this.options,e=t.heightStyle,s=this.element.parent();this.active=this._findActive(t.active),this._addClass(this.active,"ui-accordion-header-active","ui-state-active")._removeClass(this.active,"ui-accordion-header-collapsed"),this._addClass(this.active.next(),"ui-accordion-content-active"),this.active.next().show(),this.headers.attr("role","tab").each(function(){var t=V(this),e=t.uniqueId().attr("id"),i=t.next(),s=i.uniqueId().attr("id");t.attr("aria-controls",s),i.attr("aria-labelledby",e)}).next().attr("role","tabpanel"),this.headers.not(this.active).attr({"aria-selected":"false","aria-expanded":"false",tabIndex:-1}).next().attr({"aria-hidden":"true"}).hide(),this.active.length?this.active.attr({"aria-selected":"true","aria-expanded":"true",tabIndex:0}).next().attr({"aria-hidden":"false"}):this.headers.eq(0).attr("tabIndex",0),this._createIcons(),this._setupEvents(t.event),"fill"===e?(i=s.height(),this.element.siblings(":visible").each(function(){var t=V(this),e=t.css("position");"absolute"!==e&&"fixed"!==e&&(i-=t.outerHeight(!0))}),this.headers.each(function(){i-=V(this).outerHeight(!0)}),this.headers.next().each(function(){V(this).height(Math.max(0,i-V(this).innerHeight()+V(this).height()))}).css("overflow","auto")):"auto"===e&&(i=0,this.headers.next().each(function(){var t=V(this).is(":visible");t||V(this).show(),i=Math.max(i,V(this).css("height","").height()),t||V(this).hide()}).height(i))},_activate:function(t){t=this._findActive(t)[0];t!==this.active[0]&&(t=t||this.active[0],this._eventHandler({target:t,currentTarget:t,preventDefault:V.noop}))},_findActive:function(t){return"number"==typeof t?this.headers.eq(t):V()},_setupEvents:function(t){var i={keydown:"_keydown"};t&&V.each(t.split(" "),function(t,e){i[e]="_eventHandler"}),this._off(this.headers.add(this.headers.next())),this._on(this.headers,i),this._on(this.headers.next(),{keydown:"_panelKeyDown"}),this._hoverable(this.headers),this._focusable(this.headers)},_eventHandler:function(t){var e=this.options,i=this.active,s=V(t.currentTarget),n=s[0]===i[0],o=n&&e.collapsible,a=o?V():s.next(),r=i.next(),a={oldHeader:i,oldPanel:r,newHeader:o?V():s,newPanel:a};t.preventDefault(),n&&!e.collapsible||!1===this._trigger("beforeActivate",t,a)||(e.active=!o&&this.headers.index(s),this.active=n?V():s,this._toggle(a),this._removeClass(i,"ui-accordion-header-active","ui-state-active"),e.icons&&(i=i.children(".ui-accordion-header-icon"),this._removeClass(i,null,e.icons.activeHeader)._addClass(i,null,e.icons.header)),n||(this._removeClass(s,"ui-accordion-header-collapsed")._addClass(s,"ui-accordion-header-active","ui-state-active"),e.icons&&(n=s.children(".ui-accordion-header-icon"),this._removeClass(n,null,e.icons.header)._addClass(n,null,e.icons.activeHeader)),this._addClass(s.next(),"ui-accordion-content-active")))},_toggle:function(t){var e=t.newPanel,i=this.prevShow.length?this.prevShow:t.oldPanel;this.prevShow.add(this.prevHide).stop(!0,!0),this.prevShow=e,this.prevHide=i,this.options.animate?this._animate(e,i,t):(i.hide(),e.show(),this._toggleComplete(t)),i.attr({"aria-hidden":"true"}),i.prev().attr({"aria-selected":"false","aria-expanded":"false"}),e.length&&i.length?i.prev().attr({tabIndex:-1,"aria-expanded":"false"}):e.length&&this.headers.filter(function(){return 0===parseInt(V(this).attr("tabIndex"),10)}).attr("tabIndex",-1),e.attr("aria-hidden","false").prev().attr({"aria-selected":"true","aria-expanded":"true",tabIndex:0})},_animate:function(t,i,e){var s,n,o,a=this,r=0,l=t.css("box-sizing"),h=t.length&&(!i.length||t.index()",delay:300,options:{icons:{submenu:"ui-icon-caret-1-e"},items:"> *",menus:"ul",position:{my:"left top",at:"right top"},role:"menu",blur:null,focus:null,select:null},_create:function(){this.activeMenu=this.element,this.mouseHandled=!1,this.lastMousePosition={x:null,y:null},this.element.uniqueId().attr({role:this.options.role,tabIndex:0}),this._addClass("ui-menu","ui-widget ui-widget-content"),this._on({"mousedown .ui-menu-item":function(t){t.preventDefault(),this._activateItem(t)},"click .ui-menu-item":function(t){var e=V(t.target),i=V(V.ui.safeActiveElement(this.document[0]));!this.mouseHandled&&e.not(".ui-state-disabled").length&&(this.select(t),t.isPropagationStopped()||(this.mouseHandled=!0),e.has(".ui-menu").length?this.expand(t):!this.element.is(":focus")&&i.closest(".ui-menu").length&&(this.element.trigger("focus",[!0]),this.active&&1===this.active.parents(".ui-menu").length&&clearTimeout(this.timer)))},"mouseenter .ui-menu-item":"_activateItem","mousemove .ui-menu-item":"_activateItem",mouseleave:"collapseAll","mouseleave .ui-menu":"collapseAll",focus:function(t,e){var i=this.active||this._menuItems().first();e||this.focus(t,i)},blur:function(t){this._delay(function(){V.contains(this.element[0],V.ui.safeActiveElement(this.document[0]))||this.collapseAll(t)})},keydown:"_keydown"}),this.refresh(),this._on(this.document,{click:function(t){this._closeOnDocumentClick(t)&&this.collapseAll(t,!0),this.mouseHandled=!1}})},_activateItem:function(t){var e,i;this.previousFilter||t.clientX===this.lastMousePosition.x&&t.clientY===this.lastMousePosition.y||(this.lastMousePosition={x:t.clientX,y:t.clientY},e=V(t.target).closest(".ui-menu-item"),i=V(t.currentTarget),e[0]===i[0]&&(i.is(".ui-state-active")||(this._removeClass(i.siblings().children(".ui-state-active"),null,"ui-state-active"),this.focus(t,i))))},_destroy:function(){var t=this.element.find(".ui-menu-item").removeAttr("role aria-disabled").children(".ui-menu-item-wrapper").removeUniqueId().removeAttr("tabIndex role aria-haspopup");this.element.removeAttr("aria-activedescendant").find(".ui-menu").addBack().removeAttr("role aria-labelledby aria-expanded aria-hidden aria-disabled tabIndex").removeUniqueId().show(),t.children().each(function(){var t=V(this);t.data("ui-menu-submenu-caret")&&t.remove()})},_keydown:function(t){var e,i,s,n=!0;switch(t.keyCode){case V.ui.keyCode.PAGE_UP:this.previousPage(t);break;case V.ui.keyCode.PAGE_DOWN:this.nextPage(t);break;case V.ui.keyCode.HOME:this._move("first","first",t);break;case V.ui.keyCode.END:this._move("last","last",t);break;case V.ui.keyCode.UP:this.previous(t);break;case V.ui.keyCode.DOWN:this.next(t);break;case V.ui.keyCode.LEFT:this.collapse(t);break;case V.ui.keyCode.RIGHT:this.active&&!this.active.is(".ui-state-disabled")&&this.expand(t);break;case V.ui.keyCode.ENTER:case V.ui.keyCode.SPACE:this._activate(t);break;case V.ui.keyCode.ESCAPE:this.collapse(t);break;default:e=this.previousFilter||"",s=n=!1,i=96<=t.keyCode&&t.keyCode<=105?(t.keyCode-96).toString():String.fromCharCode(t.keyCode),clearTimeout(this.filterTimer),i===e?s=!0:i=e+i,e=this._filterMenuItems(i),(e=s&&-1!==e.index(this.active.next())?this.active.nextAll(".ui-menu-item"):e).length||(i=String.fromCharCode(t.keyCode),e=this._filterMenuItems(i)),e.length?(this.focus(t,e),this.previousFilter=i,this.filterTimer=this._delay(function(){delete this.previousFilter},1e3)):delete this.previousFilter}n&&t.preventDefault()},_activate:function(t){this.active&&!this.active.is(".ui-state-disabled")&&(this.active.children("[aria-haspopup='true']").length?this.expand(t):this.select(t))},refresh:function(){var t,e,s=this,n=this.options.icons.submenu,i=this.element.find(this.options.menus);this._toggleClass("ui-menu-icons",null,!!this.element.find(".ui-icon").length),e=i.filter(":not(.ui-menu)").hide().attr({role:this.options.role,"aria-hidden":"true","aria-expanded":"false"}).each(function(){var t=V(this),e=t.prev(),i=V("").data("ui-menu-submenu-caret",!0);s._addClass(i,"ui-menu-icon","ui-icon "+n),e.attr("aria-haspopup","true").prepend(i),t.attr("aria-labelledby",e.attr("id"))}),this._addClass(e,"ui-menu","ui-widget ui-widget-content ui-front"),(t=i.add(this.element).find(this.options.items)).not(".ui-menu-item").each(function(){var t=V(this);s._isDivider(t)&&s._addClass(t,"ui-menu-divider","ui-widget-content")}),i=(e=t.not(".ui-menu-item, .ui-menu-divider")).children().not(".ui-menu").uniqueId().attr({tabIndex:-1,role:this._itemRole()}),this._addClass(e,"ui-menu-item")._addClass(i,"ui-menu-item-wrapper"),t.filter(".ui-state-disabled").attr("aria-disabled","true"),this.active&&!V.contains(this.element[0],this.active[0])&&this.blur()},_itemRole:function(){return{menu:"menuitem",listbox:"option"}[this.options.role]},_setOption:function(t,e){var i;"icons"===t&&(i=this.element.find(".ui-menu-icon"),this._removeClass(i,null,this.options.icons.submenu)._addClass(i,null,e.submenu)),this._super(t,e)},_setOptionDisabled:function(t){this._super(t),this.element.attr("aria-disabled",String(t)),this._toggleClass(null,"ui-state-disabled",!!t)},focus:function(t,e){var i;this.blur(t,t&&"focus"===t.type),this._scrollIntoView(e),this.active=e.first(),i=this.active.children(".ui-menu-item-wrapper"),this._addClass(i,null,"ui-state-active"),this.options.role&&this.element.attr("aria-activedescendant",i.attr("id")),i=this.active.parent().closest(".ui-menu-item").children(".ui-menu-item-wrapper"),this._addClass(i,null,"ui-state-active"),t&&"keydown"===t.type?this._close():this.timer=this._delay(function(){this._close()},this.delay),(i=e.children(".ui-menu")).length&&t&&/^mouse/.test(t.type)&&this._startOpening(i),this.activeMenu=e.parent(),this._trigger("focus",t,{item:e})},_scrollIntoView:function(t){var e,i,s;this._hasScroll()&&(i=parseFloat(V.css(this.activeMenu[0],"borderTopWidth"))||0,s=parseFloat(V.css(this.activeMenu[0],"paddingTop"))||0,e=t.offset().top-this.activeMenu.offset().top-i-s,i=this.activeMenu.scrollTop(),s=this.activeMenu.height(),t=t.outerHeight(),e<0?this.activeMenu.scrollTop(i+e):s",options:{appendTo:null,autoFocus:!1,delay:300,minLength:1,position:{my:"left top",at:"left bottom",collision:"none"},source:null,change:null,close:null,focus:null,open:null,response:null,search:null,select:null},requestIndex:0,pending:0,liveRegionTimer:null,_create:function(){var i,s,n,t=this.element[0].nodeName.toLowerCase(),e="textarea"===t,t="input"===t;this.isMultiLine=e||!t&&this._isContentEditable(this.element),this.valueMethod=this.element[e||t?"val":"text"],this.isNewMenu=!0,this._addClass("ui-autocomplete-input"),this.element.attr("autocomplete","off"),this._on(this.element,{keydown:function(t){if(this.element.prop("readOnly"))s=n=i=!0;else{s=n=i=!1;var e=V.ui.keyCode;switch(t.keyCode){case e.PAGE_UP:i=!0,this._move("previousPage",t);break;case e.PAGE_DOWN:i=!0,this._move("nextPage",t);break;case e.UP:i=!0,this._keyEvent("previous",t);break;case e.DOWN:i=!0,this._keyEvent("next",t);break;case e.ENTER:this.menu.active&&(i=!0,t.preventDefault(),this.menu.select(t));break;case e.TAB:this.menu.active&&this.menu.select(t);break;case e.ESCAPE:this.menu.element.is(":visible")&&(this.isMultiLine||this._value(this.term),this.close(t),t.preventDefault());break;default:s=!0,this._searchTimeout(t)}}},keypress:function(t){if(i)return i=!1,void(this.isMultiLine&&!this.menu.element.is(":visible")||t.preventDefault());if(!s){var e=V.ui.keyCode;switch(t.keyCode){case e.PAGE_UP:this._move("previousPage",t);break;case e.PAGE_DOWN:this._move("nextPage",t);break;case e.UP:this._keyEvent("previous",t);break;case e.DOWN:this._keyEvent("next",t)}}},input:function(t){if(n)return n=!1,void t.preventDefault();this._searchTimeout(t)},focus:function(){this.selectedItem=null,this.previous=this._value()},blur:function(t){clearTimeout(this.searching),this.close(t),this._change(t)}}),this._initSource(),this.menu=V("
    ").appendTo(this._appendTo()).menu({role:null}).hide().attr({unselectable:"on"}).menu("instance"),this._addClass(this.menu.element,"ui-autocomplete","ui-front"),this._on(this.menu.element,{mousedown:function(t){t.preventDefault()},menufocus:function(t,e){var i,s;if(this.isNewMenu&&(this.isNewMenu=!1,t.originalEvent&&/^mouse/.test(t.originalEvent.type)))return this.menu.blur(),void this.document.one("mousemove",function(){V(t.target).trigger(t.originalEvent)});s=e.item.data("ui-autocomplete-item"),!1!==this._trigger("focus",t,{item:s})&&t.originalEvent&&/^key/.test(t.originalEvent.type)&&this._value(s.value),(i=e.item.attr("aria-label")||s.value)&&String.prototype.trim.call(i).length&&(clearTimeout(this.liveRegionTimer),this.liveRegionTimer=this._delay(function(){this.liveRegion.html(V("
    ").text(i))},100))},menuselect:function(t,e){var i=e.item.data("ui-autocomplete-item"),s=this.previous;this.element[0]!==V.ui.safeActiveElement(this.document[0])&&(this.element.trigger("focus"),this.previous=s,this._delay(function(){this.previous=s,this.selectedItem=i})),!1!==this._trigger("select",t,{item:i})&&this._value(i.value),this.term=this._value(),this.close(t),this.selectedItem=i}}),this.liveRegion=V("
    ",{role:"status","aria-live":"assertive","aria-relevant":"additions"}).appendTo(this.document[0].body),this._addClass(this.liveRegion,null,"ui-helper-hidden-accessible"),this._on(this.window,{beforeunload:function(){this.element.removeAttr("autocomplete")}})},_destroy:function(){clearTimeout(this.searching),this.element.removeAttr("autocomplete"),this.menu.element.remove(),this.liveRegion.remove()},_setOption:function(t,e){this._super(t,e),"source"===t&&this._initSource(),"appendTo"===t&&this.menu.element.appendTo(this._appendTo()),"disabled"===t&&e&&this.xhr&&this.xhr.abort()},_isEventTargetInWidget:function(t){var e=this.menu.element[0];return t.target===this.element[0]||t.target===e||V.contains(e,t.target)},_closeOnClickOutside:function(t){this._isEventTargetInWidget(t)||this.close()},_appendTo:function(){var t=this.options.appendTo;return t=!(t=!(t=t&&(t.jquery||t.nodeType?V(t):this.document.find(t).eq(0)))||!t[0]?this.element.closest(".ui-front, dialog"):t).length?this.document[0].body:t},_initSource:function(){var i,s,n=this;Array.isArray(this.options.source)?(i=this.options.source,this.source=function(t,e){e(V.ui.autocomplete.filter(i,t.term))}):"string"==typeof this.options.source?(s=this.options.source,this.source=function(t,e){n.xhr&&n.xhr.abort(),n.xhr=V.ajax({url:s,data:t,dataType:"json",success:function(t){e(t)},error:function(){e([])}})}):this.source=this.options.source},_searchTimeout:function(s){clearTimeout(this.searching),this.searching=this._delay(function(){var t=this.term===this._value(),e=this.menu.element.is(":visible"),i=s.altKey||s.ctrlKey||s.metaKey||s.shiftKey;t&&(e||i)||(this.selectedItem=null,this.search(null,s))},this.options.delay)},search:function(t,e){return t=null!=t?t:this._value(),this.term=this._value(),t.length").append(V("
    ").text(e.label)).appendTo(t)},_move:function(t,e){if(this.menu.element.is(":visible"))return this.menu.isFirstItem()&&/^previous/.test(t)||this.menu.isLastItem()&&/^next/.test(t)?(this.isMultiLine||this._value(this.term),void this.menu.blur()):void this.menu[t](e);this.search(null,e)},widget:function(){return this.menu.element},_value:function(){return this.valueMethod.apply(this.element,arguments)},_keyEvent:function(t,e){this.isMultiLine&&!this.menu.element.is(":visible")||(this._move(t,e),e.preventDefault())},_isContentEditable:function(t){if(!t.length)return!1;var e=t.prop("contentEditable");return"inherit"===e?this._isContentEditable(t.parent()):"true"===e}}),V.extend(V.ui.autocomplete,{escapeRegex:function(t){return t.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&")},filter:function(t,e){var i=new RegExp(V.ui.autocomplete.escapeRegex(e),"i");return V.grep(t,function(t){return i.test(t.label||t.value||t)})}}),V.widget("ui.autocomplete",V.ui.autocomplete,{options:{messages:{noResults:"No search results.",results:function(t){return t+(1").text(e))},100))}});V.ui.autocomplete;var tt=/ui-corner-([a-z]){2,6}/g;V.widget("ui.controlgroup",{version:"1.13.2",defaultElement:"
    ",options:{direction:"horizontal",disabled:null,onlyVisible:!0,items:{button:"input[type=button], input[type=submit], input[type=reset], button, a",controlgroupLabel:".ui-controlgroup-label",checkboxradio:"input[type='checkbox'], input[type='radio']",selectmenu:"select",spinner:".ui-spinner-input"}},_create:function(){this._enhance()},_enhance:function(){this.element.attr("role","toolbar"),this.refresh()},_destroy:function(){this._callChildMethod("destroy"),this.childWidgets.removeData("ui-controlgroup-data"),this.element.removeAttr("role"),this.options.items.controlgroupLabel&&this.element.find(this.options.items.controlgroupLabel).find(".ui-controlgroup-label-contents").contents().unwrap()},_initWidgets:function(){var o=this,a=[];V.each(this.options.items,function(s,t){var e,n={};if(t)return"controlgroupLabel"===s?((e=o.element.find(t)).each(function(){var t=V(this);t.children(".ui-controlgroup-label-contents").length||t.contents().wrapAll("")}),o._addClass(e,null,"ui-widget ui-widget-content ui-state-default"),void(a=a.concat(e.get()))):void(V.fn[s]&&(n=o["_"+s+"Options"]?o["_"+s+"Options"]("middle"):{classes:{}},o.element.find(t).each(function(){var t=V(this),e=t[s]("instance"),i=V.widget.extend({},n);"button"===s&&t.parent(".ui-spinner").length||((e=e||t[s]()[s]("instance"))&&(i.classes=o._resolveClassesValues(i.classes,e)),t[s](i),i=t[s]("widget"),V.data(i[0],"ui-controlgroup-data",e||t[s]("instance")),a.push(i[0]))})))}),this.childWidgets=V(V.uniqueSort(a)),this._addClass(this.childWidgets,"ui-controlgroup-item")},_callChildMethod:function(e){this.childWidgets.each(function(){var t=V(this).data("ui-controlgroup-data");t&&t[e]&&t[e]()})},_updateCornerClass:function(t,e){e=this._buildSimpleOptions(e,"label").classes.label;this._removeClass(t,null,"ui-corner-top ui-corner-bottom ui-corner-left ui-corner-right ui-corner-all"),this._addClass(t,null,e)},_buildSimpleOptions:function(t,e){var i="vertical"===this.options.direction,s={classes:{}};return s.classes[e]={middle:"",first:"ui-corner-"+(i?"top":"left"),last:"ui-corner-"+(i?"bottom":"right"),only:"ui-corner-all"}[t],s},_spinnerOptions:function(t){t=this._buildSimpleOptions(t,"ui-spinner");return t.classes["ui-spinner-up"]="",t.classes["ui-spinner-down"]="",t},_buttonOptions:function(t){return this._buildSimpleOptions(t,"ui-button")},_checkboxradioOptions:function(t){return this._buildSimpleOptions(t,"ui-checkboxradio-label")},_selectmenuOptions:function(t){var e="vertical"===this.options.direction;return{width:e&&"auto",classes:{middle:{"ui-selectmenu-button-open":"","ui-selectmenu-button-closed":""},first:{"ui-selectmenu-button-open":"ui-corner-"+(e?"top":"tl"),"ui-selectmenu-button-closed":"ui-corner-"+(e?"top":"left")},last:{"ui-selectmenu-button-open":e?"":"ui-corner-tr","ui-selectmenu-button-closed":"ui-corner-"+(e?"bottom":"right")},only:{"ui-selectmenu-button-open":"ui-corner-top","ui-selectmenu-button-closed":"ui-corner-all"}}[t]}},_resolveClassesValues:function(i,s){var n={};return V.each(i,function(t){var e=s.options.classes[t]||"",e=String.prototype.trim.call(e.replace(tt,""));n[t]=(e+" "+i[t]).replace(/\s+/g," ")}),n},_setOption:function(t,e){"direction"===t&&this._removeClass("ui-controlgroup-"+this.options.direction),this._super(t,e),"disabled"!==t?this.refresh():this._callChildMethod(e?"disable":"enable")},refresh:function(){var n,o=this;this._addClass("ui-controlgroup ui-controlgroup-"+this.options.direction),"horizontal"===this.options.direction&&this._addClass(null,"ui-helper-clearfix"),this._initWidgets(),n=this.childWidgets,(n=this.options.onlyVisible?n.filter(":visible"):n).length&&(V.each(["first","last"],function(t,e){var i,s=n[e]().data("ui-controlgroup-data");s&&o["_"+s.widgetName+"Options"]?((i=o["_"+s.widgetName+"Options"](1===n.length?"only":e)).classes=o._resolveClassesValues(i.classes,s),s.element[s.widgetName](i)):o._updateCornerClass(n[e](),e)}),this._callChildMethod("refresh"))}});V.widget("ui.checkboxradio",[V.ui.formResetMixin,{version:"1.13.2",options:{disabled:null,label:null,icon:!0,classes:{"ui-checkboxradio-label":"ui-corner-all","ui-checkboxradio-icon":"ui-corner-all"}},_getCreateOptions:function(){var t,e=this._super()||{};return this._readType(),t=this.element.labels(),this.label=V(t[t.length-1]),this.label.length||V.error("No label found for checkboxradio widget"),this.originalLabel="",(t=this.label.contents().not(this.element[0])).length&&(this.originalLabel+=t.clone().wrapAll("
    ").parent().html()),this.originalLabel&&(e.label=this.originalLabel),null!=(t=this.element[0].disabled)&&(e.disabled=t),e},_create:function(){var t=this.element[0].checked;this._bindFormResetHandler(),null==this.options.disabled&&(this.options.disabled=this.element[0].disabled),this._setOption("disabled",this.options.disabled),this._addClass("ui-checkboxradio","ui-helper-hidden-accessible"),this._addClass(this.label,"ui-checkboxradio-label","ui-button ui-widget"),"radio"===this.type&&this._addClass(this.label,"ui-checkboxradio-radio-label"),this.options.label&&this.options.label!==this.originalLabel?this._updateLabel():this.originalLabel&&(this.options.label=this.originalLabel),this._enhance(),t&&this._addClass(this.label,"ui-checkboxradio-checked","ui-state-active"),this._on({change:"_toggleClasses",focus:function(){this._addClass(this.label,null,"ui-state-focus ui-visual-focus")},blur:function(){this._removeClass(this.label,null,"ui-state-focus ui-visual-focus")}})},_readType:function(){var t=this.element[0].nodeName.toLowerCase();this.type=this.element[0].type,"input"===t&&/radio|checkbox/.test(this.type)||V.error("Can't create checkboxradio on element.nodeName="+t+" and element.type="+this.type)},_enhance:function(){this._updateIcon(this.element[0].checked)},widget:function(){return this.label},_getRadioGroup:function(){var t=this.element[0].name,e="input[name='"+V.escapeSelector(t)+"']";return t?(this.form.length?V(this.form[0].elements).filter(e):V(e).filter(function(){return 0===V(this)._form().length})).not(this.element):V([])},_toggleClasses:function(){var t=this.element[0].checked;this._toggleClass(this.label,"ui-checkboxradio-checked","ui-state-active",t),this.options.icon&&"checkbox"===this.type&&this._toggleClass(this.icon,null,"ui-icon-check ui-state-checked",t)._toggleClass(this.icon,null,"ui-icon-blank",!t),"radio"===this.type&&this._getRadioGroup().each(function(){var t=V(this).checkboxradio("instance");t&&t._removeClass(t.label,"ui-checkboxradio-checked","ui-state-active")})},_destroy:function(){this._unbindFormResetHandler(),this.icon&&(this.icon.remove(),this.iconSpace.remove())},_setOption:function(t,e){if("label"!==t||e){if(this._super(t,e),"disabled"===t)return this._toggleClass(this.label,null,"ui-state-disabled",e),void(this.element[0].disabled=e);this.refresh()}},_updateIcon:function(t){var e="ui-icon ui-icon-background ";this.options.icon?(this.icon||(this.icon=V(""),this.iconSpace=V(" "),this._addClass(this.iconSpace,"ui-checkboxradio-icon-space")),"checkbox"===this.type?(e+=t?"ui-icon-check ui-state-checked":"ui-icon-blank",this._removeClass(this.icon,null,t?"ui-icon-blank":"ui-icon-check")):e+="ui-icon-blank",this._addClass(this.icon,"ui-checkboxradio-icon",e),t||this._removeClass(this.icon,null,"ui-icon-check ui-state-checked"),this.icon.prependTo(this.label).after(this.iconSpace)):void 0!==this.icon&&(this.icon.remove(),this.iconSpace.remove(),delete this.icon)},_updateLabel:function(){var t=this.label.contents().not(this.element[0]);this.icon&&(t=t.not(this.icon[0])),(t=this.iconSpace?t.not(this.iconSpace[0]):t).remove(),this.label.append(this.options.label)},refresh:function(){var t=this.element[0].checked,e=this.element[0].disabled;this._updateIcon(t),this._toggleClass(this.label,"ui-checkboxradio-checked","ui-state-active",t),null!==this.options.label&&this._updateLabel(),e!==this.options.disabled&&this._setOptions({disabled:e})}}]);var et;V.ui.checkboxradio;V.widget("ui.button",{version:"1.13.2",defaultElement:"
{{ruleName}} ({{activeAlertsLength}} active) {{definition.name}} ({{activeAlertsLength}} active)
-
-
{{htmlSnippet}}
+
+
name: {{definition.name}}
+ + {{#definition.labels.length}} +
+ labels: + {{#definition.labels}} +
{{name}}: {{value}}
+ {{/definition.labels}} +
+ {{/definition.labels.length}} + {{#definition.annotations.length}} +
+ annotations: + {{#definition.annotations}} +
{{name}}: {{value}}
+ {{/definition.annotations}} +
+ {{/definition.annotations.length}}
- - {{#activeAlerts}} - - - - - - - - - - - - - - - - - - {{/activeAlerts}} - - - - - - + + + + + + + {{/activeAlerts}} +
LabelsStateWhenValue
- {{#Labels}} - {{key}}="{{value}}" - {{/Labels}} - {{stateName}} -
- Pending: - {{ActiveAt}} -
- {{#FiredAt}} -
- Fired: - {{FiredAt}} -
- {{/FiredAt}} - {{#ResolvedAt}} -
- Resolved: - {{ResolvedAt}} -
- {{/ResolvedAt}} -
{{Value}}
-
- {{#Annotations}} -
{{key}}
-
{{value}}
- {{/Annotations}} -
-
Graph
-
-
-
-
-
+
+
+
+
+
+
+ + + + + + + + + + + + + - - - - - - + + + {{#activeAlerts}} + + + + + + + + - - -
Graph
+
+
+
+
+
+
+
+
+
+ + +
+
+
+
+
+
+
-
-
-
-
-
-
-
- - -
-
+
+
Graph: 'ALERTS'
+
+
+
+
+
+
+
- -
Graph: 'ALERTS'
-
-
-
-
-
-
-
-
+
{{name}}
+ {{#Labels}} + {{key}}="{{value}}" + {{/Labels}} + {{stateName}} +
+ Pending: + {{ActiveAt}} +
+ {{#FiredAt}} +
+ Fired: + {{FiredAt}}
- -
+ {{/FiredAt}} + {{#ResolvedAt}} +
+ Resolved: + {{ResolvedAt}} +
+ {{/ResolvedAt}} +
+ Value: + {{Value}} +
+
+ {{#Annotations}} +
{{key}}
+
{{value}}
+ {{/Annotations}} +
+
+
",x=o?"":"",g=0;g<7;g++)x+="";for(w+=x+"",D=this._getDaysInMonth(U,K),U===t.selectedYear&&K===t.selectedMonth&&(t.selectedDay=Math.min(t.selectedDay,D)),C=(this._getFirstDayOfMonth(U,K)-n+7)%7,D=Math.ceil((C+D)/7),I=Y&&this.maxRows>D?this.maxRows:D,this.maxRows=I,T=this._daylightSavingAdjust(new Date(U,K,1-C)),P=0;P",M=o?"":"",g=0;g<7;g++)S=c?c.apply(t.input?t.input[0]:null,[T]):[!0,""],z=(H=T.getMonth()!==K)&&!d||!S[0]||j&&T"+(H&&!u?" ":z?""+T.getDate()+"":""+T.getDate()+"")+"",T.setDate(T.getDate()+1),T=this._daylightSavingAdjust(T);w+=M+""}11<++K&&(K=0,U++),_+=w+="
"+this._get(t,"weekHeader")+""+r[k]+"
"+this._get(t,"calculateWeek")(T)+"
"+(Y?"
"+(0":""):"")}f+=_}return f+=F,t._keyEvent=!1,f},_generateMonthYearHeader:function(t,e,i,s,n,o,a,r){var l,h,c,u,d,p,f=this._get(t,"changeMonth"),g=this._get(t,"changeYear"),m=this._get(t,"showMonthAfterYear"),_=this._get(t,"selectMonthLabel"),v=this._get(t,"selectYearLabel"),b="
",y="";if(o||!f)y+=""+a[e]+"";else{for(l=s&&s.getFullYear()===i,h=n&&n.getFullYear()===i,y+=""}if(m||(b+=y+(!o&&f&&g?"":" ")),!t.yearshtml)if(t.yearshtml="",o||!g)b+=""+i+"";else{for(a=this._get(t,"yearRange").split(":"),u=(new Date).getFullYear(),d=(_=function(t){t=t.match(/c[+\-].*/)?i+parseInt(t.substring(1),10):t.match(/[+\-].*/)?u+parseInt(t,10):parseInt(t,10);return isNaN(t)?u:t})(a[0]),p=Math.max(d,_(a[1]||"")),d=s?Math.max(d,s.getFullYear()):d,p=n?Math.min(p,n.getFullYear()):p,t.yearshtml+="",b+=t.yearshtml,t.yearshtml=null}return b+=this._get(t,"yearSuffix"),m&&(b+=(!o&&f&&g?"":" ")+y),b+="
"},_adjustInstDate:function(t,e,i){var s=t.selectedYear+("Y"===i?e:0),n=t.selectedMonth+("M"===i?e:0),e=Math.min(t.selectedDay,this._getDaysInMonth(s,n))+("D"===i?e:0),e=this._restrictMinMax(t,this._daylightSavingAdjust(new Date(s,n,e)));t.selectedDay=e.getDate(),t.drawMonth=t.selectedMonth=e.getMonth(),t.drawYear=t.selectedYear=e.getFullYear(),"M"!==i&&"Y"!==i||this._notifyChange(t)},_restrictMinMax:function(t,e){var i=this._getMinMaxDate(t,"min"),t=this._getMinMaxDate(t,"max"),e=i&&e=i.getTime())&&(!s||e.getTime()<=s.getTime())&&(!n||e.getFullYear()>=n)&&(!o||e.getFullYear()<=o)},_getFormatConfig:function(t){var e=this._get(t,"shortYearCutoff");return{shortYearCutoff:e="string"!=typeof e?e:(new Date).getFullYear()%100+parseInt(e,10),dayNamesShort:this._get(t,"dayNamesShort"),dayNames:this._get(t,"dayNames"),monthNamesShort:this._get(t,"monthNamesShort"),monthNames:this._get(t,"monthNames")}},_formatDate:function(t,e,i,s){e||(t.currentDay=t.selectedDay,t.currentMonth=t.selectedMonth,t.currentYear=t.selectedYear);e=e?"object"==typeof e?e:this._daylightSavingAdjust(new Date(s,i,e)):this._daylightSavingAdjust(new Date(t.currentYear,t.currentMonth,t.currentDay));return this.formatDate(this._get(t,"dateFormat"),e,this._getFormatConfig(t))}}),V.fn.datepicker=function(t){if(!this.length)return this;V.datepicker.initialized||(V(document).on("mousedown",V.datepicker._checkExternalClick),V.datepicker.initialized=!0),0===V("#"+V.datepicker._mainDivId).length&&V("body").append(V.datepicker.dpDiv);var e=Array.prototype.slice.call(arguments,1);return"string"==typeof t&&("isDisabled"===t||"getDate"===t||"widget"===t)||"option"===t&&2===arguments.length&&"string"==typeof arguments[1]?V.datepicker["_"+t+"Datepicker"].apply(V.datepicker,[this[0]].concat(e)):this.each(function(){"string"==typeof t?V.datepicker["_"+t+"Datepicker"].apply(V.datepicker,[this].concat(e)):V.datepicker._attachDatepicker(this,t)})},V.datepicker=new st,V.datepicker.initialized=!1,V.datepicker.uuid=(new Date).getTime(),V.datepicker.version="1.13.2";V.datepicker,V.ui.ie=!!/msie [\w.]+/.exec(navigator.userAgent.toLowerCase());var rt=!1;V(document).on("mouseup",function(){rt=!1});V.widget("ui.mouse",{version:"1.13.2",options:{cancel:"input, textarea, button, select, option",distance:1,delay:0},_mouseInit:function(){var e=this;this.element.on("mousedown."+this.widgetName,function(t){return e._mouseDown(t)}).on("click."+this.widgetName,function(t){if(!0===V.data(t.target,e.widgetName+".preventClickEvent"))return V.removeData(t.target,e.widgetName+".preventClickEvent"),t.stopImmediatePropagation(),!1}),this.started=!1},_mouseDestroy:function(){this.element.off("."+this.widgetName),this._mouseMoveDelegate&&this.document.off("mousemove."+this.widgetName,this._mouseMoveDelegate).off("mouseup."+this.widgetName,this._mouseUpDelegate)},_mouseDown:function(t){if(!rt){this._mouseMoved=!1,this._mouseStarted&&this._mouseUp(t),this._mouseDownEvent=t;var e=this,i=1===t.which,s=!("string"!=typeof this.options.cancel||!t.target.nodeName)&&V(t.target).closest(this.options.cancel).length;return i&&!s&&this._mouseCapture(t)?(this.mouseDelayMet=!this.options.delay,this.mouseDelayMet||(this._mouseDelayTimer=setTimeout(function(){e.mouseDelayMet=!0},this.options.delay)),this._mouseDistanceMet(t)&&this._mouseDelayMet(t)&&(this._mouseStarted=!1!==this._mouseStart(t),!this._mouseStarted)?(t.preventDefault(),!0):(!0===V.data(t.target,this.widgetName+".preventClickEvent")&&V.removeData(t.target,this.widgetName+".preventClickEvent"),this._mouseMoveDelegate=function(t){return e._mouseMove(t)},this._mouseUpDelegate=function(t){return e._mouseUp(t)},this.document.on("mousemove."+this.widgetName,this._mouseMoveDelegate).on("mouseup."+this.widgetName,this._mouseUpDelegate),t.preventDefault(),rt=!0)):!0}},_mouseMove:function(t){if(this._mouseMoved){if(V.ui.ie&&(!document.documentMode||document.documentMode<9)&&!t.button)return this._mouseUp(t);if(!t.which)if(t.originalEvent.altKey||t.originalEvent.ctrlKey||t.originalEvent.metaKey||t.originalEvent.shiftKey)this.ignoreMissingWhich=!0;else if(!this.ignoreMissingWhich)return this._mouseUp(t)}return(t.which||t.button)&&(this._mouseMoved=!0),this._mouseStarted?(this._mouseDrag(t),t.preventDefault()):(this._mouseDistanceMet(t)&&this._mouseDelayMet(t)&&(this._mouseStarted=!1!==this._mouseStart(this._mouseDownEvent,t),this._mouseStarted?this._mouseDrag(t):this._mouseUp(t)),!this._mouseStarted)},_mouseUp:function(t){this.document.off("mousemove."+this.widgetName,this._mouseMoveDelegate).off("mouseup."+this.widgetName,this._mouseUpDelegate),this._mouseStarted&&(this._mouseStarted=!1,t.target===this._mouseDownEvent.target&&V.data(t.target,this.widgetName+".preventClickEvent",!0),this._mouseStop(t)),this._mouseDelayTimer&&(clearTimeout(this._mouseDelayTimer),delete this._mouseDelayTimer),this.ignoreMissingWhich=!1,rt=!1,t.preventDefault()},_mouseDistanceMet:function(t){return Math.max(Math.abs(this._mouseDownEvent.pageX-t.pageX),Math.abs(this._mouseDownEvent.pageY-t.pageY))>=this.options.distance},_mouseDelayMet:function(){return this.mouseDelayMet},_mouseStart:function(){},_mouseDrag:function(){},_mouseStop:function(){},_mouseCapture:function(){return!0}}),V.ui.plugin={add:function(t,e,i){var s,n=V.ui[t].prototype;for(s in i)n.plugins[s]=n.plugins[s]||[],n.plugins[s].push([e,i[s]])},call:function(t,e,i,s){var n,o=t.plugins[e];if(o&&(s||t.element[0].parentNode&&11!==t.element[0].parentNode.nodeType))for(n=0;n").css("position","absolute").appendTo(t.parent()).outerWidth(t.outerWidth()).outerHeight(t.outerHeight()).offset(t.offset())[0]})},_unblockFrames:function(){this.iframeBlocks&&(this.iframeBlocks.remove(),delete this.iframeBlocks)},_blurActiveElement:function(t){var e=V.ui.safeActiveElement(this.document[0]);V(t.target).closest(e).length||V.ui.safeBlur(e)},_mouseStart:function(t){var e=this.options;return this.helper=this._createHelper(t),this._addClass(this.helper,"ui-draggable-dragging"),this._cacheHelperProportions(),V.ui.ddmanager&&(V.ui.ddmanager.current=this),this._cacheMargins(),this.cssPosition=this.helper.css("position"),this.scrollParent=this.helper.scrollParent(!0),this.offsetParent=this.helper.offsetParent(),this.hasFixedAncestor=0i[2]&&(o=i[2]+this.offset.click.left),t.pageY-this.offset.click.top>i[3]&&(a=i[3]+this.offset.click.top)),s.grid&&(t=s.grid[1]?this.originalPageY+Math.round((a-this.originalPageY)/s.grid[1])*s.grid[1]:this.originalPageY,a=!i||t-this.offset.click.top>=i[1]||t-this.offset.click.top>i[3]?t:t-this.offset.click.top>=i[1]?t-s.grid[1]:t+s.grid[1],t=s.grid[0]?this.originalPageX+Math.round((o-this.originalPageX)/s.grid[0])*s.grid[0]:this.originalPageX,o=!i||t-this.offset.click.left>=i[0]||t-this.offset.click.left>i[2]?t:t-this.offset.click.left>=i[0]?t-s.grid[0]:t+s.grid[0]),"y"===s.axis&&(o=this.originalPageX),"x"===s.axis&&(a=this.originalPageY)),{top:a-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+("fixed"===this.cssPosition?-this.offset.scroll.top:n?0:this.offset.scroll.top),left:o-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+("fixed"===this.cssPosition?-this.offset.scroll.left:n?0:this.offset.scroll.left)}},_clear:function(){this._removeClass(this.helper,"ui-draggable-dragging"),this.helper[0]===this.element[0]||this.cancelHelperRemoval||this.helper.remove(),this.helper=null,this.cancelHelperRemoval=!1,this.destroyOnClear&&this.destroy()},_trigger:function(t,e,i){return i=i||this._uiHash(),V.ui.plugin.call(this,t,[e,i,this],!0),/^(drag|start|stop)/.test(t)&&(this.positionAbs=this._convertPositionTo("absolute"),i.offset=this.positionAbs),V.Widget.prototype._trigger.call(this,t,e,i)},plugins:{},_uiHash:function(){return{helper:this.helper,position:this.position,originalPosition:this.originalPosition,offset:this.positionAbs}}}),V.ui.plugin.add("draggable","connectToSortable",{start:function(e,t,i){var s=V.extend({},t,{item:i.element});i.sortables=[],V(i.options.connectToSortable).each(function(){var t=V(this).sortable("instance");t&&!t.options.disabled&&(i.sortables.push(t),t.refreshPositions(),t._trigger("activate",e,s))})},stop:function(e,t,i){var s=V.extend({},t,{item:i.element});i.cancelHelperRemoval=!1,V.each(i.sortables,function(){var t=this;t.isOver?(t.isOver=0,i.cancelHelperRemoval=!0,t.cancelHelperRemoval=!1,t._storedCSS={position:t.placeholder.css("position"),top:t.placeholder.css("top"),left:t.placeholder.css("left")},t._mouseStop(e),t.options.helper=t.options._helper):(t.cancelHelperRemoval=!0,t._trigger("deactivate",e,s))})},drag:function(i,s,n){V.each(n.sortables,function(){var t=!1,e=this;e.positionAbs=n.positionAbs,e.helperProportions=n.helperProportions,e.offset.click=n.offset.click,e._intersectsWith(e.containerCache)&&(t=!0,V.each(n.sortables,function(){return this.positionAbs=n.positionAbs,this.helperProportions=n.helperProportions,this.offset.click=n.offset.click,t=this!==e&&this._intersectsWith(this.containerCache)&&V.contains(e.element[0],this.element[0])?!1:t})),t?(e.isOver||(e.isOver=1,n._parent=s.helper.parent(),e.currentItem=s.helper.appendTo(e.element).data("ui-sortable-item",!0),e.options._helper=e.options.helper,e.options.helper=function(){return s.helper[0]},i.target=e.currentItem[0],e._mouseCapture(i,!0),e._mouseStart(i,!0,!0),e.offset.click.top=n.offset.click.top,e.offset.click.left=n.offset.click.left,e.offset.parent.left-=n.offset.parent.left-e.offset.parent.left,e.offset.parent.top-=n.offset.parent.top-e.offset.parent.top,n._trigger("toSortable",i),n.dropped=e.element,V.each(n.sortables,function(){this.refreshPositions()}),n.currentItem=n.element,e.fromOutside=n),e.currentItem&&(e._mouseDrag(i),s.position=e.position)):e.isOver&&(e.isOver=0,e.cancelHelperRemoval=!0,e.options._revert=e.options.revert,e.options.revert=!1,e._trigger("out",i,e._uiHash(e)),e._mouseStop(i,!0),e.options.revert=e.options._revert,e.options.helper=e.options._helper,e.placeholder&&e.placeholder.remove(),s.helper.appendTo(n._parent),n._refreshOffsets(i),s.position=n._generatePosition(i,!0),n._trigger("fromSortable",i),n.dropped=!1,V.each(n.sortables,function(){this.refreshPositions()}))})}}),V.ui.plugin.add("draggable","cursor",{start:function(t,e,i){var s=V("body"),i=i.options;s.css("cursor")&&(i._cursor=s.css("cursor")),s.css("cursor",i.cursor)},stop:function(t,e,i){i=i.options;i._cursor&&V("body").css("cursor",i._cursor)}}),V.ui.plugin.add("draggable","opacity",{start:function(t,e,i){e=V(e.helper),i=i.options;e.css("opacity")&&(i._opacity=e.css("opacity")),e.css("opacity",i.opacity)},stop:function(t,e,i){i=i.options;i._opacity&&V(e.helper).css("opacity",i._opacity)}}),V.ui.plugin.add("draggable","scroll",{start:function(t,e,i){i.scrollParentNotHidden||(i.scrollParentNotHidden=i.helper.scrollParent(!1)),i.scrollParentNotHidden[0]!==i.document[0]&&"HTML"!==i.scrollParentNotHidden[0].tagName&&(i.overflowOffset=i.scrollParentNotHidden.offset())},drag:function(t,e,i){var s=i.options,n=!1,o=i.scrollParentNotHidden[0],a=i.document[0];o!==a&&"HTML"!==o.tagName?(s.axis&&"x"===s.axis||(i.overflowOffset.top+o.offsetHeight-t.pageY").css({overflow:"hidden",position:this.element.css("position"),width:this.element.outerWidth(),height:this.element.outerHeight(),top:this.element.css("top"),left:this.element.css("left")})),this.element=this.element.parent().data("ui-resizable",this.element.resizable("instance")),this.elementIsWrapper=!0,t={marginTop:this.originalElement.css("marginTop"),marginRight:this.originalElement.css("marginRight"),marginBottom:this.originalElement.css("marginBottom"),marginLeft:this.originalElement.css("marginLeft")},this.element.css(t),this.originalElement.css("margin",0),this.originalResizeStyle=this.originalElement.css("resize"),this.originalElement.css("resize","none"),this._proportionallyResizeElements.push(this.originalElement.css({position:"static",zoom:1,display:"block"})),this.originalElement.css(t),this._proportionallyResize()),this._setupHandles(),e.autoHide&&V(this.element).on("mouseenter",function(){e.disabled||(i._removeClass("ui-resizable-autohide"),i._handles.show())}).on("mouseleave",function(){e.disabled||i.resizing||(i._addClass("ui-resizable-autohide"),i._handles.hide())}),this._mouseInit()},_destroy:function(){this._mouseDestroy(),this._addedHandles.remove();function t(t){V(t).removeData("resizable").removeData("ui-resizable").off(".resizable")}var e;return this.elementIsWrapper&&(t(this.element),e=this.element,this.originalElement.css({position:e.css("position"),width:e.outerWidth(),height:e.outerHeight(),top:e.css("top"),left:e.css("left")}).insertAfter(e),e.remove()),this.originalElement.css("resize",this.originalResizeStyle),t(this.originalElement),this},_setOption:function(t,e){switch(this._super(t,e),t){case"handles":this._removeHandles(),this._setupHandles();break;case"aspectRatio":this._aspectRatio=!!e}},_setupHandles:function(){var t,e,i,s,n,o=this.options,a=this;if(this.handles=o.handles||(V(".ui-resizable-handle",this.element).length?{n:".ui-resizable-n",e:".ui-resizable-e",s:".ui-resizable-s",w:".ui-resizable-w",se:".ui-resizable-se",sw:".ui-resizable-sw",ne:".ui-resizable-ne",nw:".ui-resizable-nw"}:"e,s,se"),this._handles=V(),this._addedHandles=V(),this.handles.constructor===String)for("all"===this.handles&&(this.handles="n,e,s,w,se,sw,ne,nw"),i=this.handles.split(","),this.handles={},e=0;e"),this._addClass(n,"ui-resizable-handle "+s),n.css({zIndex:o.zIndex}),this.handles[t]=".ui-resizable-"+t,this.element.children(this.handles[t]).length||(this.element.append(n),this._addedHandles=this._addedHandles.add(n));this._renderAxis=function(t){var e,i,s;for(e in t=t||this.element,this.handles)this.handles[e].constructor===String?this.handles[e]=this.element.children(this.handles[e]).first().show():(this.handles[e].jquery||this.handles[e].nodeType)&&(this.handles[e]=V(this.handles[e]),this._on(this.handles[e],{mousedown:a._mouseDown})),this.elementIsWrapper&&this.originalElement[0].nodeName.match(/^(textarea|input|select|button)$/i)&&(i=V(this.handles[e],this.element),s=/sw|ne|nw|se|n|s/.test(e)?i.outerHeight():i.outerWidth(),i=["padding",/ne|nw|n/.test(e)?"Top":/se|sw|s/.test(e)?"Bottom":/^e$/.test(e)?"Right":"Left"].join(""),t.css(i,s),this._proportionallyResize()),this._handles=this._handles.add(this.handles[e])},this._renderAxis(this.element),this._handles=this._handles.add(this.element.find(".ui-resizable-handle")),this._handles.disableSelection(),this._handles.on("mouseover",function(){a.resizing||(this.className&&(n=this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i)),a.axis=n&&n[1]?n[1]:"se")}),o.autoHide&&(this._handles.hide(),this._addClass("ui-resizable-autohide"))},_removeHandles:function(){this._addedHandles.remove()},_mouseCapture:function(t){var e,i,s=!1;for(e in this.handles)(i=V(this.handles[e])[0])!==t.target&&!V.contains(i,t.target)||(s=!0);return!this.options.disabled&&s},_mouseStart:function(t){var e,i,s=this.options,n=this.element;return this.resizing=!0,this._renderProxy(),e=this._num(this.helper.css("left")),i=this._num(this.helper.css("top")),s.containment&&(e+=V(s.containment).scrollLeft()||0,i+=V(s.containment).scrollTop()||0),this.offset=this.helper.offset(),this.position={left:e,top:i},this.size=this._helper?{width:this.helper.width(),height:this.helper.height()}:{width:n.width(),height:n.height()},this.originalSize=this._helper?{width:n.outerWidth(),height:n.outerHeight()}:{width:n.width(),height:n.height()},this.sizeDiff={width:n.outerWidth()-n.width(),height:n.outerHeight()-n.height()},this.originalPosition={left:e,top:i},this.originalMousePosition={left:t.pageX,top:t.pageY},this.aspectRatio="number"==typeof s.aspectRatio?s.aspectRatio:this.originalSize.width/this.originalSize.height||1,s=V(".ui-resizable-"+this.axis).css("cursor"),V("body").css("cursor","auto"===s?this.axis+"-resize":s),this._addClass("ui-resizable-resizing"),this._propagate("start",t),!0},_mouseDrag:function(t){var e=this.originalMousePosition,i=this.axis,s=t.pageX-e.left||0,e=t.pageY-e.top||0,i=this._change[i];return this._updatePrevProperties(),i&&(e=i.apply(this,[t,s,e]),this._updateVirtualBoundaries(t.shiftKey),(this._aspectRatio||t.shiftKey)&&(e=this._updateRatio(e,t)),e=this._respectSize(e,t),this._updateCache(e),this._propagate("resize",t),e=this._applyChanges(),!this._helper&&this._proportionallyResizeElements.length&&this._proportionallyResize(),V.isEmptyObject(e)||(this._updatePrevProperties(),this._trigger("resize",t,this.ui()),this._applyChanges())),!1},_mouseStop:function(t){this.resizing=!1;var e,i,s,n=this.options,o=this;return this._helper&&(s=(e=(i=this._proportionallyResizeElements).length&&/textarea/i.test(i[0].nodeName))&&this._hasScroll(i[0],"left")?0:o.sizeDiff.height,i=e?0:o.sizeDiff.width,e={width:o.helper.width()-i,height:o.helper.height()-s},i=parseFloat(o.element.css("left"))+(o.position.left-o.originalPosition.left)||null,s=parseFloat(o.element.css("top"))+(o.position.top-o.originalPosition.top)||null,n.animate||this.element.css(V.extend(e,{top:s,left:i})),o.helper.height(o.size.height),o.helper.width(o.size.width),this._helper&&!n.animate&&this._proportionallyResize()),V("body").css("cursor","auto"),this._removeClass("ui-resizable-resizing"),this._propagate("stop",t),this._helper&&this.helper.remove(),!1},_updatePrevProperties:function(){this.prevPosition={top:this.position.top,left:this.position.left},this.prevSize={width:this.size.width,height:this.size.height}},_applyChanges:function(){var t={};return this.position.top!==this.prevPosition.top&&(t.top=this.position.top+"px"),this.position.left!==this.prevPosition.left&&(t.left=this.position.left+"px"),this.size.width!==this.prevSize.width&&(t.width=this.size.width+"px"),this.size.height!==this.prevSize.height&&(t.height=this.size.height+"px"),this.helper.css(t),t},_updateVirtualBoundaries:function(t){var e,i,s=this.options,n={minWidth:this._isNumber(s.minWidth)?s.minWidth:0,maxWidth:this._isNumber(s.maxWidth)?s.maxWidth:1/0,minHeight:this._isNumber(s.minHeight)?s.minHeight:0,maxHeight:this._isNumber(s.maxHeight)?s.maxHeight:1/0};(this._aspectRatio||t)&&(e=n.minHeight*this.aspectRatio,i=n.minWidth/this.aspectRatio,s=n.maxHeight*this.aspectRatio,t=n.maxWidth/this.aspectRatio,e>n.minWidth&&(n.minWidth=e),i>n.minHeight&&(n.minHeight=i),st.width,a=this._isNumber(t.height)&&e.minHeight&&e.minHeight>t.height,r=this.originalPosition.left+this.originalSize.width,l=this.originalPosition.top+this.originalSize.height,h=/sw|nw|w/.test(i),i=/nw|ne|n/.test(i);return o&&(t.width=e.minWidth),a&&(t.height=e.minHeight),s&&(t.width=e.maxWidth),n&&(t.height=e.maxHeight),o&&h&&(t.left=r-e.minWidth),s&&h&&(t.left=r-e.maxWidth),a&&i&&(t.top=l-e.minHeight),n&&i&&(t.top=l-e.maxHeight),t.width||t.height||t.left||!t.top?t.width||t.height||t.top||!t.left||(t.left=null):t.top=null,t},_getPaddingPlusBorderDimensions:function(t){for(var e=0,i=[],s=[t.css("borderTopWidth"),t.css("borderRightWidth"),t.css("borderBottomWidth"),t.css("borderLeftWidth")],n=[t.css("paddingTop"),t.css("paddingRight"),t.css("paddingBottom"),t.css("paddingLeft")];e<4;e++)i[e]=parseFloat(s[e])||0,i[e]+=parseFloat(n[e])||0;return{height:i[0]+i[2],width:i[1]+i[3]}},_proportionallyResize:function(){if(this._proportionallyResizeElements.length)for(var t,e=0,i=this.helper||this.element;e").css({overflow:"hidden"}),this._addClass(this.helper,this._helper),this.helper.css({width:this.element.outerWidth(),height:this.element.outerHeight(),position:"absolute",left:this.elementOffset.left+"px",top:this.elementOffset.top+"px",zIndex:++e.zIndex}),this.helper.appendTo("body").disableSelection()):this.helper=this.element},_change:{e:function(t,e){return{width:this.originalSize.width+e}},w:function(t,e){var i=this.originalSize;return{left:this.originalPosition.left+e,width:i.width-e}},n:function(t,e,i){var s=this.originalSize;return{top:this.originalPosition.top+i,height:s.height-i}},s:function(t,e,i){return{height:this.originalSize.height+i}},se:function(t,e,i){return V.extend(this._change.s.apply(this,arguments),this._change.e.apply(this,[t,e,i]))},sw:function(t,e,i){return V.extend(this._change.s.apply(this,arguments),this._change.w.apply(this,[t,e,i]))},ne:function(t,e,i){return V.extend(this._change.n.apply(this,arguments),this._change.e.apply(this,[t,e,i]))},nw:function(t,e,i){return V.extend(this._change.n.apply(this,arguments),this._change.w.apply(this,[t,e,i]))}},_propagate:function(t,e){V.ui.plugin.call(this,t,[e,this.ui()]),"resize"!==t&&this._trigger(t,e,this.ui())},plugins:{},ui:function(){return{originalElement:this.originalElement,element:this.element,helper:this.helper,position:this.position,size:this.size,originalSize:this.originalSize,originalPosition:this.originalPosition}}}),V.ui.plugin.add("resizable","animate",{stop:function(e){var i=V(this).resizable("instance"),t=i.options,s=i._proportionallyResizeElements,n=s.length&&/textarea/i.test(s[0].nodeName),o=n&&i._hasScroll(s[0],"left")?0:i.sizeDiff.height,a=n?0:i.sizeDiff.width,n={width:i.size.width-a,height:i.size.height-o},a=parseFloat(i.element.css("left"))+(i.position.left-i.originalPosition.left)||null,o=parseFloat(i.element.css("top"))+(i.position.top-i.originalPosition.top)||null;i.element.animate(V.extend(n,o&&a?{top:o,left:a}:{}),{duration:t.animateDuration,easing:t.animateEasing,step:function(){var t={width:parseFloat(i.element.css("width")),height:parseFloat(i.element.css("height")),top:parseFloat(i.element.css("top")),left:parseFloat(i.element.css("left"))};s&&s.length&&V(s[0]).css({width:t.width,height:t.height}),i._updateCache(t),i._propagate("resize",e)}})}}),V.ui.plugin.add("resizable","containment",{start:function(){var i,s,n=V(this).resizable("instance"),t=n.options,e=n.element,o=t.containment,a=o instanceof V?o.get(0):/parent/.test(o)?e.parent().get(0):o;a&&(n.containerElement=V(a),/document/.test(o)||o===document?(n.containerOffset={left:0,top:0},n.containerPosition={left:0,top:0},n.parentData={element:V(document),left:0,top:0,width:V(document).width(),height:V(document).height()||document.body.parentNode.scrollHeight}):(i=V(a),s=[],V(["Top","Right","Left","Bottom"]).each(function(t,e){s[t]=n._num(i.css("padding"+e))}),n.containerOffset=i.offset(),n.containerPosition=i.position(),n.containerSize={height:i.innerHeight()-s[3],width:i.innerWidth()-s[1]},t=n.containerOffset,e=n.containerSize.height,o=n.containerSize.width,o=n._hasScroll(a,"left")?a.scrollWidth:o,e=n._hasScroll(a)?a.scrollHeight:e,n.parentData={element:a,left:t.left,top:t.top,width:o,height:e}))},resize:function(t){var e=V(this).resizable("instance"),i=e.options,s=e.containerOffset,n=e.position,o=e._aspectRatio||t.shiftKey,a={top:0,left:0},r=e.containerElement,t=!0;r[0]!==document&&/static/.test(r.css("position"))&&(a=s),n.left<(e._helper?s.left:0)&&(e.size.width=e.size.width+(e._helper?e.position.left-s.left:e.position.left-a.left),o&&(e.size.height=e.size.width/e.aspectRatio,t=!1),e.position.left=i.helper?s.left:0),n.top<(e._helper?s.top:0)&&(e.size.height=e.size.height+(e._helper?e.position.top-s.top:e.position.top),o&&(e.size.width=e.size.height*e.aspectRatio,t=!1),e.position.top=e._helper?s.top:0),i=e.containerElement.get(0)===e.element.parent().get(0),n=/relative|absolute/.test(e.containerElement.css("position")),i&&n?(e.offset.left=e.parentData.left+e.position.left,e.offset.top=e.parentData.top+e.position.top):(e.offset.left=e.element.offset().left,e.offset.top=e.element.offset().top),n=Math.abs(e.sizeDiff.width+(e._helper?e.offset.left-a.left:e.offset.left-s.left)),s=Math.abs(e.sizeDiff.height+(e._helper?e.offset.top-a.top:e.offset.top-s.top)),n+e.size.width>=e.parentData.width&&(e.size.width=e.parentData.width-n,o&&(e.size.height=e.size.width/e.aspectRatio,t=!1)),s+e.size.height>=e.parentData.height&&(e.size.height=e.parentData.height-s,o&&(e.size.width=e.size.height*e.aspectRatio,t=!1)),t||(e.position.left=e.prevPosition.left,e.position.top=e.prevPosition.top,e.size.width=e.prevSize.width,e.size.height=e.prevSize.height)},stop:function(){var t=V(this).resizable("instance"),e=t.options,i=t.containerOffset,s=t.containerPosition,n=t.containerElement,o=V(t.helper),a=o.offset(),r=o.outerWidth()-t.sizeDiff.width,o=o.outerHeight()-t.sizeDiff.height;t._helper&&!e.animate&&/relative/.test(n.css("position"))&&V(this).css({left:a.left-s.left-i.left,width:r,height:o}),t._helper&&!e.animate&&/static/.test(n.css("position"))&&V(this).css({left:a.left-s.left-i.left,width:r,height:o})}}),V.ui.plugin.add("resizable","alsoResize",{start:function(){var t=V(this).resizable("instance").options;V(t.alsoResize).each(function(){var t=V(this);t.data("ui-resizable-alsoresize",{width:parseFloat(t.width()),height:parseFloat(t.height()),left:parseFloat(t.css("left")),top:parseFloat(t.css("top"))})})},resize:function(t,i){var e=V(this).resizable("instance"),s=e.options,n=e.originalSize,o=e.originalPosition,a={height:e.size.height-n.height||0,width:e.size.width-n.width||0,top:e.position.top-o.top||0,left:e.position.left-o.left||0};V(s.alsoResize).each(function(){var t=V(this),s=V(this).data("ui-resizable-alsoresize"),n={},e=t.parents(i.originalElement[0]).length?["width","height"]:["width","height","top","left"];V.each(e,function(t,e){var i=(s[e]||0)+(a[e]||0);i&&0<=i&&(n[e]=i||null)}),t.css(n)})},stop:function(){V(this).removeData("ui-resizable-alsoresize")}}),V.ui.plugin.add("resizable","ghost",{start:function(){var t=V(this).resizable("instance"),e=t.size;t.ghost=t.originalElement.clone(),t.ghost.css({opacity:.25,display:"block",position:"relative",height:e.height,width:e.width,margin:0,left:0,top:0}),t._addClass(t.ghost,"ui-resizable-ghost"),!1!==V.uiBackCompat&&"string"==typeof t.options.ghost&&t.ghost.addClass(this.options.ghost),t.ghost.appendTo(t.helper)},resize:function(){var t=V(this).resizable("instance");t.ghost&&t.ghost.css({position:"relative",height:t.size.height,width:t.size.width})},stop:function(){var t=V(this).resizable("instance");t.ghost&&t.helper&&t.helper.get(0).removeChild(t.ghost.get(0))}}),V.ui.plugin.add("resizable","grid",{resize:function(){var t,e=V(this).resizable("instance"),i=e.options,s=e.size,n=e.originalSize,o=e.originalPosition,a=e.axis,r="number"==typeof i.grid?[i.grid,i.grid]:i.grid,l=r[0]||1,h=r[1]||1,c=Math.round((s.width-n.width)/l)*l,u=Math.round((s.height-n.height)/h)*h,d=n.width+c,p=n.height+u,f=i.maxWidth&&i.maxWidthd,s=i.minHeight&&i.minHeight>p;i.grid=r,m&&(d+=l),s&&(p+=h),f&&(d-=l),g&&(p-=h),/^(se|s|e)$/.test(a)?(e.size.width=d,e.size.height=p):/^(ne)$/.test(a)?(e.size.width=d,e.size.height=p,e.position.top=o.top-u):/^(sw)$/.test(a)?(e.size.width=d,e.size.height=p,e.position.left=o.left-c):((p-h<=0||d-l<=0)&&(t=e._getPaddingPlusBorderDimensions(this)),0=+this.uiDialog.css("z-index")&&(this.uiDialog.css("z-index",s+1),i=!0),i&&!e&&this._trigger("focus",t),i},open:function(){var t=this;this._isOpen?this._moveToTop()&&this._focusTabbable():(this._isOpen=!0,this.opener=V(V.ui.safeActiveElement(this.document[0])),this._size(),this._position(),this._createOverlay(),this._moveToTop(null,!0),this.overlay&&this.overlay.css("z-index",this.uiDialog.css("z-index")-1),this._show(this.uiDialog,this.options.show,function(){t._focusTabbable(),t._trigger("focus")}),this._makeFocusTarget(),this._trigger("open"))},_focusTabbable:function(){var t=this._focusedElement;(t=!(t=!(t=!(t=!(t=t||this.element.find("[autofocus]")).length?this.element.find(":tabbable"):t).length?this.uiDialogButtonPane.find(":tabbable"):t).length?this.uiDialogTitlebarClose.filter(":tabbable"):t).length?this.uiDialog:t).eq(0).trigger("focus")},_restoreTabbableFocus:function(){var t=V.ui.safeActiveElement(this.document[0]);this.uiDialog[0]===t||V.contains(this.uiDialog[0],t)||this._focusTabbable()},_keepFocus:function(t){t.preventDefault(),this._restoreTabbableFocus(),this._delay(this._restoreTabbableFocus)},_createWrapper:function(){this.uiDialog=V("
").hide().attr({tabIndex:-1,role:"dialog"}).appendTo(this._appendTo()),this._addClass(this.uiDialog,"ui-dialog","ui-widget ui-widget-content ui-front"),this._on(this.uiDialog,{keydown:function(t){if(this.options.closeOnEscape&&!t.isDefaultPrevented()&&t.keyCode&&t.keyCode===V.ui.keyCode.ESCAPE)return t.preventDefault(),void this.close(t);var e,i,s;t.keyCode!==V.ui.keyCode.TAB||t.isDefaultPrevented()||(e=this.uiDialog.find(":tabbable"),i=e.first(),s=e.last(),t.target!==s[0]&&t.target!==this.uiDialog[0]||t.shiftKey?t.target!==i[0]&&t.target!==this.uiDialog[0]||!t.shiftKey||(this._delay(function(){s.trigger("focus")}),t.preventDefault()):(this._delay(function(){i.trigger("focus")}),t.preventDefault()))},mousedown:function(t){this._moveToTop(t)&&this._focusTabbable()}}),this.element.find("[aria-describedby]").length||this.uiDialog.attr({"aria-describedby":this.element.uniqueId().attr("id")})},_createTitlebar:function(){var t;this.uiDialogTitlebar=V("
"),this._addClass(this.uiDialogTitlebar,"ui-dialog-titlebar","ui-widget-header ui-helper-clearfix"),this._on(this.uiDialogTitlebar,{mousedown:function(t){V(t.target).closest(".ui-dialog-titlebar-close")||this.uiDialog.trigger("focus")}}),this.uiDialogTitlebarClose=V("").button({label:V("").text(this.options.closeText).html(),icon:"ui-icon-closethick",showLabel:!1}).appendTo(this.uiDialogTitlebar),this._addClass(this.uiDialogTitlebarClose,"ui-dialog-titlebar-close"),this._on(this.uiDialogTitlebarClose,{click:function(t){t.preventDefault(),this.close(t)}}),t=V("").uniqueId().prependTo(this.uiDialogTitlebar),this._addClass(t,"ui-dialog-title"),this._title(t),this.uiDialogTitlebar.prependTo(this.uiDialog),this.uiDialog.attr({"aria-labelledby":t.attr("id")})},_title:function(t){this.options.title?t.text(this.options.title):t.html(" ")},_createButtonPane:function(){this.uiDialogButtonPane=V("
"),this._addClass(this.uiDialogButtonPane,"ui-dialog-buttonpane","ui-widget-content ui-helper-clearfix"),this.uiButtonSet=V("
").appendTo(this.uiDialogButtonPane),this._addClass(this.uiButtonSet,"ui-dialog-buttonset"),this._createButtons()},_createButtons:function(){var s=this,t=this.options.buttons;this.uiDialogButtonPane.remove(),this.uiButtonSet.empty(),V.isEmptyObject(t)||Array.isArray(t)&&!t.length?this._removeClass(this.uiDialog,"ui-dialog-buttons"):(V.each(t,function(t,e){var i;e=V.extend({type:"button"},e="function"==typeof e?{click:e,text:t}:e),i=e.click,t={icon:e.icon,iconPosition:e.iconPosition,showLabel:e.showLabel,icons:e.icons,text:e.text},delete e.click,delete e.icon,delete e.iconPosition,delete e.showLabel,delete e.icons,"boolean"==typeof e.text&&delete e.text,V("",e).button(t).appendTo(s.uiButtonSet).on("click",function(){i.apply(s.element[0],arguments)})}),this._addClass(this.uiDialog,"ui-dialog-buttons"),this.uiDialogButtonPane.appendTo(this.uiDialog))},_makeDraggable:function(){var n=this,o=this.options;function a(t){return{position:t.position,offset:t.offset}}this.uiDialog.draggable({cancel:".ui-dialog-content, .ui-dialog-titlebar-close",handle:".ui-dialog-titlebar",containment:"document",start:function(t,e){n._addClass(V(this),"ui-dialog-dragging"),n._blockFrames(),n._trigger("dragStart",t,a(e))},drag:function(t,e){n._trigger("drag",t,a(e))},stop:function(t,e){var i=e.offset.left-n.document.scrollLeft(),s=e.offset.top-n.document.scrollTop();o.position={my:"left top",at:"left"+(0<=i?"+":"")+i+" top"+(0<=s?"+":"")+s,of:n.window},n._removeClass(V(this),"ui-dialog-dragging"),n._unblockFrames(),n._trigger("dragStop",t,a(e))}})},_makeResizable:function(){var n=this,o=this.options,t=o.resizable,e=this.uiDialog.css("position"),t="string"==typeof t?t:"n,e,s,w,se,sw,ne,nw";function a(t){return{originalPosition:t.originalPosition,originalSize:t.originalSize,position:t.position,size:t.size}}this.uiDialog.resizable({cancel:".ui-dialog-content",containment:"document",alsoResize:this.element,maxWidth:o.maxWidth,maxHeight:o.maxHeight,minWidth:o.minWidth,minHeight:this._minHeight(),handles:t,start:function(t,e){n._addClass(V(this),"ui-dialog-resizing"),n._blockFrames(),n._trigger("resizeStart",t,a(e))},resize:function(t,e){n._trigger("resize",t,a(e))},stop:function(t,e){var i=n.uiDialog.offset(),s=i.left-n.document.scrollLeft(),i=i.top-n.document.scrollTop();o.height=n.uiDialog.height(),o.width=n.uiDialog.width(),o.position={my:"left top",at:"left"+(0<=s?"+":"")+s+" top"+(0<=i?"+":"")+i,of:n.window},n._removeClass(V(this),"ui-dialog-resizing"),n._unblockFrames(),n._trigger("resizeStop",t,a(e))}}).css("position",e)},_trackFocus:function(){this._on(this.widget(),{focusin:function(t){this._makeFocusTarget(),this._focusedElement=V(t.target)}})},_makeFocusTarget:function(){this._untrackInstance(),this._trackingInstances().unshift(this)},_untrackInstance:function(){var t=this._trackingInstances(),e=V.inArray(this,t);-1!==e&&t.splice(e,1)},_trackingInstances:function(){var t=this.document.data("ui-dialog-instances");return t||this.document.data("ui-dialog-instances",t=[]),t},_minHeight:function(){var t=this.options;return"auto"===t.height?t.minHeight:Math.min(t.minHeight,t.height)},_position:function(){var t=this.uiDialog.is(":visible");t||this.uiDialog.show(),this.uiDialog.position(this.options.position),t||this.uiDialog.hide()},_setOptions:function(t){var i=this,s=!1,n={};V.each(t,function(t,e){i._setOption(t,e),t in i.sizeRelatedOptions&&(s=!0),t in i.resizableRelatedOptions&&(n[t]=e)}),s&&(this._size(),this._position()),this.uiDialog.is(":data(ui-resizable)")&&this.uiDialog.resizable("option",n)},_setOption:function(t,e){var i,s=this.uiDialog;"disabled"!==t&&(this._super(t,e),"appendTo"===t&&this.uiDialog.appendTo(this._appendTo()),"buttons"===t&&this._createButtons(),"closeText"===t&&this.uiDialogTitlebarClose.button({label:V("").text(""+this.options.closeText).html()}),"draggable"===t&&((i=s.is(":data(ui-draggable)"))&&!e&&s.draggable("destroy"),!i&&e&&this._makeDraggable()),"position"===t&&this._position(),"resizable"===t&&((i=s.is(":data(ui-resizable)"))&&!e&&s.resizable("destroy"),i&&"string"==typeof e&&s.resizable("option","handles",e),i||!1===e||this._makeResizable()),"title"===t&&this._title(this.uiDialogTitlebar.find(".ui-dialog-title")))},_size:function(){var t,e,i,s=this.options;this.element.show().css({width:"auto",minHeight:0,maxHeight:"none",height:0}),s.minWidth>s.width&&(s.width=s.minWidth),t=this.uiDialog.css({height:"auto",width:s.width}).outerHeight(),e=Math.max(0,s.minHeight-t),i="number"==typeof s.maxHeight?Math.max(0,s.maxHeight-t):"none","auto"===s.height?this.element.css({minHeight:e,maxHeight:i,height:"auto"}):this.element.height(Math.max(0,s.height-t)),this.uiDialog.is(":data(ui-resizable)")&&this.uiDialog.resizable("option","minHeight",this._minHeight())},_blockFrames:function(){this.iframeBlocks=this.document.find("iframe").map(function(){var t=V(this);return V("
").css({position:"absolute",width:t.outerWidth(),height:t.outerHeight()}).appendTo(t.parent()).offset(t.offset())[0]})},_unblockFrames:function(){this.iframeBlocks&&(this.iframeBlocks.remove(),delete this.iframeBlocks)},_allowInteraction:function(t){return!!V(t.target).closest(".ui-dialog").length||!!V(t.target).closest(".ui-datepicker").length},_createOverlay:function(){var i,s;this.options.modal&&(i=V.fn.jquery.substring(0,4),s=!0,this._delay(function(){s=!1}),this.document.data("ui-dialog-overlays")||this.document.on("focusin.ui-dialog",function(t){var e;s||((e=this._trackingInstances()[0])._allowInteraction(t)||(t.preventDefault(),e._focusTabbable(),"3.4."!==i&&"3.5."!==i||e._delay(e._restoreTabbableFocus)))}.bind(this)),this.overlay=V("
").appendTo(this._appendTo()),this._addClass(this.overlay,null,"ui-widget-overlay ui-front"),this._on(this.overlay,{mousedown:"_keepFocus"}),this.document.data("ui-dialog-overlays",(this.document.data("ui-dialog-overlays")||0)+1))},_destroyOverlay:function(){var t;this.options.modal&&this.overlay&&((t=this.document.data("ui-dialog-overlays")-1)?this.document.data("ui-dialog-overlays",t):(this.document.off("focusin.ui-dialog"),this.document.removeData("ui-dialog-overlays")),this.overlay.remove(),this.overlay=null)}}),!1!==V.uiBackCompat&&V.widget("ui.dialog",V.ui.dialog,{options:{dialogClass:""},_createWrapper:function(){this._super(),this.uiDialog.addClass(this.options.dialogClass)},_setOption:function(t,e){"dialogClass"===t&&this.uiDialog.removeClass(this.options.dialogClass).addClass(e),this._superApply(arguments)}});V.ui.dialog;function lt(t,e,i){return e<=t&&t").appendTo(this.element),this._addClass(this.valueDiv,"ui-progressbar-value","ui-widget-header"),this._refreshValue()},_destroy:function(){this.element.removeAttr("role aria-valuemin aria-valuemax aria-valuenow"),this.valueDiv.remove()},value:function(t){if(void 0===t)return this.options.value;this.options.value=this._constrainedValue(t),this._refreshValue()},_constrainedValue:function(t){return void 0===t&&(t=this.options.value),this.indeterminate=!1===t,"number"!=typeof t&&(t=0),!this.indeterminate&&Math.min(this.options.max,Math.max(this.min,t))},_setOptions:function(t){var e=t.value;delete t.value,this._super(t),this.options.value=this._constrainedValue(e),this._refreshValue()},_setOption:function(t,e){"max"===t&&(e=Math.max(this.min,e)),this._super(t,e)},_setOptionDisabled:function(t){this._super(t),this.element.attr("aria-disabled",t),this._toggleClass(null,"ui-state-disabled",!!t)},_percentage:function(){return this.indeterminate?100:100*(this.options.value-this.min)/(this.options.max-this.min)},_refreshValue:function(){var t=this.options.value,e=this._percentage();this.valueDiv.toggle(this.indeterminate||t>this.min).width(e.toFixed(0)+"%"),this._toggleClass(this.valueDiv,"ui-progressbar-complete",null,t===this.options.max)._toggleClass("ui-progressbar-indeterminate",null,this.indeterminate),this.indeterminate?(this.element.removeAttr("aria-valuenow"),this.overlayDiv||(this.overlayDiv=V("
").appendTo(this.valueDiv),this._addClass(this.overlayDiv,"ui-progressbar-overlay"))):(this.element.attr({"aria-valuemax":this.options.max,"aria-valuenow":t}),this.overlayDiv&&(this.overlayDiv.remove(),this.overlayDiv=null)),this.oldValue!==t&&(this.oldValue=t,this._trigger("change")),t===this.options.max&&this._trigger("complete")}}),V.widget("ui.selectable",V.ui.mouse,{version:"1.13.2",options:{appendTo:"body",autoRefresh:!0,distance:0,filter:"*",tolerance:"touch",selected:null,selecting:null,start:null,stop:null,unselected:null,unselecting:null},_create:function(){var i=this;this._addClass("ui-selectable"),this.dragged=!1,this.refresh=function(){i.elementPos=V(i.element[0]).offset(),i.selectees=V(i.options.filter,i.element[0]),i._addClass(i.selectees,"ui-selectee"),i.selectees.each(function(){var t=V(this),e=t.offset(),e={left:e.left-i.elementPos.left,top:e.top-i.elementPos.top};V.data(this,"selectable-item",{element:this,$element:t,left:e.left,top:e.top,right:e.left+t.outerWidth(),bottom:e.top+t.outerHeight(),startselected:!1,selected:t.hasClass("ui-selected"),selecting:t.hasClass("ui-selecting"),unselecting:t.hasClass("ui-unselecting")})})},this.refresh(),this._mouseInit(),this.helper=V("
"),this._addClass(this.helper,"ui-selectable-helper")},_destroy:function(){this.selectees.removeData("selectable-item"),this._mouseDestroy()},_mouseStart:function(i){var s=this,t=this.options;this.opos=[i.pageX,i.pageY],this.elementPos=V(this.element[0]).offset(),this.options.disabled||(this.selectees=V(t.filter,this.element[0]),this._trigger("start",i),V(t.appendTo).append(this.helper),this.helper.css({left:i.pageX,top:i.pageY,width:0,height:0}),t.autoRefresh&&this.refresh(),this.selectees.filter(".ui-selected").each(function(){var t=V.data(this,"selectable-item");t.startselected=!0,i.metaKey||i.ctrlKey||(s._removeClass(t.$element,"ui-selected"),t.selected=!1,s._addClass(t.$element,"ui-unselecting"),t.unselecting=!0,s._trigger("unselecting",i,{unselecting:t.element}))}),V(i.target).parents().addBack().each(function(){var t,e=V.data(this,"selectable-item");if(e)return t=!i.metaKey&&!i.ctrlKey||!e.$element.hasClass("ui-selected"),s._removeClass(e.$element,t?"ui-unselecting":"ui-selected")._addClass(e.$element,t?"ui-selecting":"ui-unselecting"),e.unselecting=!t,e.selecting=t,(e.selected=t)?s._trigger("selecting",i,{selecting:e.element}):s._trigger("unselecting",i,{unselecting:e.element}),!1}))},_mouseDrag:function(s){if(this.dragged=!0,!this.options.disabled){var t,n=this,o=this.options,a=this.opos[0],r=this.opos[1],l=s.pageX,h=s.pageY;return ll||i.righth||i.bottoma&&i.rightr&&i.bottom",options:{appendTo:null,classes:{"ui-selectmenu-button-open":"ui-corner-top","ui-selectmenu-button-closed":"ui-corner-all"},disabled:null,icons:{button:"ui-icon-triangle-1-s"},position:{my:"left top",at:"left bottom",collision:"none"},width:!1,change:null,close:null,focus:null,open:null,select:null},_create:function(){var t=this.element.uniqueId().attr("id");this.ids={element:t,button:t+"-button",menu:t+"-menu"},this._drawButton(),this._drawMenu(),this._bindFormResetHandler(),this._rendered=!1,this.menuItems=V()},_drawButton:function(){var t,e=this,i=this._parseOption(this.element.find("option:selected"),this.element[0].selectedIndex);this.labels=this.element.labels().attr("for",this.ids.button),this._on(this.labels,{click:function(t){this.button.trigger("focus"),t.preventDefault()}}),this.element.hide(),this.button=V("",{tabindex:this.options.disabled?-1:0,id:this.ids.button,role:"combobox","aria-expanded":"false","aria-autocomplete":"list","aria-owns":this.ids.menu,"aria-haspopup":"true",title:this.element.attr("title")}).insertAfter(this.element),this._addClass(this.button,"ui-selectmenu-button ui-selectmenu-button-closed","ui-button ui-widget"),t=V("").appendTo(this.button),this._addClass(t,"ui-selectmenu-icon","ui-icon "+this.options.icons.button),this.buttonItem=this._renderButtonItem(i).appendTo(this.button),!1!==this.options.width&&this._resizeButton(),this._on(this.button,this._buttonEvents),this.button.one("focusin",function(){e._rendered||e._refreshMenu()})},_drawMenu:function(){var i=this;this.menu=V("