diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md
new file mode 100644
index 000000000..73a5f1645
--- /dev/null
+++ b/.github/copilot-instructions.md
@@ -0,0 +1,298 @@
+# GitHub Copilot Instructions for Application Insights JavaScript SDK
+
+## Project Overview
+This is the **Microsoft Application Insights JavaScript SDK** - a browser-based telemetry library for monitoring web applications. The SDK tracks page views, user interactions, performance metrics, exceptions, and custom events.
+
+## Architecture & Structure
+
+### Monorepo Structure
+- **AISKU/**: Main Application Insights SDK package
+- **AISKULight/**: Lightweight version of the SDK
+- **shared/**: Core shared libraries (AppInsightsCore, AppInsightsCommon, 1ds-core-js)
+- **extensions/**: Plugin-based extensions (analytics, dependencies, etc.)
+- **channels/**: Data transmission channels (online, offline, tee)
+- **tools/**: Build and development tools
+- **examples/**: Sample implementations
+
+### Key Technologies
+- **TypeScript/JavaScript**: Primary languages (ES5 target for browser compatibility)
+- **Rush**: Monorepo management tool
+- **Rollup**: Module bundler
+- **Grunt**: Task runner
+- **Dynamic Proto**: Dynamic prototype pattern for performance
+
+## Code Style & Patterns
+
+### TypeScript/JavaScript Conventions
+- Use **ES5-compatible** syntax for browser support and target ES5 for modern browsers
+- Prefer `function` declarations over arrow functions for better IE compatibility
+- Use `var` instead of `let/const` in JavaScript files for ES5 compatibility (use `let/const` in TypeScript files)
+- Always use semicolons
+- Use 4-space indentation
+- Maximum line length: 140 characters
+
+### Naming Conventions
+- **Classes**: PascalCase (e.g., `PageViewManager`, `TelemetryContext`)
+- **Interfaces**: PascalCase with `I` prefix (e.g., `ITelemetryItem`, `IPageViewTelemetry`)
+- **Methods/Functions**: camelCase (e.g., `trackPageView`, `sendTelemetry`)
+- **Constants**: UPPER_SNAKE_CASE (e.g., `MAX_DURATION_ALLOWED`)
+- **Private variables**: underscore prefix (e.g., `_logger`, `_hasInitialized`)
+- **Enums**: PascalCase with `e` prefix (e.g., `eLoggingSeverity`, `eInternalMessageId`)
+ - Must be const enums with integer values (not strings)
+ - Use `createEnumStyle` helper for exported enums
+ - All usage should reference the const enum directly
+
+### Dynamic Proto Pattern
+This project uses a unique `dynamicProto` pattern for performance optimization. This pattern should be used for all classes:
+
+```typescript
+export class MyClass {
+ constructor() {
+ dynamicProto(MyClass, this, (_self, _base) => {
+ // Private variables should be included inside the constructor closure
+ // They are not publicly visible on the class
+ let _logger = _self._logger;
+ let _hasInitialized = false;
+
+ // Public methods need @DynamicProtoStub comment for TypeScript definitions
+ _self.myMethod = () => {
+ // Method implementation
+ };
+ });
+ }
+
+ /**
+ * @DynamicProtoStub -- DO NOT add any code as this will be removed during packaging
+ */
+ public myMethod(): void {
+ // This stub will be replaced by the dynamicProto implementation
+ }
+}
+```
+
+Key requirements:
+- Use this pattern for all classes
+- Private variables must be inside the constructor closure
+- Public functions need `@DynamicProtoStub` comment for TypeScript definition generation
+- Never add implementation code to the stub methods
+
+### Error Handling
+- Use `_throwInternal` for logging diagnostic errors
+- Always include telemetry context in error messages
+- Use appropriate logging severity levels: `CRITICAL`, `WARNING`, `INFORMATION`
+
+```typescript
+_throwInternal(_logger,
+ eLoggingSeverity.WARNING,
+ _eInternalMessageId.InvalidDurationValue,
+ "Invalid page load duration value",
+ { total, network, request, response, dom });
+```
+
+### Performance Considerations
+- Minimize object allocations in hot paths
+- Use `doPerf()` wrapper for performance tracking
+- Avoid synchronous operations that could block the browser
+- Implement lazy initialization where possible
+- Use object pooling for frequently created objects
+- Minimize the size of generated JavaScript by avoiding certain TypeScript features:
+ - Do not use the spread `...` operator
+ - Do not use optional chaining `?.` operator
+ - Do not use the nullish coalescing `??` operator - use `||` instead
+ - These restrictions will be removed once ES5 support is discontinued
+
+## Browser Compatibility
+
+### Target Support
+- **Modern browsers**: Chrome, Firefox, Safari, Edge (targeting ES5 for modern browsers)
+- **Legacy support**: Internet Explorer 8+ (ES5 compatibility required)
+- **Mobile browsers**: iOS Safari, Android Chrome
+- **Non-browser runtimes**: Node.js and other browser-like environments (for worker contexts and server-side rendering)
+
+### Compatibility Patterns
+- Feature detection over browser detection
+- Graceful degradation for missing APIs
+- Use existing polyfills rather than creating new ones
+- Safe API usage with null checks
+
+### Async Operations Support
+Support async operations using ts-async helpers instead of native async/await:
+- Use `doAwait` for `await` operations
+- Use `doAwaitResponse` to handle catch operations for asynchronous operations
+- Use `createPromise`, `createSyncPromise`, `createIdlePromise` instead of declaring functions as `async`
+- Return type should use `IPromise` instead of `Promise` for IE support
+
+```typescript
+const perf = getPerformance();
+if (perf && perf.timing && perf.timing.navigationStart) {
+ // Use performance API
+}
+```
+
+## Telemetry & Data Collection
+
+### Core Telemetry Types
+- **Page Views**: `IPageViewTelemetry` - Track page navigation
+- **Events**: `IEventTelemetry` - Custom user actions
+- **Metrics**: `IMetricTelemetry` - Numeric measurements
+- **Exceptions**: `IExceptionTelemetry` - Error tracking
+- **Dependencies**: `IDependencyTelemetry` - External calls
+- **Traces**: `ITraceTelemetry` - Logging messages
+
+### Data Privacy & Compliance
+- Never collect PII (personally identifiable information) by default
+- Sanitize URLs and remove sensitive query parameters
+- Implement data sampling and throttling
+- Support opt-out mechanisms
+- Follow GDPR/privacy regulations
+
+### Performance Monitoring
+- Use `IPerfManager` and `IPerfEvent` for internal performance tracking
+- Collect browser timing APIs (Navigation Timing, Resource Timing)
+- Track page load performance metrics
+- Monitor SDK overhead and impact
+
+## Plugin Architecture
+
+### Plugin Development
+- Extend `BaseTelemetryPlugin` for new plugins
+- Implement `ITelemetryPlugin` interface
+- Use `IProcessTelemetryContext` for processing pipeline
+- Support plugin chaining and dependencies
+
+```typescript
+export class MyPlugin extends BaseTelemetryPlugin {
+ public processTelemetry(evt: ITelemetryItem, itemCtx?: IProcessTelemetryContext) {
+ // Process telemetry
+ this.processNext(evt, itemCtx);
+ }
+}
+```
+
+### Extension Points
+- **Telemetry Initializers**: Modify telemetry before sending
+- **Dependency Listeners**: Track AJAX/fetch calls
+- **Channels**: Custom data transmission
+
+## Testing Patterns
+
+### Unit Testing
+- Use framework-agnostic test patterns
+- Mock browser APIs consistently
+- Test both success and failure scenarios
+- Verify telemetry data structure and content
+
+### Browser Testing
+- Cross-browser compatibility testing
+- Performance regression testing
+- Memory leak detection
+- Network failure scenarios
+
+### Test Organization
+- Collocate tests with source code in `Tests/` directories
+- Use descriptive test names
+- Group related tests in test suites
+- Mock external dependencies
+
+## Configuration & Initialization
+
+### SDK Configuration
+- Support both snippet and npm installation
+- Provide sensible defaults
+- Allow runtime configuration changes
+- Validate configuration parameters
+- Configuration names should be descriptive but mindful of browser bundle size by keeping names concise and readable
+
+```typescript
+const config: IConfiguration = {
+ instrumentationKey: "your-key",
+ enableAutoRouteTracking: true,
+ disableTelemetry: false,
+ samplingPercentage: 100
+};
+```
+
+### Initialization Patterns
+- Lazy initialization to minimize startup impact
+- Graceful handling of initialization failures
+- Support for multiple SDK instances
+- Plugin dependency resolution
+
+## Performance Guidelines
+
+### Bundle Size Optimization
+- Tree-shaking friendly exports
+- Conditional feature loading
+- Minimize third-party dependencies
+- Use rollup for optimal bundling
+
+### Runtime Performance
+- Avoid blocking the main thread
+- Use requestIdleCallback when available
+- Batch telemetry operations
+- Implement efficient queuing mechanisms
+
+### Memory Management
+- Clean up event listeners on teardown
+- Avoid memory leaks in long-running applications
+- Use weak references where appropriate
+- Implement proper disposal patterns
+
+### Code Organization & Tree-Shaking
+- Each package should be side-effect free to enable proper tree-shaking
+- All code should be tree-shakable - avoid global side effects
+- Use lazy initialization for any globals via `ILazyValue` interface or similar patterns
+- Distinguish between "value not yet checked/assigned" vs "resulting value is null/undefined"
+- Export functions and classes individually rather than as default exports
+- Avoid executing code at module load time
+
+## Common Patterns & Anti-Patterns
+
+### ✅ Good Practices
+- Use TypeScript interfaces for contracts
+- Implement proper error boundaries
+- Follow the plugin architecture
+- Use performance monitoring internally
+- Sanitize all user inputs
+- Support both sync and async operations
+
+### ❌ Anti-Patterns
+- Don't block the browser UI thread
+- Avoid throwing unhandled exceptions
+- Don't collect sensitive user data
+- Avoid tight coupling between components
+- Don't ignore browser compatibility
+- Avoid memory leaks in event handlers
+
+## Documentation Standards
+
+### Code Comments
+- Use TypeDoc format for public APIs
+- Document complex algorithms and business logic
+- Include examples for public methods
+- Explain browser compatibility considerations
+
+### Interface Documentation
+- Document all public interfaces thoroughly using TypeDoc comments
+- Include parameter validation requirements
+- Include defaults and any relevant examples
+- Specify return value contracts
+- Note any side effects or state changes
+
+## Build & Deployment
+
+### Build Process
+- Rush for monorepo management
+- TypeScript compilation with strict settings
+- Rollup bundling with multiple output formats
+- Minification and size optimization
+
+### Release Process
+- Semantic versioning
+- Automated testing before release
+- Bundle size monitoring
+- Browser compatibility verification
+
+---
+
+*This document helps GitHub Copilot understand the unique patterns, architecture, and requirements of the Application Insights JavaScript SDK project.*
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 3254835bd..b22b909dd 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -5,9 +5,9 @@ name: Node.js CI
on:
push:
- branches: [ main, master, beta, Release2.7, release-3.0 ]
+ branches: [ main, master, beta, Release2.7, release-3.0, otel-sdk ]
pull_request:
- branches: [ main, master, beta, Release2.7, release-3.0 ]
+ branches: [ main, master, beta, Release2.7, release-3.0, otel-sdk ]
merge_group:
branches: [ "main", "master", "beta", "Release*", "release*", "*-legacy", "legacy-v1" ]
diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml
index ea12979f6..32d0813a7 100644
--- a/.github/workflows/codeql-analysis.yml
+++ b/.github/workflows/codeql-analysis.yml
@@ -16,9 +16,9 @@ on:
branches: [ "main", "master", "beta", "Release*", "release*", "*-legacy", "legacy-v1" ]
pull_request:
# The branches below must be a subset of the branches above
- branches: [ "main", "master", "beta", "Release*", "release*", "*-legacy", "legacy-v1" ]
+ branches: [ "main", "master", "beta", "Release*", "release*", "*-legacy", "legacy-v1", "otel-sdk" ]
schedule:
- - cron: '15 */2 * * *' # run every 2 hours at 15 minutes past the hour
+ - cron: '15 17 * * 2' # Every Tuesday at 17:15 UTC
jobs:
analyze:
@@ -99,4 +99,4 @@ jobs:
run: |
echo "Executed CodeQL for language: ${{ matrix.language }}"
echo "Category used: /language:${{ matrix.language }}"
- echo "Node version: ${{ matrix.node-version || 'N/A' }}"
\ No newline at end of file
+ echo "Node version: ${{ matrix.node-version || 'N/A' }}"
diff --git a/AISKU/README.md b/AISKU/README.md
index 42e7a4e3a..2fe3bf807 100644
--- a/AISKU/README.md
+++ b/AISKU/README.md
@@ -34,6 +34,7 @@ See [Breaking Changes](https://microsoft.github.io/ApplicationInsights-JS/upgrad
| Version | Full Size | Raw Minified | GZip Size
|---------|-----------|--------------|-------------
| [<nightly3>](https://github.com/microsoft/ApplicationInsights-JS/tree/main/AISKU) | [](https://js.monitor.azure.com/nightly/ai.3-nightly3.js.svg)|  | 
+| 3.3.9: | [](https://js.monitor.azure.com/scripts/b/ai.3.3.9.js.svg)|  | 
| 3.3.8: | [](https://js.monitor.azure.com/scripts/b/ai.3.3.8.js.svg)|  | 
| 3.3.7: | [](https://js.monitor.azure.com/scripts/b/ai.3.3.7.js.svg)|  | 
| 3.3.6: | [](https://js.monitor.azure.com/scripts/b/ai.3.3.6.js.svg)|  | 
diff --git a/AISKU/Tests/Perf/src/AISKUPerf.Tests.ts b/AISKU/Tests/Perf/src/AISKUPerf.Tests.ts
index 19aa62857..1d24d1dd5 100644
--- a/AISKU/Tests/Perf/src/AISKUPerf.Tests.ts
+++ b/AISKU/Tests/Perf/src/AISKUPerf.Tests.ts
@@ -153,8 +153,8 @@ export class AISKUPerf extends AITestClass {
}
public testCleanup() {
- utlRemoveSessionStorage(null as any, "AI_sentBuffer", );
- utlRemoveSessionStorage(null as any, "AI_buffer", );
+ utlRemoveSessionStorage(null as any, "AI_sentBuffer");
+ utlRemoveSessionStorage(null as any, "AI_buffer");
}
public registerTests() {
diff --git a/AISKU/Tests/Perf/src/AISKUPerf.ts b/AISKU/Tests/Perf/src/AISKUPerf.ts
index 8e7fdcc38..1da8993a5 100644
--- a/AISKU/Tests/Perf/src/AISKUPerf.ts
+++ b/AISKU/Tests/Perf/src/AISKUPerf.ts
@@ -19,7 +19,7 @@ export class AppInsightsInitPerfTestClass {
* should update version after new release
* version with doperf(): after 2.5.6
* */
- var defaultVer = "3.3.8";
+ var defaultVer = "3.3.9";
this.version = ver? ver:this._getQueryParameterVersion(defaultVer);
this.perfEventsBuffer = [];
this.perfEventWaitBuffer = [];
diff --git a/AISKU/Tests/Unit/src/AISKUSize.Tests.ts b/AISKU/Tests/Unit/src/AISKUSize.Tests.ts
index b02b6976e..f24e518bf 100644
--- a/AISKU/Tests/Unit/src/AISKUSize.Tests.ts
+++ b/AISKU/Tests/Unit/src/AISKUSize.Tests.ts
@@ -54,13 +54,13 @@ function _checkSize(checkType: string, maxSize: number, size: number, isNightly:
}
export class AISKUSizeCheck extends AITestClass {
- private readonly MAX_RAW_SIZE = 147;
- private readonly MAX_BUNDLE_SIZE = 147;
+ private readonly MAX_RAW_SIZE = 148;
+ private readonly MAX_BUNDLE_SIZE = 148;
private readonly MAX_RAW_DEFLATE_SIZE = 59;
private readonly MAX_BUNDLE_DEFLATE_SIZE = 59;
private readonly rawFilePath = "../dist/es5/applicationinsights-web.min.js";
// Automatically updated by version scripts
- private readonly currentVer = "3.3.8";
+ private readonly currentVer = "3.3.9";
private readonly prodFilePath = `../browser/es5/ai.${this.currentVer[0]}.min.js`;
public testInitialize() {
@@ -85,8 +85,8 @@ export class AISKUSizeCheck extends AITestClass {
}
public testCleanup() {
- utlRemoveSessionStorage(null as any, "AI_sentBuffer", );
- utlRemoveSessionStorage(null as any, "AI_buffer", );
+ utlRemoveSessionStorage(null as any, "AI_sentBuffer");
+ utlRemoveSessionStorage(null as any, "AI_buffer");
}
public registerTests() {
diff --git a/AISKU/Tests/Unit/src/CdnPackaging.tests.ts b/AISKU/Tests/Unit/src/CdnPackaging.tests.ts
index 7faf10b20..765d72dc8 100644
--- a/AISKU/Tests/Unit/src/CdnPackaging.tests.ts
+++ b/AISKU/Tests/Unit/src/CdnPackaging.tests.ts
@@ -16,7 +16,7 @@ const enum CdnFormat {
export class CdnPackagingChecks extends AITestClass {
// Automatically updated by version scripts
- private readonly currentVer = "3.3.8";
+ private readonly currentVer = "3.3.9";
public testInitialize() {
}
diff --git a/AISKU/Tests/Unit/src/IAnalyticsConfig.Tests.ts b/AISKU/Tests/Unit/src/IAnalyticsConfig.Tests.ts
new file mode 100644
index 000000000..d9bd8c6f5
--- /dev/null
+++ b/AISKU/Tests/Unit/src/IAnalyticsConfig.Tests.ts
@@ -0,0 +1,105 @@
+import { ApplicationInsights, IAnalyticsConfig, IAppInsights, IConfig, ApplicationAnalytics } from "../../../src/applicationinsights-web";
+import { AITestClass, Assert } from "@microsoft/ai-test-framework";
+import { AnalyticsPluginIdentifier, utlRemoveSessionStorage } from "@microsoft/applicationinsights-common";
+import { AppInsightsCore, IConfiguration, isFunction, onConfigChange } from "@microsoft/applicationinsights-core-js";
+import { Sender } from "@microsoft/applicationinsights-channel-js";
+
+const TestInstrumentationKey = 'b7170927-2d1c-44f1-acec-59f4e1751c11';
+
+export class IAnalyticsConfigTests extends AITestClass {
+
+ public testInitialize() {
+ this._disableDynProtoBaseFuncs();
+ }
+
+ public testCleanup() {
+ // Clean up session storage
+ utlRemoveSessionStorage(null as any, "AI_sentBuffer");
+ utlRemoveSessionStorage(null as any, "AI_buffer");
+ }
+
+ public registerTests() {
+
+ this.testCase({
+ name: "IAnalyticsConfig: Interface compatibility with existing functionality",
+ test: () => {
+ // Test that the interface doesn't break existing functionality
+ // Use root configuration (IConfiguration) for ApplicationInsights initialization
+ const init = new ApplicationInsights({
+ config: {
+ instrumentationKey: TestInstrumentationKey
+ }
+ });
+ this.onDone(() => {
+ if (init && init.unload) {
+ init.unload(false);
+ }
+ });
+ init.loadAppInsights();
+
+ // These should work as before
+ Assert.ok(isFunction(init.trackEvent), "trackEvent should be available");
+ Assert.ok(isFunction(init.trackPageView), "trackPageView should be available");
+ Assert.ok(isFunction(init.trackException), "trackException should be available");
+ Assert.ok(isFunction(init.trackTrace), "trackTrace should be available");
+ Assert.ok(isFunction(init.trackMetric), "trackMetric should be available");
+ Assert.ok(isFunction(init.trackDependencyData), "trackDependencyData should be available");
+ }
+ });
+
+ this.testCase({
+ name: "IAnalyticsConfig: onConfigChange integration test",
+ useFakeTimers: true,
+ test: () => {
+ let theConfig: IConfiguration & IConfig = {
+ instrumentationKey: TestInstrumentationKey,
+ samplingPercentage: 50
+ };
+
+ const core = new AppInsightsCore();
+ const init = new ApplicationInsights({
+ config: theConfig
+ });
+ this.onDone(() => {
+ if (init && init.unload) {
+ init.unload(false);
+ }
+ });
+
+ init.loadAppInsights();
+ let onChangeCalled = 0;
+ let expectedSamplingPercentage = 50;
+
+ let handler = onConfigChange(theConfig, (details) => {
+ onChangeCalled++;
+ Assert.equal(TestInstrumentationKey, details.cfg.instrumentationKey, "Expect the iKey to be set");
+ if (details.cfg.samplingPercentage !== undefined) {
+ Assert.equal(expectedSamplingPercentage, details.cfg.samplingPercentage, "Expect the sampling percentage to be set");
+ }
+ });
+
+ // Initial call should happen
+ Assert.equal(1, onChangeCalled, "OnCfgChange was called exactly once initially");
+ let initialCallCount = onChangeCalled;
+
+ // Change a config value
+ expectedSamplingPercentage = 75;
+ (theConfig as any).samplingPercentage = expectedSamplingPercentage;
+
+ // Wait for the change to propagate
+ this.clock.tick(1);
+ Assert.ok(onChangeCalled > initialCallCount, "Expected the onChanged was called when config changed");
+
+ // Remove the handler
+ handler.rm();
+ let callCountBeforeRemoval = onChangeCalled;
+
+ expectedSamplingPercentage = 25;
+ (theConfig as any).samplingPercentage = expectedSamplingPercentage;
+
+ this.clock.tick(1);
+ Assert.equal(callCountBeforeRemoval, onChangeCalled, "Expected the onChanged was not called after handler removal");
+ }
+ });
+ }
+}
\ No newline at end of file
diff --git a/AISKU/Tests/Unit/src/aiskuunittests.ts b/AISKU/Tests/Unit/src/aiskuunittests.ts
index 39a168f4e..8a53729b0 100644
--- a/AISKU/Tests/Unit/src/aiskuunittests.ts
+++ b/AISKU/Tests/Unit/src/aiskuunittests.ts
@@ -9,6 +9,7 @@ import { SenderE2ETests } from './sender.e2e.tests';
import { SnippetInitializationTests } from './SnippetInitialization.Tests';
import { CdnThrottle} from "./CdnThrottle.tests";
import { ThrottleSentMessage } from "./ThrottleSentMessage.tests";
+import { IAnalyticsConfigTests } from './IAnalyticsConfig.Tests';
export function runTests() {
new GlobalTestHooks().registerTests();
@@ -23,4 +24,5 @@ export function runTests() {
new SnippetInitializationTests(true).registerTests();
new ThrottleSentMessage().registerTests();
new CdnThrottle().registerTests();
+ new IAnalyticsConfigTests().registerTests();
}
\ No newline at end of file
diff --git a/AISKU/Tests/es6-module-type-check/package.json b/AISKU/Tests/es6-module-type-check/package.json
index e6d3d89e6..cfb02aa0c 100644
--- a/AISKU/Tests/es6-module-type-check/package.json
+++ b/AISKU/Tests/es6-module-type-check/package.json
@@ -1,7 +1,7 @@
{
"name": "@microsoft/applicationinsights-test-module-type-check",
"author": "Microsoft Application Insights Team and Contributors",
- "version": "3.3.8",
+ "version": "3.3.9",
"description": "Microsoft Application Insights ES6 Module and Type check Example",
"homepage": "https://github.com/microsoft/ApplicationInsights-JS#readme",
"keywords": [
@@ -32,7 +32,7 @@
"tslib": ">= 1.0.0"
},
"dependencies": {
- "@microsoft/applicationinsights-common": "3.3.8",
- "@microsoft/applicationinsights-web": "3.3.8"
+ "@microsoft/applicationinsights-common": "3.3.9",
+ "@microsoft/applicationinsights-web": "3.3.9"
}
}
diff --git a/AISKU/package.json b/AISKU/package.json
index 61f5dea35..ddd92e997 100644
--- a/AISKU/package.json
+++ b/AISKU/package.json
@@ -1,6 +1,6 @@
{
"name": "@microsoft/applicationinsights-web",
- "version": "3.3.8",
+ "version": "3.3.9",
"description": "Microsoft Application Insights JavaScript SDK - Web",
"homepage": "https://github.com/microsoft/ApplicationInsights-JS#readme",
"author": "Microsoft Application Insights Team",
@@ -32,7 +32,7 @@
},
"devDependencies": {
"@microsoft/ai-test-framework": "0.0.1",
- "@microsoft/applicationinsights-offlinechannel-js": "0.3.8",
+ "@microsoft/applicationinsights-offlinechannel-js": "0.3.9",
"@microsoft/applicationinsights-rollup-plugin-uglify3-js": "1.0.0",
"@microsoft/applicationinsights-rollup-es5": "1.0.2",
"sinon": "^7.3.1",
@@ -65,13 +65,13 @@
"dependencies": {
"@microsoft/dynamicproto-js": "^2.0.3",
"@microsoft/applicationinsights-shims": "3.0.1",
- "@microsoft/applicationinsights-analytics-js": "3.3.8",
- "@microsoft/applicationinsights-channel-js": "3.3.8",
- "@microsoft/applicationinsights-cfgsync-js": "3.3.8",
- "@microsoft/applicationinsights-common": "3.3.8",
- "@microsoft/applicationinsights-core-js": "3.3.8",
- "@microsoft/applicationinsights-dependencies-js": "3.3.8",
- "@microsoft/applicationinsights-properties-js": "3.3.8",
+ "@microsoft/applicationinsights-analytics-js": "3.3.9",
+ "@microsoft/applicationinsights-channel-js": "3.3.9",
+ "@microsoft/applicationinsights-cfgsync-js": "3.3.9",
+ "@microsoft/applicationinsights-common": "3.3.9",
+ "@microsoft/applicationinsights-core-js": "3.3.9",
+ "@microsoft/applicationinsights-dependencies-js": "3.3.9",
+ "@microsoft/applicationinsights-properties-js": "3.3.9",
"@nevware21/ts-utils": ">= 0.11.8 < 2.x",
"@nevware21/ts-async": ">= 0.5.4 < 2.x"
},
diff --git a/AISKU/scripts/publishAzReleaseToCdn.ps1 b/AISKU/scripts/publishAzReleaseToCdn.ps1
index 99aacadc3..4367b754a 100644
--- a/AISKU/scripts/publishAzReleaseToCdn.ps1
+++ b/AISKU/scripts/publishAzReleaseToCdn.ps1
@@ -139,7 +139,7 @@ elseif ($version.type -eq "dev" -or $version.type -eq "beta") {
# Publish to release type folder folder
PublishFiles $releaseFiles "$($version.type)" $cacheControl1Year $contentType $overwrite
}
-elseif ($version.type -eq "nightly" -or $version.type -eq "nightly3") {
+elseif ($version.type -like "nightly*") {
# Publish to release nightly folder folder
PublishFiles $releaseFiles "nightly" $cacheControl1Year $contentType $overwrite
}
diff --git a/AISKU/scripts/setAzActiveCdnVersion.ps1 b/AISKU/scripts/setAzActiveCdnVersion.ps1
index c83e1680e..97472c382 100644
--- a/AISKU/scripts/setAzActiveCdnVersion.ps1
+++ b/AISKU/scripts/setAzActiveCdnVersion.ps1
@@ -87,7 +87,7 @@ Function Validate-Params
Write-LogFailure "Container [$container] is not valid for version type [$($version.type)]"
}
}
- elseif ($version.type -eq "nightly" -or $version.type -eq "nightly3") {
+ elseif ($version.type -like "nightly*") {
if ("nightly" -ne $container) {
Write-LogFailure "Container [$container] is not valid for version type [$($version.type)]"
}
diff --git a/AISKU/src/Init.ts b/AISKU/src/Init.ts
index 05b23a4d5..22c39f5ab 100644
--- a/AISKU/src/Init.ts
+++ b/AISKU/src/Init.ts
@@ -50,6 +50,70 @@ export {
// End of Exports available from the Cdn bundles
// ----------------------------------------------------------------------------------------------------
+// ----------------------------------------------------------------------------------------------------
+// Additional exports available from applicationinsights-web.ts (interfaces and enums for typedoc)
+// ----------------------------------------------------------------------------------------------------
+export {
+ IConfiguration,
+ IAppInsightsCore,
+ eLoggingSeverity,
+ ITelemetryItem,
+ ITelemetryPlugin,
+ IPerfEvent,
+ IPerfManager,
+ IPerfManagerProvider,
+ INotificationListener,
+ IPlugin,
+ IDiagnosticLogger,
+ ITelemetryPluginChain,
+ ICustomProperties,
+ INotificationManager,
+ IProcessTelemetryContext,
+ ILoadedPlugin
+} from "@microsoft/applicationinsights-core-js";
+
+export {
+ IConfig,
+ IDependencyTelemetry,
+ IPageViewPerformanceTelemetry,
+ IPageViewTelemetry,
+ IExceptionTelemetry,
+ IAutoExceptionTelemetry,
+ ITraceTelemetry,
+ IMetricTelemetry,
+ IEventTelemetry,
+ IAppInsights,
+ eSeverityLevel,
+ IRequestHeaders,
+ EventPersistence
+} from "@microsoft/applicationinsights-common";
+
+export { ISenderConfig } from "@microsoft/applicationinsights-channel-js";
+
+export { IAppInsightsInternal } from "@microsoft/applicationinsights-analytics-js";
+
+export {
+ IDependenciesPlugin,
+ DependencyListenerFunction,
+ DependencyInitializerFunction,
+ IDependencyInitializerHandler,
+ IDependencyListenerHandler
+} from "@microsoft/applicationinsights-dependencies-js";
+
+export {
+ ICfgSyncPlugin,
+ ICfgSyncConfig,
+ ICfgSyncEvent,
+ ICfgSyncMode,
+ NonOverrideCfg,
+ OnCompleteCallback,
+ SendGetFunction
+} from "@microsoft/applicationinsights-cfgsync-js";
+
+// ----------------------------------------------------------------------------------------------------
+// End of Additional exports
+// ----------------------------------------------------------------------------------------------------
+
function _logWarn(aiName:string, message:string) {
// TODO: Find better place to warn to console when SDK initialization fails
diff --git a/AISKU/src/applicationinsights-web.ts b/AISKU/src/applicationinsights-web.ts
index b26f55015..0ad8ca2b3 100644
--- a/AISKU/src/applicationinsights-web.ts
+++ b/AISKU/src/applicationinsights-web.ts
@@ -57,7 +57,7 @@ export {
EventPersistence
} from "@microsoft/applicationinsights-common";
export { Sender, ISenderConfig } from "@microsoft/applicationinsights-channel-js";
-export { ApplicationInsights as ApplicationAnalytics, IAppInsightsInternal } from "@microsoft/applicationinsights-analytics-js";
+export { ApplicationInsights as ApplicationAnalytics, IAppInsightsInternal, IAnalyticsConfig } from "@microsoft/applicationinsights-analytics-js";
export { PropertiesPlugin } from "@microsoft/applicationinsights-properties-js";
export {
AjaxPlugin as DependenciesPlugin, IDependenciesPlugin,
diff --git a/AISKULight/Tests/Unit/src/AISKULightSize.Tests.ts b/AISKULight/Tests/Unit/src/AISKULightSize.Tests.ts
index 02e7838bf..a8d3baf45 100644
--- a/AISKULight/Tests/Unit/src/AISKULightSize.Tests.ts
+++ b/AISKULight/Tests/Unit/src/AISKULightSize.Tests.ts
@@ -52,11 +52,11 @@ function _checkSize(checkType: string, maxSize: number, size: number, isNightly:
export class AISKULightSizeCheck extends AITestClass {
private readonly MAX_RAW_SIZE = 93;
- private readonly MAX_BUNDLE_SIZE = 93;
- private readonly MAX_RAW_DEFLATE_SIZE = 38;
- private readonly MAX_BUNDLE_DEFLATE_SIZE = 38;
+ private readonly MAX_BUNDLE_SIZE = 94;
+ private readonly MAX_RAW_DEFLATE_SIZE = 39;
+ private readonly MAX_BUNDLE_DEFLATE_SIZE = 39;
private readonly rawFilePath = "../dist/es5/applicationinsights-web-basic.min.js";
- private readonly currentVer = "3.3.8";
+ private readonly currentVer = "3.3.9";
private readonly prodFilePath = `../browser/es5/aib.${this.currentVer[0]}.min.js`;
public testInitialize() {
diff --git a/AISKULight/package.json b/AISKULight/package.json
index 01b64c769..15e51a812 100644
--- a/AISKULight/package.json
+++ b/AISKULight/package.json
@@ -1,6 +1,6 @@
{
"name": "@microsoft/applicationinsights-web-basic",
- "version": "3.3.8",
+ "version": "3.3.9",
"description": "Microsoft Application Insights JavaScript SDK - Web Basic",
"homepage": "https://github.com/microsoft/ApplicationInsights-JS#readme",
"author": "Microsoft Application Insights Team",
@@ -58,9 +58,9 @@
"dependencies": {
"@microsoft/dynamicproto-js": "^2.0.3",
"@microsoft/applicationinsights-shims": "3.0.1",
- "@microsoft/applicationinsights-common": "3.3.8",
- "@microsoft/applicationinsights-channel-js": "3.3.8",
- "@microsoft/applicationinsights-core-js": "3.3.8",
+ "@microsoft/applicationinsights-common": "3.3.9",
+ "@microsoft/applicationinsights-channel-js": "3.3.9",
+ "@microsoft/applicationinsights-core-js": "3.3.9",
"@nevware21/ts-utils": ">= 0.11.8 < 2.x",
"@nevware21/ts-async": ">= 0.5.4 < 2.x"
},
diff --git a/README.md b/README.md
index 30ebc8e73..3b83a990b 100644
--- a/README.md
+++ b/README.md
@@ -119,19 +119,23 @@ The current version of the snippet is version 8, the version is identified by th
```html
```
@@ -176,6 +180,10 @@ The available configuration options are: -
| onInit | function(aiSdk) { ... } *[optional]* | This callback function which is called after the main SDK script has been successfully loaded and initialized from the CDN (based on the src value), it is passed a reference to the sdk instance that it is being called for and it is also called _before_ the first initial page view. If the SDK has already been loaded and initialized this callback will still be called. NOTE: As this callback is called during the processing of the sdk.queue array you CANNOT add any additional items to the queue as they will be ignored and dropped. (Added as part of snippet version 5 -- the sv:"#" value within the snippet script, the current version is 7)
| cfg | object **[required]** | The configuration passed to the Application Insights SDK during initialization.
| sri | boolean *[optional]* | Custom optional value to specify whether to fetch the snippet from an integrity file and perform an integrity check. When this option is used, the integrity file is loaded first, affecting the load order and script execution. Hence the ld option will be ignored. Additionally, if the page navigates away before the integrity file is loaded, some events may be lost.
+| pl | boolean *[optional]* | Custom optional value to specify whether to enable the Trusted Type policy check on the snippet.
+| pn | string *[optional]* | Custom optional value to specify the name of the Trusted Type policy that would be implemented on the snippet, default is 'aiPolicy'.
+| ttp | TrustedTypePolicy *[optional]* | Custom optional value to specify the Trusted Type policy that would be applied on the snippet src.
+| nt | string *[optional]* | Custom optional value to specify the nonce attribute value that will be applied to the script tag when it is added to the page.
#### Example using the snippet onInit callback
@@ -375,84 +383,145 @@ The differences between a telemetry initializer and a dependency initializer are
- [How to add more details in my Exception Telemetry?](https://microsoft.github.io/ApplicationInsights-JS/exceptionTelemetry)
-## Configuration
+## [Configuration](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-web/interfaces/IConfiguration.html)
Most configuration fields are named such that they can be defaulted to falsey. All fields are optional except for `instrumentationKey` or a `connectionString` containing the instrumentation key.
| Name | Type | Default | Description |
|------|------|---------|-------------|
-| instrumentationKey | string [**Required if `connectionString` not supplied**]| null | Instrumentation key that you obtained from the Azure Portal. |
-| connectionString | string [**Require if `instrumentationKey` not supplied**] | null | The Connection string that you obtained from the Azure portal |
-| accountId | string | null | An optional account id, if your app groups users into accounts. No spaces, commas, semicolons, equals, or vertical bars |
-| sessionRenewalMs | numeric | 1800000 | A session is logged if the user is inactive for this amount of time in milliseconds. Default is 30 minutes |
-| sessionExpirationMs | numeric | 86400000 | A session is logged if it has continued for this amount of time in milliseconds. Default is 24 hours |
-| maxBatchSizeInBytes | numberic | 10000 | Max size of telemetry batch. If a batch exceeds this limit, it is immediately sent and a new batch is started |
-| maxBatchInterval | numeric | 15000 | How long to batch telemetry for before sending (milliseconds) |
-| disableExceptionTracking | boolean || false | If true, exceptions are not autocollected. Default is false. |
-| disableTelemetry | boolean | false | If true, telemetry is not collected or sent. Default is false. |
-| enableDebug | boolean | false | If true, **internal** debugging data is thrown as an exception **instead** of being logged, regardless of SDK logging settings. Default is false. ***Note:*** Enabling this setting will result in dropped telemetry whenever an internal error occurs. This can be useful for quickly identifying issues with your configuration or usage of the SDK. If you do not want to lose telemetry while debugging, consider using `loggingLevelConsole` or `loggingLevelTelemetry` instead of `enableDebug`.
+| [instrumentationKey](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-web/interfaces/IConfiguration.html#instrumentationKey) | string [**Required if `connectionString` not supplied**]| null | Instrumentation key that you obtained from the Azure Portal. |
+| [connectionString](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-web/interfaces/IConfiguration.html#connectionString) | string [**Require if `instrumentationKey` not supplied**] | null | The Connection string that you obtained from the Azure portal |
+| [accountId](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-web/interfaces/IConfig.html#accountId) | string | null | An optional account id, if your app groups users into accounts. No spaces, commas, semicolons, equals, or vertical bars |
+| [sessionRenewalMs](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-web/interfaces/IConfig.html#sessionRenewalMs) | numeric | 1800000 | A session is logged if the user is inactive for this amount of time in milliseconds. Default is 30 minutes |
+| [sessionExpirationMs](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-web/interfaces/IConfig.html#sessionExpirationMs) | numeric | 86400000 | A session is logged if it has continued for this amount of time in milliseconds. Default is 24 hours |
+| [maxBatchSizeInBytes](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-web/interfaces/IConfig.html#maxBatchSizeInBytes) | numberic | 10000 | Max size of telemetry batch. If a batch exceeds this limit, it is immediately sent and a new batch is started |
+| [maxBatchInterval](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-web/interfaces/IConfig.html#maxBatchInterval) | numeric | 15000 | How long to batch telemetry for before sending (milliseconds) |
+| [disableExceptionTracking](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-web/interfaces/IConfig.html#disableExceptionTracking) | boolean || false | If true, exceptions are not autocollected. Default is false. |
+| [disableTelemetry](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-web/interfaces/IConfig.html#disableTelemetry) | boolean | false | If true, telemetry is not collected or sent. Default is false. |
+| [enableDebug](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-web/interfaces/IConfiguration.html#enableDebug) | boolean | false | If true, **internal** debugging data is thrown as an exception **instead** of being logged, regardless of SDK logging settings. Default is false. ***Note:*** Enabling this setting will result in dropped telemetry whenever an internal error occurs. This can be useful for quickly identifying issues with your configuration or usage of the SDK. If you do not want to lose telemetry while debugging, consider using `loggingLevelConsole` or `loggingLevelTelemetry` instead of `enableDebug`.
| enableDebugExceptions | boolean | false | Removed from v3.x, Prior to v2.8.12 this was the only supported value and the documented `enableDebug` was incorrect, since v2.8.12 both `enableDebug` and `enableDebugExceptions` is supported.
-| loggingLevelConsole | numeric | 0 | Logs **internal** Application Insights errors to console. 0: off, 1: Critical errors only, 2: Everything (errors & warnings) |
-| loggingLevelTelemetry | numeric | 1 | Sends **internal** Application Insights errors as telemetry. 0: off, 1: Critical errors only, 2: Everything (errors & warnings) |
-| diagnosticLogInterval | numeric | 10000 | (internal) Polling interval (in ms) for internal logging queue |
-| samplingPercentage | numeric | 100 | Percentage of events that will be sent. Default is 100, meaning all events are sent. Set this if you wish to preserve your datacap for large-scale applications. |
-| autoTrackPageVisitTime | boolean | false | If true, on a pageview, the _previous_ instrumented page's view time is tracked and sent as telemetry and a new timer is started for the current pageview. It is sent as a custom metric named `PageVisitTime` in `milliseconds` and is calculated via the Date [now()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/now) function (if available) and falls back to (new Date()).[getTime()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/getTime) if now() is unavailable (IE8 or less). Default is false. |
-| disableAjaxTracking | boolean | false | If true, Ajax calls are not autocollected. Default is false. |
-| disableFetchTracking | boolean | false | If true, Fetch requests are not autocollected. Default is false (Since v2.8.0, previously true) |
-| excludeRequestFromAutoTrackingPatterns | string[] \| RegExp[] | undefined | Provide a way to exclude specific route from automatic tracking for XMLHttpRequest or Fetch request. If defined, for an ajax / fetch request that the request url matches with the regex patterns, auto tracking is turned off. Default is undefined. |
-| addRequestContext | (requestContext: IRequestionContext) => {[key: string]: any} | undefined | Provide a way to enrich dependencies logs with context at the beginning of api call. Default is undefined. You will need to check if `xhr` exists if you configure `xhr` related conetext. You will need to check if `fetch request` and `fetch response` exist if you configure `fetch` related context. Otherwise you may not get the data you need. |
-| overridePageViewDuration | boolean | false | If true, default behavior of trackPageView is changed to record end of page view duration interval when trackPageView is called. If false and no custom duration is provided to trackPageView, the page view performance is calculated using the navigation timing API. Default is false. |
-| maxAjaxCallsPerView | numeric | 500 | Default 500 - controls how many ajax calls will be monitored per page view. Set to -1 to monitor all (unlimited) ajax calls on the page. |
-| disableDataLossAnalysis | boolean | true | If false, internal telemetry sender buffers will be checked at startup for items not yet sent. |
-| disableCorrelationHeaders | boolean | false | If false, the SDK will add two headers ('Request-Id' and 'Request-Context') to all dependency requests to correlate them with corresponding requests on the server side. Default is false. |
-| correlationHeaderExcludedDomains | string[] | undefined | Disable correlation headers for specific domains |
-| correlationHeaderExcludePatterns | regex[] | undefined | Disable correlation headers using regular expressions |
-| correlationHeaderDomains | string[] | undefined | Enable correlation headers for specific domains |
-| disableFlushOnBeforeUnload | boolean | false | Default false. If true, flush method will not be called when onBeforeUnload event triggers |
-| enableSessionStorageBuffer | boolean | true | Default true. If true, the buffer with all unsent telemetry is stored in session storage. The buffer is restored on page load |
-| cookieCfg | [ICookieCfgConfig](#ICookieMgrConfig) [Optional] (Since 2.6.0) | undefined | Defaults to cookie usage enabled see [ICookieCfgConfig](#ICookieMgrConfig) settings for full defaults. |
-| ~~isCookieUseDisabled~~ disableCookiesUsage | alias for [`cookieCfg.enabled`](#ICookieMgrConfig) [Optional] | false | Default false. A boolean that indicates whether to disable the use of cookies by the SDK. If true, the SDK will not store or read any data from cookies. isCookieUseDisable is deprecated in favor of disableCookiesUsage, when both are provided disableCookiesUsage take precedence. (Since v2.6.0) If `cookieCfg.enabled` is defined it will take precedence over these values, Cookie usage can be re-enabled after initialization via the core.getCookieMgr().setEnabled(true). |
-| cookieDomain | alias for [`cookieCfg.domain`](#ICookieMgrConfig) [Optional] | null | Custom cookie domain. This is helpful if you want to share Application Insights cookies across subdomains. (Since v2.6.0) If `cookieCfg.domain` is defined it will take precedence over this value. |
-| cookiePath | alias for [`cookieCfg.path`](#ICookieMgrConfig) [Optional] (Since 2.6.0) | null | Custom cookie path. This is helpful if you want to share Application Insights cookies behind an application gateway. If `cookieCfg.path` is defined it will take precedence over this value. |
-| isRetryDisabled | boolean | false | Default false. If false, retry on 206 (partial success), 408 (timeout), 429 (too many requests), 500 (internal server error), 503 (service unavailable), and 0 (offline, only if detected) |
-| isStorageUseDisabled | boolean | false | If true, the SDK will not store or read any data from local and session storage. Default is false. |
-| isBeaconApiDisabled | boolean | true | If false, the SDK will send all telemetry using the [Beacon API](https://www.w3.org/TR/beacon) |
-| disableXhr | boolean | false | Don't use XMLHttpRequest or XDomainRequest (for IE < 9) by default instead attempt to use fetch() or sendBeacon. If no other transport is available it will still use XMLHttpRequest |
-| onunloadDisableBeacon | boolean | false | Default false. when tab is closed, the SDK will send all remaining telemetry using the [Beacon API](https://www.w3.org/TR/beacon) |
-| onunloadDisableFetch | boolean | false | If fetch keepalive is supported do not use it for sending events during unload, it may still fallback to fetch() without keepalive |
-| sdkExtension | string | null | Sets the sdk extension name. Only alphabetic characters are allowed. The extension name is added as a prefix to the 'ai.internal.sdkVersion' tag (e.g. 'ext_javascript:2.0.0'). Default is null. |
-| isBrowserLinkTrackingEnabled | boolean | false | Default is false. If true, the SDK will track all [Browser Link](https://docs.microsoft.com/en-us/aspnet/core/client-side/using-browserlink) requests. |
-| appId | string | null | AppId is used for the correlation between AJAX dependencies happening on the client-side with the server-side requests. When Beacon API is enabled, it cannot be used automatically, but can be set manually in the configuration. Default is null |
-| enableCorsCorrelation | boolean | false | If true, the SDK will add two headers ('Request-Id' and 'Request-Context') to all CORS requests to correlate outgoing AJAX dependencies with corresponding requests on the server side. Default is false |
-| namePrefix | string | undefined | An optional value that will be used as name postfix for localStorage and session cookie name.
-| sessionCookiePostfix | string | undefined | An optional value that will be used as name postfix for session cookie name. If undefined, namePrefix is used as name postfix for session cookie name.
-| userCookiePostfix | string | undefined | An optional value that will be used as name postfix for user cookie name. If undefined, no postfix is added on user cookie name.
-| enableAutoRouteTracking | boolean | false | Automatically track route changes in Single Page Applications (SPA). If true, each route change will send a new Pageview to Application Insights. Hash route changes changes (`example.com/foo#bar`) are also recorded as new page views.
-| enableRequestHeaderTracking | boolean | false | If true, AJAX & Fetch request headers is tracked, default is false. If ignoreHeaders is not configured, Authorization and X-API-Key headers are not logged.
-| enableResponseHeaderTracking | boolean | false | If true, AJAX & Fetch request's response headers is tracked, default is false. If ignoreHeaders is not configured, WWW-Authenticate header is not logged.
-| enableAjaxErrorStatusText | boolean | false | Default false. If true, include response error data text | boolean in dependency event on failed AJAX requests.
-| enableAjaxPerfTracking | boolean | false | Default false. Flag to enable looking up and including additional browser window.performance timings in the reported ajax (XHR and fetch) reported metrics.
-| maxAjaxPerfLookupAttempts | numeric | 3 | Defaults to 3. The maximum number of times to look for the window.performance timings (if available), this is required as not all browsers populate the window.performance before reporting the end of the XHR request and for fetch requests this is added after its complete.
-| ajaxPerfLookupDelay | numeric | 25 | Defaults to 25ms. The amount of time to wait before re-attempting to find the windows.performance timings for an ajax request, time is in milliseconds and is passed directly to setTimeout().
-| distributedTracingMode | numeric or `DistributedTracingModes` | `DistributedTracingModes.AI_AND_W3C` | Sets the distributed tracing mode. If AI_AND_W3C mode or W3C mode is set, W3C trace context headers (traceparent/tracestate) will be generated and included in all outgoing requests. AI_AND_W3C is provided for back-compatibility with any legacy Application Insights instrumented services.
-| enableUnhandledPromiseRejectionTracking | boolean | false | If true, unhandled promise rejections will be autocollected and reported as a javascript error. When disableExceptionTracking is true (dont track exceptions) the config value will be ignored and unhandled promise rejections will not be reported.
-| disableInstrumentationKeyValidation | boolean | false | If true, instrumentation key validation check is bypassed. Default value is false.
-| enablePerfMgr | boolean | false | [Optional] When enabled (true) this will create local perfEvents for code that has been instrumented to emit perfEvents (via the doPerf() helper). This can be used to identify performance issues within the SDK based on your usage or optionally within your own instrumented code. [More details are available by the basic documentation](https://microsoft.github.io/ApplicationInsights-JS/PerformanceMonitoring). Since v2.5.7
-| perfEvtsSendAll | boolean | false | [Optional] When _enablePerfMgr_ is enabled and the [IPerfManager](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-core-js/interfaces/IPerfManager.html) fires a [INotificationManager](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-core-js/interfaces/INotificationManager.html).perfEvent() this flag determines whether an event is fired (and sent to all listeners) for all events (true) or only for 'parent' events (false <default>). A parent [IPerfEvent](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-core-js/interfaces/IPerfEvent.html) is an event where no other IPerfEvent is still running at the point of this event being created and it's _parent_ property is not null or undefined. Since v2.5.7
-| createPerfMgr | (core: IAppInsightsCore, notificationManager: INotificationManager) => IPerfManager | undefined | Callback function that will be called to create a the IPerfManager instance when required and ```enablePerfMgr``` is enabled, this enables you to override the default creation of a PerfManager() without needing to ```setPerfMgr()``` after initialization.
-| idLength | numeric | 22 | [Optional] Identifies the default length used to generate new random session and user id's. Defaults to 22, previous default value was 5 (v2.5.8 or less), if you need to keep the previous maximum length you should set this value to 5.
-| customHeaders | `[{header: string, value: string}]` | undefined | [Optional] The ability for the user to provide extra headers when using a custom endpoint. customHeaders will not be added on browser shutdown moment when beacon sender is used. And adding custom headers is not supported on IE9 or earlier.
-| convertUndefined | `any` | undefined | [Optional] Provide user an option to convert undefined field to user defined value.
-| eventsLimitInMem | number | 10000 | [Optional] The number of events that can be kept in memory before the SDK starts to drop events when not using Session Storage (the default).
-| disableIkeyDeprecationMessage | boolean | true | [Optional] Disable instrumentation Key deprecation error message. If true, error message will NOT be sent. **Note: instrumentation key support will end soon**, see aka.ms/IkeyMigrate for more details.
-| bufferOverride since 2.8.12 | IStorageBuffer | undefined | [Optional] Identifies a simple interface to allow you to override the storage mechanism used for tracking unsent and unacknowledged events, when not provided defaults to using SessionStorage interface. You MUST supply both the `getItem` and `setItem` functions when defined.
-| storagePrefix | string[] | undefined | [Optional] An optional value that will be added as name prefix for storage name. |
-| featureOptIn (#feature) since 3.0.3 | IFeatureOptIn | undefined | [Optional] Set Feature opt in details. |
-| throttleMgrCfg since 3.0.3 | `{[key: number]: IThrottleMgrConfig}` | undefined | [Optional] Set throttle mgr configuration by key. |
+| [loggingLevelConsole](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-web/interfaces/IConfiguration.html#loggingLevelConsole) | numeric | 0 | Logs **internal** Application Insights errors to console. 0: off, 1: Critical errors only, 2: Everything (errors & warnings) |
+| [loggingLevelTelemetry](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-web/interfaces/IConfiguration.html#loggingLevelTelemetry) | numeric | 1 | Sends **internal** Application Insights errors as telemetry. 0: off, 1: Critical errors only, 2: Everything (errors & warnings) |
+| [diagnosticLogInterval](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-web/interfaces/IConfiguration.html#diagnosticLogInterval) | numeric | 10000 | (internal) Polling interval (in ms) for internal logging queue |
+| [samplingPercentage](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-web/interfaces/IConfig.html#samplingPercentage) | numeric | 100 | Percentage of events that will be sent. Default is 100, meaning all events are sent. Set this if you wish to preserve your datacap for large-scale applications. |
+| [autoTrackPageVisitTime](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-web/interfaces/IConfig.html#autoTrackPageVisitTime) | boolean | false | If true, on a pageview, the _previous_ instrumented page's view time is tracked and sent as telemetry and a new timer is started for the current pageview. It is sent as a custom metric named `PageVisitTime` in `milliseconds` and is calculated via the Date [now()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/now) function (if available) and falls back to (new Date()).[getTime()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/getTime) if now() is unavailable (IE8 or less). Default is false. |
+| [disableAjaxTracking](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-web/interfaces/IConfig.html#disableAjaxTracking) | boolean | false | If true, Ajax calls are not autocollected. Default is false. |
+| [disableFetchTracking](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-web/interfaces/IConfig.html#disableFetchTracking) | boolean | false | If true, Fetch requests are not autocollected. Default is false (Since v2.8.0, previously true) |
+| [excludeRequestFromAutoTrackingPatterns](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-web/interfaces/IConfig.html#excludeRequestFromAutoTrackingPatterns) | string[] \| RegExp[] | undefined | Provide a way to exclude specific route from automatic tracking for XMLHttpRequest or Fetch request. If defined, for an ajax / fetch request that the request url matches with the regex patterns, auto tracking is turned off. Default is undefined. |
+| [addRequestContext](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-web/interfaces/IConfig.html#addRequestContext) | (requestContext: IRequestionContext) => {[key: string]: any} | undefined | Provide a way to enrich dependencies logs with context at the beginning of api call. Default is undefined. You will need to check if `xhr` exists if you configure `xhr` related conetext. You will need to check if `fetch request` and `fetch response` exist if you configure `fetch` related context. Otherwise you may not get the data you need. |
+| [overridePageViewDuration](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-web/interfaces/IConfig.html#overridePageViewDuration) | boolean | false | If true, default behavior of trackPageView is changed to record end of page view duration interval when trackPageView is called. If false and no custom duration is provided to trackPageView, the page view performance is calculated using the navigation timing API. Default is false. |
+| [maxAjaxCallsPerView](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-web/interfaces/IConfig.html#maxAjaxCallsPerView) | numeric | 500 | Default 500 - controls how many ajax calls will be monitored per page view. Set to -1 to monitor all (unlimited) ajax calls on the page. |
+| [disableDataLossAnalysis](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-web/interfaces/IConfig.html#disableDataLossAnalysis) | boolean | true | If false, internal telemetry sender buffers will be checked at startup for items not yet sent. |
+| [disableCorrelationHeaders](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-web/interfaces/IConfig.html#disableCorrelationHeaders) | boolean | false | If false, the SDK will add two headers ('Request-Id' and 'Request-Context') to all dependency requests to correlate them with corresponding requests on the server side. Default is false. |
+| [correlationHeaderExcludedDomains](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-web/interfaces/IConfig.html#correlationHeaderExcludedDomains) | string[] | undefined | Disable correlation headers for specific domains |
+| [correlationHeaderExcludePatterns](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-web/interfaces/IConfig.html#correlationHeaderExcludePatterns) | regex[] | undefined | Disable correlation headers using regular expressions |
+| [correlationHeaderDomains](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-web/interfaces/IConfig.html#correlationHeaderDomains) | string[] | undefined | Enable correlation headers for specific domains |
+| [disableFlushOnBeforeUnload](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-web/interfaces/IConfig.html#disableFlushOnBeforeUnload) | boolean | false | Default false. If true, flush method will not be called when onBeforeUnload event triggers |
+| [enableSessionStorageBuffer](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-web/interfaces/IConfig.html#enableSessionStorageBuffer) | boolean | true | Default true. If true, the buffer with all unsent telemetry is stored in session storage. The buffer is restored on page load |
+| [cookieCfg](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-web/interfaces/IConfiguration.html#cookieCfg) | [ICookieCfgConfig](#ICookieMgrConfig) [Optional] (Since 2.6.0) | undefined | Defaults to cookie usage enabled see [ICookieCfgConfig](#ICookieMgrConfig) settings for full defaults. |
+| [~~isCookieUseDisabled~~ disableCookiesUsage](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-web/interfaces/IConfig.html#disableCookiesUsage) | alias for [`cookieCfg.enabled`](#ICookieMgrConfig) [Optional] | false | Default false. A boolean that indicates whether to disable the use of cookies by the SDK. If true, the SDK will not store or read any data from cookies. isCookieUseDisable is deprecated in favor of disableCookiesUsage, when both are provided disableCookiesUsage take precedence. (Since v2.6.0) If `cookieCfg.enabled` is defined it will take precedence over these values, Cookie usage can be re-enabled after initialization via the core.getCookieMgr().setEnabled(true). |
+| [cookieDomain](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-web/interfaces/IConfiguration.html#cookieDomain) | alias for [`cookieCfg.domain`](#ICookieMgrConfig) [Optional] | null | Custom cookie domain. This is helpful if you want to share Application Insights cookies across subdomains. (Since v2.6.0) If `cookieCfg.domain` is defined it will take precedence over this value. |
+| [cookiePath](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-web/interfaces/IConfiguration.html#cookiePath) | alias for [`cookieCfg.path`](#ICookieMgrConfig) [Optional] (Since 2.6.0) | null | Custom cookie path. This is helpful if you want to share Application Insights cookies behind an application gateway. If `cookieCfg.path` is defined it will take precedence over this value. |
+| [isRetryDisabled](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-web/interfaces/IConfig.html#isRetryDisabled) | boolean | false | Default false. If false, retry on 206 (partial success), 408 (timeout), 429 (too many requests), 500 (internal server error), 503 (service unavailable), and 0 (offline, only if detected) |
+| [isStorageUseDisabled](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-web/interfaces/IConfig.html#isStorageUseDisabled) | boolean | false | If true, the SDK will not store or read any data from local and session storage. Default is false. |
+| [isBeaconApiDisabled](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-web/interfaces/IConfig.html#isBeaconApiDisabled) | boolean | true | If false, the SDK will send all telemetry using the [Beacon API](https://www.w3.org/TR/beacon) |
+| [disableXhr](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-web/interfaces/IConfig.html#disableXhr) | boolean | false | Don't use XMLHttpRequest or XDomainRequest (for IE < 9) by default instead attempt to use fetch() or sendBeacon. If no other transport is available it will still use XMLHttpRequest |
+| [onunloadDisableBeacon](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-web/interfaces/IConfig.html#onunloadDisableBeacon) | boolean | false | Default false. when tab is closed, the SDK will send all remaining telemetry using the [Beacon API](https://www.w3.org/TR/beacon) |
+| [onunloadDisableFetch](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-web/interfaces/IConfig.html#onunloadDisableFetch) | boolean | false | If fetch keepalive is supported do not use it for sending events during unload, it may still fallback to fetch() without keepalive |
+| [sdkExtension](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-web/interfaces/IConfig.html#sdkExtension) | string | null | Sets the sdk extension name. Only alphabetic characters are allowed. The extension name is added as a prefix to the 'ai.internal.sdkVersion' tag (e.g. 'ext_javascript:2.0.0'). Default is null. |
+| [isBrowserLinkTrackingEnabled](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-web/interfaces/IConfig.html#isBrowserLinkTrackingEnabled) | boolean | false | Default is false. If true, the SDK will track all [Browser Link](https://docs.microsoft.com/en-us/aspnet/core/client-side/using-browserlink) requests. |
+| [appId](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-web/interfaces/IConfig.html#appId) | string | null | AppId is used for the correlation between AJAX dependencies happening on the client-side with the server-side requests. When Beacon API is enabled, it cannot be used automatically, but can be set manually in the configuration. Default is null |
+| [enableCorsCorrelation](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-web/interfaces/IConfig.html#enableCorsCorrelation) | boolean | false | If true, the SDK will add two headers ('Request-Id' and 'Request-Context') to all CORS requests to correlate outgoing AJAX dependencies with corresponding requests on the server side. Default is false |
+| [namePrefix](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-web/interfaces/IConfig.html#namePrefix) | string | undefined | An optional value that will be used as name postfix for localStorage and session cookie name.
+| [sessionCookiePostfix](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-web/interfaces/IConfig.html#sessionCookiePostfix) | string | undefined | An optional value that will be used as name postfix for session cookie name. If undefined, namePrefix is used as name postfix for session cookie name.
+| [userCookiePostfix](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-web/interfaces/IConfig.html#userCookiePostfix) | string | undefined | An optional value that will be used as name postfix for user cookie name. If undefined, no postfix is added on user cookie name.
+| [enableAutoRouteTracking](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-web/interfaces/IConfig.html#enableAutoRouteTracking) | boolean | false | Automatically track route changes in Single Page Applications (SPA). If true, each route change will send a new Pageview to Application Insights. Hash route changes changes (`example.com/foo#bar`) are also recorded as new page views.
+| [enableRequestHeaderTracking](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-web/interfaces/IConfig.html#enableRequestHeaderTracking) | boolean | false | If true, AJAX & Fetch request headers is tracked, default is false. If ignoreHeaders is not configured, Authorization and X-API-Key headers are not logged.
+| [enableResponseHeaderTracking](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-web/interfaces/IConfig.html#enableResponseHeaderTracking) | boolean | false | If true, AJAX & Fetch request's response headers is tracked, default is false. If ignoreHeaders is not configured, WWW-Authenticate header is not logged.
+| [enableAjaxErrorStatusText](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-web/interfaces/IConfig.html#enableAjaxErrorStatusText) | boolean | false | Default false. If true, include response error data text | boolean in dependency event on failed AJAX requests.
+| [enableAjaxPerfTracking](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-web/interfaces/IConfig.html#enableAjaxPerfTracking) | boolean | false | Default false. Flag to enable looking up and including additional browser window.performance timings in the reported ajax (XHR and fetch) reported metrics.
+| [maxAjaxPerfLookupAttempts](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-web/interfaces/IConfig.html#maxAjaxPerfLookupAttempts) | numeric | 3 | Defaults to 3. The maximum number of times to look for the window.performance timings (if available), this is required as not all browsers populate the window.performance before reporting the end of the XHR request and for fetch requests this is added after its complete.
+| [ajaxPerfLookupDelay](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-web/interfaces/IConfig.html#ajaxPerfLookupDelay) | numeric | 25 | Defaults to 25ms. The amount of time to wait before re-attempting to find the windows.performance timings for an ajax request, time is in milliseconds and is passed directly to setTimeout().
+| [distributedTracingMode](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-web/interfaces/IConfig.html#distributedTracingMode) | numeric or `DistributedTracingModes` | `DistributedTracingModes.AI_AND_W3C` | Sets the distributed tracing mode. If AI_AND_W3C mode or W3C mode is set, W3C trace context headers (traceparent/tracestate) will be generated and included in all outgoing requests. AI_AND_W3C is provided for back-compatibility with any legacy Application Insights instrumented services.
+| [enableUnhandledPromiseRejectionTracking](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-web/interfaces/IConfig.html#enableUnhandledPromiseRejectionTracking) | boolean | false | If true, unhandled promise rejections will be autocollected and reported as a javascript error. When disableExceptionTracking is true (dont track exceptions) the config value will be ignored and unhandled promise rejections will not be reported.
+| [disableInstrumentationKeyValidation](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-web/interfaces/IConfiguration.html#disableInstrumentationKeyValidation) | boolean | false | If true, instrumentation key validation check is bypassed. Default value is false.
+| [enablePerfMgr](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-web/interfaces/IConfiguration.html#enablePerfMgr) | boolean | false | [Optional] When enabled (true) this will create local perfEvents for code that has been instrumented to emit perfEvents (via the doPerf() helper). This can be used to identify performance issues within the SDK based on your usage or optionally within your own instrumented code. [More details are available by the basic documentation](https://microsoft.github.io/ApplicationInsights-JS/PerformanceMonitoring). Since v2.5.7
+| [perfEvtsSendAll](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-web/interfaces/IConfiguration.html#perfEvtsSendAll) | boolean | false | [Optional] When _enablePerfMgr_ is enabled and the [IPerfManager](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-core-js/interfaces/IPerfManager.html) fires a [INotificationManager](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-core-js/interfaces/INotificationManager.html).perfEvent() this flag determines whether an event is fired (and sent to all listeners) for all events (true) or only for 'parent' events (false <default>). A parent [IPerfEvent](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-core-js/interfaces/IPerfEvent.html) is an event where no other IPerfEvent is still running at the point of this event being created and it's _parent_ property is not null or undefined. Since v2.5.7
+| [createPerfMgr](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-web/interfaces/IConfiguration.html#createPerfMgr) | (core: IAppInsightsCore, notificationManager: INotificationManager) => IPerfManager | undefined | Callback function that will be called to create a the IPerfManager instance when required and ```enablePerfMgr``` is enabled, this enables you to override the default creation of a PerfManager() without needing to ```setPerfMgr()``` after initialization.
+| [idLength](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-web/interfaces/IConfiguration.html#idLength) | numeric | 22 | [Optional] Identifies the default length used to generate new random session and user id's. Defaults to 22, previous default value was 5 (v2.5.8 or less), if you need to keep the previous maximum length you should set this value to 5.
+| [customHeaders](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-web/interfaces/IConfig.html#customHeaders) | `[{header: string, value: string}]` | undefined | [Optional] The ability for the user to provide extra headers when using a custom endpoint. customHeaders will not be added on browser shutdown moment when beacon sender is used. And adding custom headers is not supported on IE9 or earlier.
+| [convertUndefined](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-web/interfaces/IConfig.html#convertUndefined) | `any` | undefined | [Optional] Provide user an option to convert undefined field to user defined value.
+| [eventsLimitInMem](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-web/interfaces/IConfig.html#eventsLimitInMem) | number | 10000 | [Optional] The number of events that can be kept in memory before the SDK starts to drop events when not using Session Storage (the default).
+| [disableIkeyDeprecationMessage](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-web/interfaces/IConfig.html#disableIkeyDeprecationMessage) | boolean | true | [Optional] Disable instrumentation Key deprecation error message. If true, error message will NOT be sent. **Note: instrumentation key support will end soon**, see aka.ms/IkeyMigrate for more details.
+| [bufferOverride](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-web/interfaces/IConfig.html#bufferOverride) since 2.8.12 | IStorageBuffer | undefined | [Optional] Identifies a simple interface to allow you to override the storage mechanism used for tracking unsent and unacknowledged events, when not provided defaults to using SessionStorage interface. You MUST supply both the `getItem` and `setItem` functions when defined.
+| [storagePrefix](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-web/interfaces/IConfiguration.html#storagePrefix) | string[] | undefined | [Optional] An optional value that will be added as name prefix for storage name. |
+| [featureOptIn](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-web/interfaces/IConfiguration.html#featureOptIn) (#feature) since 3.0.3 | IFeatureOptIn | undefined | [Optional] Set Feature opt in details. |
+| [throttleMgrCfg](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-web/interfaces/IConfig.html#throttleMgrCfg) since 3.0.3 | `{[key: number]: IThrottleMgrConfig}` | undefined | [Optional] Set throttle mgr configuration by key. |
| retryCodes | number[] | undefined | Identifies the status codes that will cause event batches to be resent, when `null` or `undefined` the SDK will use it's defaults `[401, 408, 429, 500, 502, 503, 504]`. `403` was removed in version 3.1.1. |
-| [disablePageUnloadEvents](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-core-js/interfaces/IConfiguration.html#disablePageUnloadEvents) | string[] | undefined | [Optional] An array of the page unload events that you would like to be ignored. [See detailed documentation](https://microsoft.github.io/ApplicationInsights-JS/docs/PageUnloadEvents.html). Unload events include "beforeunload", "unload", "visibilitychange" (with 'hidden' state) and "pagehide". This can be used to avoid jQuery 3.7.1+ deprecation warnings by configuring as `disablePageUnloadEvents: ["unload"]`. |
-| [disablePageShowEvents](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-core-js/interfaces/IConfiguration.html#disablePageShowEvents) | string[] | undefined | [Optional] An array of page show events that you would like to be ignored. [See detailed documentation](https://microsoft.github.io/ApplicationInsights-JS/docs/PageUnloadEvents.html). Page Show events include "pageshow" and "visibilitychange" (with 'visible' state). |
-| expCfg since 3.3.1| [`IExceptionConfig`](https://github.com/microsoft/ApplicationInsights-JS/blob/main/shared/AppInsightsCommon/src/Interfaces/IExceptionTelemetry.ts) | undefined | Set additional configuration for exceptions, such as more scripts to include in the exception telemetry. |
+| [disablePageUnloadEvents](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-web/interfaces/IConfiguration.html#disablePageUnloadEvents) | string[] | undefined | [Optional] An array of the page unload events that you would like to be ignored. [See detailed documentation](https://microsoft.github.io/ApplicationInsights-JS/PageUnloadEvents.html). Unload events include "beforeunload", "unload", "visibilitychange" (with 'hidden' state) and "pagehide". This can be used to avoid jQuery 3.7.1+ deprecation warnings by configuring as `disablePageUnloadEvents: ["unload"]`. |
+| [disablePageShowEvents](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-web/interfaces/IConfiguration.html#disablePageShowEvents) | string[] | undefined | [Optional] An array of page show events that you would like to be ignored. [See detailed documentation](https://microsoft.github.io/ApplicationInsights-JS/PageUnloadEvents.html). Page Show events include "pageshow" and "visibilitychange" (with 'visible' state). |
+| [expCfg](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-web/interfaces/IConfiguration.html#expCfg) since 3.3.1| [`IExceptionConfig`](https://github.com/microsoft/ApplicationInsights-JS/blob/main/shared/AppInsightsCommon/src/Interfaces/IExceptionTelemetry.ts) | undefined | Set additional configuration for exceptions, such as more scripts to include in the exception telemetry. |
+
+### Page Unload and Visibility Event Handling
+
+Application Insights SDK uses page lifecycle events to reliably send telemetry data before your page closes or navigates away. These events are essential for ensuring no telemetry data is lost during navigation, page refreshes, or tab/browser closures.
+
+**What these configurations do:**
+- Control which browser events the SDK uses to detect when the browser is about to unload, navigate away, become unresponsive, or get hibernated (especially on mobile)
+- Ensure all batched events are sent and not lost due to the browser closing or the user navigating away
+- Affect ALL telemetry types (page views, events, dependencies, exceptions, etc.)
+- Allow you to avoid deprecated event warnings (from jQuery 3.7.1+ or Chrome) while maintaining functionality
+
+**About visibility state:**
+When a browser tab becomes hidden (switching to another tab) or visible (returning to the tab), the browser fires "visibilitychange" events with document.visibilityState changing to "hidden" or "visible". The SDK uses these events to optimize telemetry sending.
+
+```js
+const appInsights = new ApplicationInsights({
+ config: {
+ connectionString: 'YOUR_CONNECTION_STRING_GOES_HERE',
+ // Disable the deprecated 'unload' event to avoid jQuery 3.7.1+ deprecation warnings
+ // This also prevents Chrome's warnings about the unload event
+ disablePageUnloadEvents: ["unload"],
+ /* ...Other Configuration Options... */
+ }
+});
+appInsights.loadAppInsights();
+appInsights.trackPageView();
+```
+
+For more detailed information about browser compatibility and configuration options, see the [Page Unload Events documentation](https://microsoft.github.io/ApplicationInsights-JS/PageUnloadEvents.html).
+
+### Feature
+
+You can use the `featureOptIn` configuration to enable or customize specific SDK features.
+
+#### Available Feature Flags
+
+| Name | Default | Description | Note |
+|-------------|---------|----------------------------------------------|------------|
+| `zipPayload` | `none`*(version 3.3.7) | Enables compression using the Compression API to zip telemetry payloads. |If this feature is turned on and the CompressionStream API is available, the payload will be compressed using the CompressionStream API. Compression will only occur if the event is asynchronous. For events like unloads, compression will not be applied. Note: if user set payloadPreprocessor, this zip compression will not be applied.|
+
+* A default value of none means the SDK may automatically enable this feature in the future. To explicitly prevent this, set the feature to disable using FeatureOptInMode.disable.
+
+#### How to Enable a Feature
+
+To enable a feature such as `zipPayload`, set the `featureOptIn` property in the SDK configuration as shown below:
+
+```javascript
+const appInsights = new ApplicationInsights({
+ config: {
+ connectionString: "YOUR_CONNECTION_STRING",
+ // Other configuration options...
+ featureOptIn: {
+ zipPayload: {
+ mode: FeatureOptInMode.enable, // Set the opt-in status for the feature
+ blockCdnCfg: false, // Define whether to block changes from CDN config
+ } as IFeatureOptInDetails
+ }
+ }
+});
+```
+See [feature opt-in status](https://microsoft.github.io/ApplicationInsights-JS/WebConfig) for more details.
### Page Unload and Visibility Event Handling
@@ -537,22 +606,22 @@ const appInsights = new ApplicationInsights({
| Name | Type | Default | Extenstion | Description |
|------|------|---------|---------|-------------|
-| ignoreHeaders | string[] | ["Authorization", "X-API-Key", "WWW-Authenticate"] | DependenciesPlugin | AJAX & Fetch request and response headers to be ignored in log data. To override or discard the default, add an array with all headers to be excluded or an empty array to the configuration. Need to be defined in depenedency plugin extension config, see more [here](./extensions/applicationinsights-dependencies-js/README.md)
+| [ignoreHeaders](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-web/interfaces/IDependenciesPluginConfig.html#ignoreHeaders) | string[] | ["Authorization", "X-API-Key", "WWW-Authenticate"] | DependenciesPlugin | AJAX & Fetch request and response headers to be ignored in log data. To override or discard the default, add an array with all headers to be excluded or an empty array to the configuration. Need to be defined in depenedency plugin extension config, see more [here](./extensions/applicationinsights-dependencies-js/README.md)
-### ICookieMgrConfig
+### [ICookieMgrConfig](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-web/interfaces/ICookieMgrConfig.html)
Cookie Configuration for instance based cookie management added in version 2.6.0.
| Name | Type | Default | Description |
|------|------|---------|-------------|
-| enabled | boolean | true | A boolean that indicates whether the use of cookies by the SDK is enabled by the current instance. If false, the instance of the SDK initialized by this configuration will not store or read any data from cookies |
-| domain | string | null | Custom cookie domain. This is helpful if you want to share Application Insights cookies across subdomains. If not provided uses the value from root `cookieDomain` value. |
-| path | string | / | Specifies the path to use for the cookie, if not provided it will use any value from the root `cookiePath` value. |
-| ignoreCookies | string[] | undefined | Specify the cookie name(s) to be ignored, this will cause any matching cookie name to never be read or written. They may still be explicitly purged or deleted. You do not need to repeat the name in the `blockedCookies` configuration.(Since v2.8.8)
-| blockedCookies | string[] | undefined | Specify the cookie name(s) to never be written, this will cause any cookie name to never be created or updated, they will still be read unless also included in the ignoreCookies and may still be explicitly purged or deleted. If not provided defaults to the same list provided in ignoreCookies. (Since v2.8.8)
-| getCookie | `(name: string) => string` | null | Function to fetch the named cookie value, if not provided it will use the internal cookie parsing / caching. |
-| setCookie | `(name: string, value: string) => void` | null | Function to set the named cookie with the specified value, only called when adding or updating a cookie. |
-| delCookie | `(name: string, value: string) => void` | null | Function to delete the named cookie with the specified value, separated from setCookie to avoid the need to parse the value to determine whether the cookie is being added or removed.if not provided it will use the internal cookie parsing / caching. |
+| [enabled](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-web/interfaces/ICookieMgrConfig.html#enabled) | boolean | true | A boolean that indicates whether the use of cookies by the SDK is enabled by the current instance. If false, the instance of the SDK initialized by this configuration will not store or read any data from cookies |
+| [domain](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-web/interfaces/ICookieMgrConfig.html#domain) | string | null | Custom cookie domain. This is helpful if you want to share Application Insights cookies across subdomains. If not provided uses the value from root `cookieDomain` value. |
+| [path](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-web/interfaces/ICookieMgrConfig.html#path) | string | / | Specifies the path to use for the cookie, if not provided it will use any value from the root `cookiePath` value. |
+| [ignoreCookies](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-web/interfaces/ICookieMgrConfig.html#ignoreCookies) | string[] | undefined | Specify the cookie name(s) to be ignored, this will cause any matching cookie name to never be read or written. They may still be explicitly purged or deleted. You do not need to repeat the name in the `blockedCookies` configuration.(Since v2.8.8)
+| [blockedCookies](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-web/interfaces/ICookieMgrConfig.html#blockedCookies) | string[] | undefined | Specify the cookie name(s) to never be written, this will cause any cookie name to never be created or updated, they will still be read unless also included in the ignoreCookies and may still be explicitly purged or deleted. If not provided defaults to the same list provided in ignoreCookies. (Since v2.8.8)
+| [getCookie](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-web/interfaces/ICookieMgrConfig.html#getCookie) | `(name: string) => string` | null | Function to fetch the named cookie value, if not provided it will use the internal cookie parsing / caching. |
+| [setCookie](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-web/interfaces/ICookieMgrConfig.html#setCookie) | `(name: string, value: string) => void` | null | Function to set the named cookie with the specified value, only called when adding or updating a cookie. |
+| [delCookie](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-web/interfaces/ICookieMgrConfig.html#delCookie) | `(name: string, value: string) => void` | null | Function to delete the named cookie with the specified value, separated from setCookie to avoid the need to parse the value to determine whether the cookie is being added or removed.if not provided it will use the internal cookie parsing / caching. |
## Cookie Handling
@@ -645,6 +714,12 @@ This version comes with the bare minimum amount of features and functionalities
Click here for a [Type Error Fixed Guideline](https://microsoft.github.io/ApplicationInsights-JS/ExtensionErrorSteps)
+## Notification
+
+### Error Handler
+
+The SDK's error handler will send the error stack trace **without encryption**. This provides full visibility into errors for diagnostics and troubleshooting, but be aware that sensitive information might be included in error messages or stack traces.
+
## Build a new extension for the SDK
The SDK supports the ability to include multiple extensions at runtime. In order to create a new extension, please implement the following interface:
diff --git a/RELEASES.md b/RELEASES.md
index 177be91c7..11ec54e4d 100644
--- a/RELEASES.md
+++ b/RELEASES.md
@@ -2,6 +2,24 @@
> Note: ES3/IE8 compatibility will be removed in the future v3.x.x releases (scheduled for mid-late 2022), so if you need to retain ES3 compatibility you will need to remain on the 2.x.x versions of the SDK or your runtime will need install polyfill's to your ES3 environment before loading / initializing the SDK.
+## 3.3.9 (June 25th, 2025)
+
+This release contains an important fix for a change introduced in v3.3.7 that caused the `autoCaptureHandler` to incorrectly evaluate elements within `trackElementsType`, resulting in some click events not being auto-captured. See more details [here](https://github.com/microsoft/ApplicationInsights-JS/issues/2589).
+
+### Changelog
+
+- #2556 Update SDK Loader to rename the snippet postfix file to avoid CodeQL scanning issues
+- #2586 [AI][Task] 33246973: Update Readme on Error Handler
+- #2581 Export ICorrelationConfig interface from dependencies extension
+- #2587 Click Analytics - Fix capturning of HTML events
+
+## Web Snippet Release 1.2.2 (June 2nd, 2025)
+
+This release adds support for Trusted Types in the Application Insights JavaScript SDK snippet loader. See more details [here](https://github.com/microsoft/ApplicationInsights-JS/blob/main/tools/applicationinsights-web-snippet/trustedTypeSupport.md).
+
+### Changelog
+- #2407 Custom Trusted Type Policy Support for Snippet Script Injection
+
## 3.3.8 (May 22nd, 2025)
This release contains an important fix for a change introduced in v3.3.7 that caused a ReferenceError exception to be thrown when running in strict mode. See more details [here](https://github.com/microsoft/ApplicationInsights-JS/issues/2529).
@@ -16,7 +34,7 @@ This release contains an important fix for a change introduced in v3.3.7 that ca
### Potential breaking change
-This release contains a potential breaking change due to the new compress api feaure added. If you are using a Proxy to redirect your telemetry to your own endpoint or are relying on the events to be uncompressed (this feature is initially disabled and it is intended to be enabled by the service in the near future), it is recommended to either update collection endpoint to support GZip or to explicitly disable the feature. See more details [here](https://github.com/Microsoft/ApplicationInsights-JS?tab=readme-ov-file#feature).
+This release contains a potential breaking change due to the new compress api feature added. If you are using a Proxy to redirect your telemetry to your own endpoint or are relying on the events to be uncompressed (this feature is initially disabled and it is intended to be enabled by the service in the near future), it is recommended to either update collection endpoint to support GZip or to explicitly disable the feature. See more details [here](https://github.com/Microsoft/ApplicationInsights-JS?tab=readme-ov-file#feature).
### Changelog
diff --git a/channels/1ds-post-js/README.md b/channels/1ds-post-js/README.md
index 5f115e966..171710295 100644
--- a/channels/1ds-post-js/README.md
+++ b/channels/1ds-post-js/README.md
@@ -40,39 +40,39 @@ appInsightsCore.initialize(coreConfig, []);
| Config | Description | Type
|----------------|--------------|----
-| eventsLimitInMem | The number of events that can be kept in memory before the SDK starts to drop events. By default, this is 10,000.|number
-| immediateEventLimit | [Optional] Sets the maximum number of immediate latency events that will be cached in memory before the SDK starts to drop other immediate events only, does not drop normal and real time latency events as immediate events have their own internal queue. Under normal situations immediate events are scheduled to be sent in the next Javascript execution cycle, so the typically number of immediate events is small (~1), the only time more than one event may be present is when the channel is paused or immediate send is disabled (via manual transmit profile). By default max number of events is 500 and the default transmit time is 0ms. Added in v3.1.1 | number
-| autoFlushEventsLimit | [Optional] If defined, once this number of events has been queued the system perform a flush() to send the queued events without waiting for the normal schedule timers. Default is undefined | number
-| httpXHROverride |The HTTP override that should be used to send requests, request properties and headers should be added to the request to maintain correct functionality with other plugins.|IXHROverride
-| overrideInstrumentationKey |Override for Instrumentation key.|string
-| overrideEndpointUrl |Override for Endpoint where telemetry data is sent.|string
-| disableTelemetry |The master off switch. Do not send any data if set to TRUE.|boolean
-| ignoreMc1Ms0CookieProcessing |MC1 and MSFPC cookies will not be provided. Default is false.|boolean
-| payloadPreprocessor |POST channel preprocessing function. Can be used to gzip the payload (and set appropriate HTTP headers) before transmission. |[Function](./src/DataModels.ts)
-| payloadListener |POST channel function hook to listen to events being sent, called after the batched events have been committed to be sent. Also used by Remote DDV Channel to send requests. |[Function](./src/DataModels.ts)
-| disableEventTimings | [Optional] By default additional timing metrics details are added to each event after they are sent to allow you to review how long it took to create serialized request. As not all users require this level of detail and it's now possible to get the same metrics via the IPerfManager and IPerfEvent, so you can now disabled this previous level. Default value is false to retain the previous behavior, if you are not using these metrics and performance is a concern then it is recommended to set this value to true. | boolean
-| valueSanitizer | [Optional] The value sanitizer to use while constructing the envelope, if not provided the default sanitizeProperty() method is called to validate and convert the fields for serialization. The path / fields names are based on the format of the envelope (serialized object) as defined via the [Common Schema 4.0](https://aka.ms/CommonSchema) specification. | IValueSanitizer
-| stringifyObjects | [Optional] During serialization, when an object is identified should the object serialized by true => JSON.stringify(theObject); otherwise theObject.toString(). Defaults to false. | boolean
-| enableCompoundKey | [Optional] Enables support for objects with compound keys which indirectly represent an object eg. event: { "somedata.embeddedvalue": 123 } where the "key" of the object contains a "." as part of it's name. Defaults to false. | boolean
-| disableOptimizeObj | [Optional] Switch to disable the v8 `optimizeObject()` calls used to provide better serialization performance. Defaults to false. | boolean
-| transports | [Optional] Either an array or single value identifying the requested `TransportType` (const enum) type that should be used. This is used during initialization to identify the requested send transport, it will be ignored if a httpXHROverride is provided. | number or number[]
-| useSendBeacon | [Optional] A flag to enable or disable the usage of the sendBeacon() API if available by the runtime. If running on ReactNative this defaults to `false` for all other cases it defaults to `true`.
-| disableFetchKeepAlive | [Optional] A flag to disable the usage of the [fetch with keep-alive](https://javascript.info/fetch-api#keepalive) support.
-| unloadTransports | [Optional] Either an array or single value identifying the requested TransportType type(s) that should be used during unload or events marked as sendBeacon. This is used during initialization to identify the requested send transport, it will be ignored if a httpXHROverride is provided and alwaysUseXhrOverride is true.
-| avoidOptions (Since 3.1.10+) Default: false (Since 3.2.0) Previously true | [Optional] Avoid adding request headers to the outgoing request that would cause a pre-flight (OPTIONS) request to be sent for each request. | boolean
-| xhrTimeout (Since 3.1.11+) | [Optional] Specify a timeout (in ms) to apply to requests when sending requests using XHR or fetch() requests only, does not affect sendBeacon() or XDR (XDomainRequest) usage. Defaults to undefined and therefore the runtime defaults (normally zero for browser environments) | number
-| disableXhrSync (Since 3.1.11+) | [Optional] When using [Xhr](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest) for sending requests disable sending as synchronous during unload or synchronous flush. __You should enable this feature for IE (when there is no sendBeacon() or fetch (with keep-alive) support) and you have clients that end up blocking the UI during page unloading__. This will cause ALL XHR requests to be sent asynchronously which during page unload may result in the lose of telemetry. This does not affect any other request type (fetch(), sendBeacon() or XDR (XDomainRequest)) | boolean Default: undefined
-| alwaysUseXhrOverride (Since 3.1.11+) | [Optional] By default during unload (or when you specify to use sendBeacon() or sync fetch (with keep-alive) for an event) the SDK ignores any provided httpXhrOverride and attempts to use sendBeacon() or fetch(with keep-alive) when they are available. When this configuration option is true any provided httpXhrOverride will always be used, so any provided httpXhrOverride will also need to "handle" the synchronous unload scenario. | boolean Default: false
-| maxEventRetryAttempts (Since 3.1.11+) | [Optional] Identifies the number of times any single event will be retried if it receives a failed (retirable) response, this causes the event to be internally "requeued" and resent in the next batch. As each normal batched send request is retried at least once before starting to increase the internal backoff send interval, normally batched events will generally be attempted the next nearest even number of times. This means that the total number of actual send attempts will almost always be even (setting to 5 will cause 6 requests), unless using manual synchronous flushing (calling flush(false)) which is not subject to request level retry attempts. | number Default: 6
-| maxUnloadEventRetryAttempts (Since 3.1.11+) | [Optional] Identifies the number of times any single event will be retried if it receives a failed (retriable) response as part of processing / flushing events once a page unload state has been detected, this causes the event to be internally "requeued" and resent in the next batch, which during page unload. Unlike the normal batching process, send requests are never retried, so the value listed here is always the maximum number of attempts for any single event. Notes: The SDK by default will use the sendBeacon() API if it exists which is treated as a fire and forget successful response, so for environments that support or supply this API the events won't be retried (because they will be deeded to be successfully sent). When an environment (IE) doesn't support sendBeacon(), this will cause multiple synchronous (by default) XMLHttpRequests to be sent, which will block the UI until a response is received. You can disable ALL synchronous XHR requests by setting the 'disableXhrSync' configuration setting and/or changing this value to 0 or 1. | number Default: 2
-| addNoResponse (Since 3.2.8+) | [Optional] flag to indicate whether the sendBeacon and fetch (with keep-alive flag) should add the "NoResponseBody" query string value to indicate that the server should return a 204 for successful requests. | boolean Default: true
-| disableZip (Since 4.3.7+) | [Optional] flag to use CompressionStream API to compress the payload. Compression will only occur if the event is asynchronous. For events like unloads, compression will not be applied. * Note: if user set payloadPreprocessor, this zip compression will not be applied. | boolean Default: true
+| [eventsLimitInMem](https://microsoft.github.io/ApplicationInsights-JS/webSdk/1ds-post-js/interfaces/IChannelConfiguration.html#eventsLimitInMem) | The number of events that can be kept in memory before the SDK starts to drop events. By default, this is 10,000.|number
+| [immediateEventLimit](https://microsoft.github.io/ApplicationInsights-JS/webSdk/1ds-post-js/interfaces/IChannelConfiguration.html#immediateEventLimit) | [Optional] Sets the maximum number of immediate latency events that will be cached in memory before the SDK starts to drop other immediate events only, does not drop normal and real time latency events as immediate events have their own internal queue. Under normal situations immediate events are scheduled to be sent in the next Javascript execution cycle, so the typically number of immediate events is small (~1), the only time more than one event may be present is when the channel is paused or immediate send is disabled (via manual transmit profile). By default max number of events is 500 and the default transmit time is 0ms. Added in v3.1.1 | number
+| [autoFlushEventsLimit](https://microsoft.github.io/ApplicationInsights-JS/webSdk/1ds-post-js/interfaces/IChannelConfiguration.html#autoFlushEventsLimit) | [Optional] If defined, once this number of events has been queued the system perform a flush() to send the queued events without waiting for the normal schedule timers. Default is undefined | number
+| [httpXHROverride](https://microsoft.github.io/ApplicationInsights-JS/webSdk/1ds-post-js/interfaces/IChannelConfiguration.html#httpXHROverride) |The HTTP override that should be used to send requests, request properties and headers should be added to the request to maintain correct functionality with other plugins.|IXHROverride
+| [overrideInstrumentationKey](https://microsoft.github.io/ApplicationInsights-JS/webSdk/1ds-post-js/interfaces/IChannelConfiguration.html#overrideInstrumentationKey) |Override for Instrumentation key.|string
+| [overrideEndpointUrl](https://microsoft.github.io/ApplicationInsights-JS/webSdk/1ds-post-js/interfaces/IChannelConfiguration.html#overrideEndpointUrl) |Override for Endpoint where telemetry data is sent.|string
+| [disableTelemetry](https://microsoft.github.io/ApplicationInsights-JS/webSdk/1ds-post-js/interfaces/IChannelConfiguration.html#disableTelemetry) |The master off switch. Do not send any data if set to TRUE.|boolean
+| [ignoreMc1Ms0CookieProcessing](https://microsoft.github.io/ApplicationInsights-JS/webSdk/1ds-post-js/interfaces/IChannelConfiguration.html#ignoreMc1Ms0CookieProcessing) |MC1 and MSFPC cookies will not be provided. Default is false.|boolean
+| [payloadPreprocessor](https://microsoft.github.io/ApplicationInsights-JS/webSdk/1ds-post-js/interfaces/IChannelConfiguration.html#payloadPreprocessor) |POST channel preprocessing function. Can be used to gzip the payload (and set appropriate HTTP headers) before transmission. |[Function](./src/DataModels.ts)
+| [payloadListener](https://microsoft.github.io/ApplicationInsights-JS/webSdk/1ds-post-js/interfaces/IChannelConfiguration.html#payloadListener) |POST channel function hook to listen to events being sent, called after the batched events have been committed to be sent. Also used by Remote DDV Channel to send requests. |[Function](./src/DataModels.ts)
+| [disableEventTimings](https://microsoft.github.io/ApplicationInsights-JS/webSdk/1ds-post-js/interfaces/IChannelConfiguration.html#disableEventTimings) | [Optional] By default additional timing metrics details are added to each event after they are sent to allow you to review how long it took to create serialized request. As not all users require this level of detail and it's now possible to get the same metrics via the IPerfManager and IPerfEvent, so you can now disabled this previous level. Default value is false to retain the previous behavior, if you are not using these metrics and performance is a concern then it is recommended to set this value to true. | boolean
+| [valueSanitizer](https://microsoft.github.io/ApplicationInsights-JS/webSdk/1ds-post-js/interfaces/IChannelConfiguration.html#valueSanitizer) | [Optional] The value sanitizer to use while constructing the envelope, if not provided the default sanitizeProperty() method is called to validate and convert the fields for serialization. The path / fields names are based on the format of the envelope (serialized object) as defined via the [Common Schema 4.0](https://aka.ms/CommonSchema) specification. | IValueSanitizer
+| [stringifyObjects](https://microsoft.github.io/ApplicationInsights-JS/webSdk/1ds-post-js/interfaces/IChannelConfiguration.html#stringifyObjects) | [Optional] During serialization, when an object is identified should the object serialized by true => JSON.stringify(theObject); otherwise theObject.toString(). Defaults to false. | boolean
+| [enableCompoundKey](https://microsoft.github.io/ApplicationInsights-JS/webSdk/1ds-post-js/interfaces/IChannelConfiguration.html#enableCompoundKey) | [Optional] Enables support for objects with compound keys which indirectly represent an object eg. event: { "somedata.embeddedvalue": 123 } where the "key" of the object contains a "." as part of it's name. Defaults to false. | boolean
+| [disableOptimizeObj](https://microsoft.github.io/ApplicationInsights-JS/webSdk/1ds-post-js/interfaces/IChannelConfiguration.html#disableOptimizeObj) | [Optional] Switch to disable the v8 `optimizeObject()` calls used to provide better serialization performance. Defaults to false. | boolean
+| [transports](https://microsoft.github.io/ApplicationInsights-JS/webSdk/1ds-post-js/interfaces/IChannelConfiguration.html#transports) | [Optional] Either an array or single value identifying the requested `TransportType` (const enum) type that should be used. This is used during initialization to identify the requested send transport, it will be ignored if a httpXHROverride is provided. | number or number[]
+| [useSendBeacon](https://microsoft.github.io/ApplicationInsights-JS/webSdk/1ds-post-js/interfaces/IChannelConfiguration.html#useSendBeacon) | [Optional] A flag to enable or disable the usage of the sendBeacon() API if available by the runtime. If running on ReactNative this defaults to `false` for all other cases it defaults to `true`.
+| [disableFetchKeepAlive](https://microsoft.github.io/ApplicationInsights-JS/webSdk/1ds-post-js/interfaces/IChannelConfiguration.html#disableFetchKeepAlive) | [Optional] A flag to disable the usage of the [fetch with keep-alive](https://javascript.info/fetch-api#keepalive) support.
+| [unloadTransports](https://microsoft.github.io/ApplicationInsights-JS/webSdk/1ds-post-js/interfaces/IChannelConfiguration.html#unloadTransports) | [Optional] Either an array or single value identifying the requested TransportType type(s) that should be used during unload or events marked as sendBeacon. This is used during initialization to identify the requested send transport, it will be ignored if a httpXHROverride is provided and alwaysUseXhrOverride is true.
+| [avoidOptions](https://microsoft.github.io/ApplicationInsights-JS/webSdk/1ds-post-js/interfaces/IChannelConfiguration.html#avoidOptions) (Since 3.1.10+) Default: false (Since 3.2.0) Previously true | [Optional] Avoid adding request headers to the outgoing request that would cause a pre-flight (OPTIONS) request to be sent for each request. | boolean
+| [xhrTimeout](https://microsoft.github.io/ApplicationInsights-JS/webSdk/1ds-post-js/interfaces/IChannelConfiguration.html#xhrTimeout) (Since 3.1.11+) | [Optional] Specify a timeout (in ms) to apply to requests when sending requests using XHR or fetch() requests only, does not affect sendBeacon() or XDR (XDomainRequest) usage. Defaults to undefined and therefore the runtime defaults (normally zero for browser environments) | number
+| [disableXhrSync](https://microsoft.github.io/ApplicationInsights-JS/webSdk/1ds-post-js/interfaces/IChannelConfiguration.html#disableXhrSync) (Since 3.1.11+) | [Optional] When using [Xhr](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest) for sending requests disable sending as synchronous during unload or synchronous flush. __You should enable this feature for IE (when there is no sendBeacon() or fetch (with keep-alive) support) and you have clients that end up blocking the UI during page unloading__. This will cause ALL XHR requests to be sent asynchronously which during page unload may result in the lose of telemetry. This does not affect any other request type (fetch(), sendBeacon() or XDR (XDomainRequest)) | boolean Default: undefined
+| [alwaysUseXhrOverride](https://microsoft.github.io/ApplicationInsights-JS/webSdk/1ds-post-js/interfaces/IChannelConfiguration.html#alwaysUseXhrOverride) (Since 3.1.11+) | [Optional] By default during unload (or when you specify to use sendBeacon() or sync fetch (with keep-alive) for an event) the SDK ignores any provided httpXhrOverride and attempts to use sendBeacon() or fetch(with keep-alive) when they are available. When this configuration option is true any provided httpXhrOverride will always be used, so any provided httpXhrOverride will also need to "handle" the synchronous unload scenario. | boolean Default: false
+| [maxEventRetryAttempts](https://microsoft.github.io/ApplicationInsights-JS/webSdk/1ds-post-js/interfaces/IChannelConfiguration.html#maxEventRetryAttempts) (Since 3.1.11+) | [Optional] Identifies the number of times any single event will be retried if it receives a failed (retirable) response, this causes the event to be internally "requeued" and resent in the next batch. As each normal batched send request is retried at least once before starting to increase the internal backoff send interval, normally batched events will generally be attempted the next nearest even number of times. This means that the total number of actual send attempts will almost always be even (setting to 5 will cause 6 requests), unless using manual synchronous flushing (calling flush(false)) which is not subject to request level retry attempts. | number Default: 6
+| [maxUnloadEventRetryAttempts](https://microsoft.github.io/ApplicationInsights-JS/webSdk/1ds-post-js/interfaces/IChannelConfiguration.html#maxUnloadEventRetryAttempts) (Since 3.1.11+) | [Optional] Identifies the number of times any single event will be retried if it receives a failed (retriable) response as part of processing / flushing events once a page unload state has been detected, this causes the event to be internally "requeued" and resent in the next batch, which during page unload. Unlike the normal batching process, send requests are never retried, so the value listed here is always the maximum number of attempts for any single event. Notes: The SDK by default will use the sendBeacon() API if it exists which is treated as a fire and forget successful response, so for environments that support or supply this API the events won't be retried (because they will be deeded to be successfully sent). When an environment (IE) doesn't support sendBeacon(), this will cause multiple synchronous (by default) XMLHttpRequests to be sent, which will block the UI until a response is received. You can disable ALL synchronous XHR requests by setting the 'disableXhrSync' configuration setting and/or changing this value to 0 or 1. | number Default: 2
+| [addNoResponse](https://microsoft.github.io/ApplicationInsights-JS/webSdk/1ds-post-js/interfaces/IChannelConfiguration.html#addNoResponse) (Since 3.2.8+) | [Optional] flag to indicate whether the sendBeacon and fetch (with keep-alive flag) should add the "NoResponseBody" query string value to indicate that the server should return a 204 for successful requests. | boolean Default: true
+| [disableZip](https://microsoft.github.io/ApplicationInsights-JS/webSdk/1ds-post-js/interfaces/IChannelConfiguration.html#disableZip) (Since 4.3.7+) | [Optional] flag to use CompressionStream API to compress the payload. Compression will only occur if the event is asynchronous. For events like unloads, compression will not be applied. * Note: if user set payloadPreprocessor, this zip compression will not be applied. | boolean Default: true
### [IXHROverride](https://microsoft.github.io/ApplicationInsights-JS/webSdk/1ds-post-js/interfaces/IXHROverride.html)
| Config | Description | Type
|----------------|----------------------------------------|----|
-| sendPOST |This method sends data to the specified URI using a POST request. If sync is true then the request is sent synchronously. The oncomplete function should always be called after the request is completed (either successfully or timed out or failed due to errors).|function
+| [sendPOST](https://microsoft.github.io/ApplicationInsights-JS/webSdk/1ds-post-js/interfaces/IXHROverride.html#sendPOST) |This method sends data to the specified URI using a POST request. If sync is true then the request is sent synchronously. The oncomplete function should always be called after the request is completed (either successfully or timed out or failed due to errors).|function
### Payload Preprocessors
diff --git a/channels/1ds-post-js/package.json b/channels/1ds-post-js/package.json
index ca9bc00d5..3486be01f 100644
--- a/channels/1ds-post-js/package.json
+++ b/channels/1ds-post-js/package.json
@@ -1,6 +1,6 @@
{
"name": "@microsoft/1ds-post-js",
- "version": "4.3.8",
+ "version": "4.3.9",
"description": "Microsoft Application Insights JavaScript SDK - 1ds-post-channel-js",
"author": "Microsoft Application Insights Team",
"homepage": "https://github.com/microsoft/ApplicationInsights-JS#readme",
@@ -27,7 +27,7 @@
"dependencies": {
"@microsoft/applicationinsights-shims": "3.0.1",
"@microsoft/dynamicproto-js": "^2.0.3",
- "@microsoft/1ds-core-js": "4.3.8",
+ "@microsoft/1ds-core-js": "4.3.9",
"@nevware21/ts-utils": ">= 0.11.8 < 2.x",
"@nevware21/ts-async": ">= 0.5.4 < 2.x"
},
diff --git a/channels/applicationinsights-channel-js/Tests/Unit/src/Sender.tests.ts b/channels/applicationinsights-channel-js/Tests/Unit/src/Sender.tests.ts
index a4e09ac84..5f41c600e 100644
--- a/channels/applicationinsights-channel-js/Tests/Unit/src/Sender.tests.ts
+++ b/channels/applicationinsights-channel-js/Tests/Unit/src/Sender.tests.ts
@@ -170,6 +170,276 @@ export class SenderTests extends AITestClass {
}
});
+ this.testCaseAsync({
+ name: "zip test: gzip encode is working and content-encode header is set (feature opt-in)",
+ stepDelay: 10,
+ useFakeTimers: true,
+ useFakeServer: true,
+ steps: [
+ () => {
+ this.genericSpy = this.sandbox.spy(this.xhrOverride, 'sendPOST');
+ let core = new AppInsightsCore();
+
+ let coreConfig = {
+ instrumentationKey: "000e0000-e000-0000-a000-000000000000",
+ featureOptIn : {["zipPayload"]: {mode: 3}},
+ extensionConfig: {
+ [this._sender.identifier]: {
+ httpXHROverride: this.xhrOverride,
+ alwaysUseXhrOverride: true,
+ }
+ }
+ }
+
+ core.initialize(coreConfig, [this._sender]);
+
+ const telemetryItem: ITelemetryItem = {
+ name: 'fake item with some really long name to take up space quickly',
+ iKey: 'iKey',
+ baseType: 'some type',
+ baseData: {}
+ };
+ this._sender.processTelemetry(telemetryItem);
+ this._sender.flush();
+ this.clock.tick(10);
+ }].concat(PollingAssert.createPollingAssert(() => {
+ if (this.genericSpy.called){
+ let request = this.genericSpy.getCall(0).args[0];
+ let gzipData = request.data;
+ QUnit.assert.ok(gzipData, "data should be set");
+ QUnit.assert.equal(true, gzipData[0] === 0x1F && gzipData[1] === 0x8B, "telemetry should be gzip encoded");
+ QUnit.assert.equal(request.headers["Content-Encoding"], "gzip", "telemetry should be gzip encoded");
+ return true;
+ }
+ return false;
+ }, "Wait for promise response" + new Date().toISOString(), 60, 1000) as any)
+ });
+
+ this.testCaseAsync({
+ name: "zip test: gzip encode is disabled (feature opt-in not set)",
+ stepDelay: 10,
+ useFakeTimers: true,
+ useFakeServer: true,
+ steps: [
+ () => {
+ this.genericSpy = this.sandbox.spy(this.xhrOverride, 'sendPOST');
+ let core = new AppInsightsCore();
+
+ let coreConfig = {
+ instrumentationKey: "000e0000-e000-0000-a000-000000000000",
+ extensionConfig: {
+ [this._sender.identifier]: {
+ httpXHROverride: this.xhrOverride,
+ alwaysUseXhrOverride: true,
+ }
+ }
+ }
+
+ core.initialize(coreConfig, [this._sender]);
+
+ const telemetryItem: ITelemetryItem = {
+ name: 'fake item with some really long name to take up space quickly',
+ iKey: 'iKey',
+ baseType: 'some type',
+ baseData: {}
+ };
+ this._sender.processTelemetry(telemetryItem);
+ this._sender.flush();
+ this.clock.tick(10);
+ }].concat(PollingAssert.createPollingAssert(() => {
+ if (this.genericSpy.called){
+ let request = this.genericSpy.getCall(0).args[0];
+ let gzipData = request.data;
+ QUnit.assert.ok(gzipData, "data should be set");
+ QUnit.assert.equal(false, gzipData[0] === 0x1F && gzipData[1] === 0x8B, "telemetry should not be gzip encoded");
+ QUnit.assert.ok(!("Content-Encoding" in request.headers), "telemetry should not be gzip encoded"); return true;
+ }
+ return false;
+ }, "Wait for promise response" + new Date().toISOString(), 60, 1000) as any)
+ });
+
+ this.testCase({
+ name: "zip test: gzip encode is working and content-encode header is set (feature opt-in)",
+ pollDelay: 10,
+ useFakeTimers: true,
+ useFakeServer: true,
+ test: () => {
+ this.genericSpy = this.sandbox.spy(this.xhrOverride, 'sendPOST');
+ let core = new AppInsightsCore();
+
+ let coreConfig = {
+ instrumentationKey: "000e0000-e000-0000-a000-000000000000",
+ featureOptIn : {["zipPayload"]: {mode: 3}},
+ extensionConfig: {
+ [this._sender.identifier]: {
+ httpXHROverride: this.xhrOverride,
+ alwaysUseXhrOverride: true,
+ }
+ }
+ }
+
+ core.initialize(coreConfig, [this._sender]);
+
+ const telemetryItem: ITelemetryItem = {
+ name: 'fake item with some really long name to take up space quickly',
+ iKey: 'iKey',
+ baseType: 'some type',
+ baseData: {}
+ };
+ this._sender.processTelemetry(telemetryItem);
+ this._sender.flush();
+ this.clock.tick(10);
+
+ return this._asyncQueue().concat(PollingAssert.asyncTaskPollingAssert(() => {
+ if (this.genericSpy.called) {
+ let request = this.genericSpy.getCall(0).args[0];
+ let gzipData = request.data;
+ QUnit.assert.ok(gzipData, "data should be set");
+ QUnit.assert.equal(true, gzipData[0] === 0x1F && gzipData[1] === 0x8B, "telemetry should be gzip encoded");
+ QUnit.assert.equal(request.headers["Content-Encoding"], "gzip", "telemetry should be gzip encoded");
+ return true;
+ }
+ return false;
+ }, "Wait for promise response" + new Date().toISOString(), 60, 1000));
+ }
+ });
+
+ this.testCase({
+ name: "zip test: gzip encode is disabled (feature opt-in not set)",
+ pollDelay: 10,
+ useFakeTimers: true,
+ useFakeServer: true,
+ test: () => {
+ this.genericSpy = this.sandbox.spy(this.xhrOverride, 'sendPOST');
+ let core = new AppInsightsCore();
+
+ let coreConfig = {
+ instrumentationKey: "000e0000-e000-0000-a000-000000000000",
+ extensionConfig: {
+ [this._sender.identifier]: {
+ httpXHROverride: this.xhrOverride,
+ alwaysUseXhrOverride: true,
+ }
+ }
+ }
+
+ core.initialize(coreConfig, [this._sender]);
+
+ const telemetryItem: ITelemetryItem = {
+ name: 'fake item with some really long name to take up space quickly',
+ iKey: 'iKey',
+ baseType: 'some type',
+ baseData: {}
+ };
+ this._sender.processTelemetry(telemetryItem);
+ this._sender.flush();
+ this.clock.tick(10);
+
+ return this._asyncQueue().concat(PollingAssert.asyncTaskPollingAssert(() => {
+ if (this.genericSpy.called){
+ let request = this.genericSpy.getCall(0).args[0];
+ let gzipData = request.data;
+ QUnit.assert.ok(gzipData, "data should be set");
+ QUnit.assert.equal(false, gzipData[0] === 0x1F && gzipData[1] === 0x8B, "telemetry should not be gzip encoded");
+ QUnit.assert.ok(!("Content-Encoding" in request.headers), "telemetry should not be gzip encoded");
+ return true;
+ }
+ return false;
+ }, "Wait for promise response" + new Date().toISOString(), 60, 1000));
+ }
+ });
+
+ this.testCase({
+ name: "zip test: gzip encode is working and content-encode header is set (feature opt-in)",
+ pollDelay: 10,
+ useFakeTimers: true,
+ useFakeServer: true,
+ test: () => {
+ this.genericSpy = this.sandbox.spy(this.xhrOverride, 'sendPOST');
+ let core = new AppInsightsCore();
+
+ let coreConfig = {
+ instrumentationKey: "000e0000-e000-0000-a000-000000000000",
+ featureOptIn : {["zipPayload"]: {mode: 3}},
+ extensionConfig: {
+ [this._sender.identifier]: {
+ httpXHROverride: this.xhrOverride,
+ alwaysUseXhrOverride: true,
+ }
+ }
+ }
+
+ core.initialize(coreConfig, [this._sender]);
+
+ const telemetryItem: ITelemetryItem = {
+ name: 'fake item with some really long name to take up space quickly',
+ iKey: 'iKey',
+ baseType: 'some type',
+ baseData: {}
+ };
+ this._sender.processTelemetry(telemetryItem);
+ this._sender.flush();
+ this.clock.tick(10);
+
+ return this._asyncQueue().concat(PollingAssert.asyncTaskPollingAssert(() => {
+ if (this.genericSpy.called) {
+ let request = this.genericSpy.getCall(0).args[0];
+ let gzipData = request.data;
+ QUnit.assert.ok(gzipData, "data should be set");
+ QUnit.assert.equal(true, gzipData[0] === 0x1F && gzipData[1] === 0x8B, "telemetry should be gzip encoded");
+ QUnit.assert.equal(request.headers["Content-Encoding"], "gzip", "telemetry should be gzip encoded");
+ return true;
+ }
+ return false;
+ }, "Wait for promise response" + new Date().toISOString(), 60, 1000));
+ }
+ });
+
+ this.testCase({
+ name: "zip test: gzip encode is disabled (feature opt-in not set)",
+ pollDelay: 10,
+ useFakeTimers: true,
+ useFakeServer: true,
+ test: () => {
+ this.genericSpy = this.sandbox.spy(this.xhrOverride, 'sendPOST');
+ let core = new AppInsightsCore();
+
+ let coreConfig = {
+ instrumentationKey: "000e0000-e000-0000-a000-000000000000",
+ extensionConfig: {
+ [this._sender.identifier]: {
+ httpXHROverride: this.xhrOverride,
+ alwaysUseXhrOverride: true,
+ }
+ }
+ }
+
+ core.initialize(coreConfig, [this._sender]);
+
+ const telemetryItem: ITelemetryItem = {
+ name: 'fake item with some really long name to take up space quickly',
+ iKey: 'iKey',
+ baseType: 'some type',
+ baseData: {}
+ };
+ this._sender.processTelemetry(telemetryItem);
+ this._sender.flush();
+ this.clock.tick(10);
+
+ return this._asyncQueue().concat(PollingAssert.asyncTaskPollingAssert(() => {
+ if (this.genericSpy.called){
+ let request = this.genericSpy.getCall(0).args[0];
+ let gzipData = request.data;
+ QUnit.assert.ok(gzipData, "data should be set");
+ QUnit.assert.equal(false, gzipData[0] === 0x1F && gzipData[1] === 0x8B, "telemetry should not be gzip encoded");
+ QUnit.assert.ok(!("Content-Encoding" in request.headers), "telemetry should not be gzip encoded");
+ return true;
+ }
+ return false;
+ }, "Wait for promise response" + new Date().toISOString(), 60, 1000));
+ }
+ });
+
this.testCase({
name: "zip test: gzip encode is working and content-encode header is set (feature opt-in)",
pollDelay: 10,
diff --git a/channels/applicationinsights-channel-js/package.json b/channels/applicationinsights-channel-js/package.json
index 1cdfc7656..d2a570194 100644
--- a/channels/applicationinsights-channel-js/package.json
+++ b/channels/applicationinsights-channel-js/package.json
@@ -1,6 +1,6 @@
{
"name": "@microsoft/applicationinsights-channel-js",
- "version": "3.3.8",
+ "version": "3.3.9",
"description": "Microsoft Application Insights JavaScript SDK Channel",
"homepage": "https://github.com/microsoft/ApplicationInsights-JS#readme",
"author": "Microsoft Application Insights Team",
@@ -57,8 +57,8 @@
"dependencies": {
"@microsoft/dynamicproto-js": "^2.0.3",
"@microsoft/applicationinsights-shims": "3.0.1",
- "@microsoft/applicationinsights-core-js": "3.3.8",
- "@microsoft/applicationinsights-common": "3.3.8",
+ "@microsoft/applicationinsights-core-js": "3.3.9",
+ "@microsoft/applicationinsights-common": "3.3.9",
"@nevware21/ts-utils": ">= 0.11.8 < 2.x",
"@nevware21/ts-async": ">= 0.5.4 < 2.x"
},
diff --git a/channels/offline-channel-js/README.md b/channels/offline-channel-js/README.md
index f14d3ff90..f48c271a0 100644
--- a/channels/offline-channel-js/README.md
+++ b/channels/offline-channel-js/README.md
@@ -14,35 +14,35 @@ The Offline Channel supports the saving of events when your application is offli
## Configuration
-`IOfflineChannelConfiguration`
+[`IOfflineChannelConfiguration`](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-offlinechannel-js/interfaces/IOfflineChannelConfiguration.html)
| Name | Type | Default | Description |
|------|------|---------|-------------|
-| maxStorageSizeInBytes | [Optional]| 5000000 | The max size in bytes that should be used for storing events in local/session storage. |
-| storageKeyPrefix | [Optional] | AIOffline | The storage key prefix that should be used when storing events in persistent storage. |
-| minPersistenceLevel | [Optional] | `EventPersistence.Normal` or 1 | Identifies the minimum level that will be cached in the offline channel. Valid values of this setting are defined by the `EventPersistence` enum, currently Normal (1) and Critical (2) with the default value being Normal (1), which means all events without a persistence level set or with invalid persistence level will be marked as Normal(1) events.|
-| providers | [Optional] | [`eStorageProviders.LocalStorage, eStorageProviders.IndexedDB`]| Identifies the StorageProviders that should be used by the system if available, the first available provider will be used. Valid available values are defined by the `eStorageProviders` enum. Note: LocalStorage will be used to save unload events even if it is not in the providers list. |
-| eventsLimitInMem | [Optional] | null | Identifies the maximum number of events to store in memory before sending to persistent storage. |
-| autoClean | [Optional] | false | Identifies if events that have existed in storage longer than the maximum allowed time (configured in inStorageMaxTime) should be cleaned after connection with storage. |
-| inMemoMaxTime | [Optional] | 15000 | Identifies the maximum time in ms that items should be in memory before being saved into storage. |
-| inStorageMaxTime | [Optional] | 10080000 (around 7days) | Identifies the maximum time in ms that items should be in the configured persistent storage. |
-| maxRetry | [Optional] | 1 | Identifies the maximum retry times for an event batch. |
-| primaryOnlineChannelId | [Optional] | `[AppInsightsChannelPlugin, PostChannel]` | Identifies online channel IDs in order. The first available one will be used. |
-| maxBatchsize | [Optional] | 63000 | Identifies the maximum size per batch in bytes that is saved in persistent storage. |
-| senderCfg | [Optional] | `IOfflineSenderConfig` | Identifies offline sender properties. |
-| maxSentBatchInterval | [Optional] | 15000 | Identifies the interval time in ms that previously stored offline event batches should be sent under online status. |
-| EventsToDropPerTime | [Optional] | 10 | Identifies the maximum event batch count when cleaning or releasing space for persistent storage per time. |
-| maxCriticalEvtsDropCnt | [Optional] | 2 | Identifies the maximum critical events count for an event batch to be able to drop when releasing space for persistent storage per time. |
-| overrideInstrumentationKey | [Optional] | null | Identifies overridden for the Instrumentation key when the offline channel calls `processTelemetry`. |
-
-`IOfflineSenderConfig`
+| [maxStorageSizeInBytes](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-offlinechannel-js/interfaces/IOfflineChannelConfiguration.html#maxStorageSizeInBytes) | [Optional]| 5000000 | The max size in bytes that should be used for storing events in local/session storage. |
+| [storageKeyPrefix](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-offlinechannel-js/interfaces/IOfflineChannelConfiguration.html#storageKeyPrefix) | [Optional] | AIOffline | The storage key prefix that should be used when storing events in persistent storage. |
+| [minPersistenceLevel](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-offlinechannel-js/interfaces/IOfflineChannelConfiguration.html#minPersistenceLevel) | [Optional] | `EventPersistence.Normal` or 1 | Identifies the minimum level that will be cached in the offline channel. Valid values of this setting are defined by the `EventPersistence` enum, currently Normal (1) and Critical (2) with the default value being Normal (1), which means all events without a persistence level set or with invalid persistence level will be marked as Normal(1) events.|
+| [providers](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-offlinechannel-js/interfaces/IOfflineChannelConfiguration.html#providers) | [Optional] | [`eStorageProviders.LocalStorage, eStorageProviders.IndexedDB`]| Identifies the StorageProviders that should be used by the system if available, the first available provider will be used. Valid available values are defined by the `eStorageProviders` enum. Note: LocalStorage will be used to save unload events even if it is not in the providers list. |
+| [eventsLimitInMem](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-offlinechannel-js/interfaces/IOfflineChannelConfiguration.html#eventsLimitInMem) | [Optional] | null | Identifies the maximum number of events to store in memory before sending to persistent storage. |
+| [autoClean](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-offlinechannel-js/interfaces/IOfflineChannelConfiguration.html#autoClean) | [Optional] | false | Identifies if events that have existed in storage longer than the maximum allowed time (configured in inStorageMaxTime) should be cleaned after connection with storage. |
+| [inMemoMaxTime](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-offlinechannel-js/interfaces/IOfflineChannelConfiguration.html#inMemoMaxTime) | [Optional] | 15000 | Identifies the maximum time in ms that items should be in memory before being saved into storage. |
+| [inStorageMaxTime](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-offlinechannel-js/interfaces/IOfflineChannelConfiguration.html#inStorageMaxTime) | [Optional] | 10080000 (around 7days) | Identifies the maximum time in ms that items should be in the configured persistent storage. |
+| [maxRetry](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-offlinechannel-js/interfaces/IOfflineChannelConfiguration.html#maxRetry) | [Optional] | 1 | Identifies the maximum retry times for an event batch. |
+| [primaryOnlineChannelId](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-offlinechannel-js/interfaces/IOfflineChannelConfiguration.html#primaryOnlineChannelId) | [Optional] | `[AppInsightsChannelPlugin, PostChannel]` | Identifies online channel IDs in order. The first available one will be used. |
+| [maxBatchsize](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-offlinechannel-js/interfaces/IOfflineChannelConfiguration.html#maxBatchsize) | [Optional] | 63000 | Identifies the maximum size per batch in bytes that is saved in persistent storage. |
+| [senderCfg](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-offlinechannel-js/interfaces/IOfflineChannelConfiguration.html#senderCfg) | [Optional] | `IOfflineSenderConfig` | Identifies offline sender properties. |
+| [maxSentBatchInterval](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-offlinechannel-js/interfaces/IOfflineChannelConfiguration.html#maxSentBatchInterval) | [Optional] | 15000 | Identifies the interval time in ms that previously stored offline event batches should be sent under online status. |
+| [EventsToDropPerTime](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-offlinechannel-js/interfaces/IOfflineChannelConfiguration.html#EventsToDropPerTime) | [Optional] | 10 | Identifies the maximum event batch count when cleaning or releasing space for persistent storage per time. |
+| [maxCriticalEvtsDropCnt](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-offlinechannel-js/interfaces/IOfflineChannelConfiguration.html#maxCriticalEvtsDropCnt) | [Optional] | 2 | Identifies the maximum critical events count for an event batch to be able to drop when releasing space for persistent storage per time. |
+| [overrideInstrumentationKey](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-offlinechannel-js/interfaces/IOfflineChannelConfiguration.html#overrideInstrumentationKey) | [Optional] | null | Identifies overridden for the Instrumentation key when the offline channel calls `processTelemetry`. |
+
+### [IOfflineSenderConfig](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-offlinechannel-js/interfaces/IOfflineSenderConfig.html)
| Name | Type | Default | Description |
|------|------|---------|-------------|
-| retryCodes | [Optional] | `[401, 403, 408, 429, 500, 502, 503, 504]` | Identifies status codes for re-sending event batches. |
-| transports | [Optional] | null | Either an array or single value identifying the requested TransportType type(s) that should be used for sending events. If not defined, the same transports will be used in the channel with the `primaryOnlineChannelI`. |
-| httpXHROverride | [Optional] | null | The HTTP override that should be used to send requests, as an `IXHROverride` object. |
-| alwaysUseXhrOverride | [Optional] | false | Identifies if provided httpXhrOverride will always be used. |
+| [retryCodes](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-offlinechannel-js/interfaces/IOfflineSenderConfig.html#retryCodes) | [Optional] | `[401, 403, 408, 429, 500, 502, 503, 504]` | Identifies status codes for re-sending event batches. |
+| [transports](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-offlinechannel-js/interfaces/IOfflineSenderConfig.html#transports) | [Optional] | null | Either an array or single value identifying the requested TransportType type(s) that should be used for sending events. If not defined, the same transports will be used in the channel with the `primaryOnlineChannelI`. |
+| [httpXHROverride](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-offlinechannel-js/interfaces/IOfflineSenderConfig.html#httpXHROverride) | [Optional] | null | The HTTP override that should be used to send requests, as an `IXHROverride` object. |
+| [alwaysUseXhrOverride](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-offlinechannel-js/interfaces/IOfflineSenderConfig.html#alwaysUseXhrOverride) | [Optional] | false | Identifies if provided httpXhrOverride will always be used. |
## Basic Usage
diff --git a/channels/offline-channel-js/package.json b/channels/offline-channel-js/package.json
index 673c0d529..b24085234 100644
--- a/channels/offline-channel-js/package.json
+++ b/channels/offline-channel-js/package.json
@@ -1,6 +1,6 @@
{
"name": "@microsoft/applicationinsights-offlinechannel-js",
- "version": "0.3.8",
+ "version": "0.3.9",
"description": "Microsoft Application Insights JavaScript SDK Offline Channel",
"homepage": "https://github.com/microsoft/ApplicationInsights-JS#readme",
"author": "Microsoft Application Insights Team",
@@ -31,8 +31,8 @@
"dependencies": {
"@microsoft/dynamicproto-js": "^2.0.3",
"@microsoft/applicationinsights-shims": "3.0.1",
- "@microsoft/applicationinsights-core-js": "3.3.8",
- "@microsoft/applicationinsights-common": "3.3.8",
+ "@microsoft/applicationinsights-core-js": "3.3.9",
+ "@microsoft/applicationinsights-common": "3.3.9",
"@nevware21/ts-utils": ">= 0.11.8 < 2.x",
"@nevware21/ts-async": ">= 0.5.4 < 2.x"
},
diff --git a/channels/tee-channel-js/README.md b/channels/tee-channel-js/README.md
index 98a4d4b12..4a737d05b 100644
--- a/channels/tee-channel-js/README.md
+++ b/channels/tee-channel-js/README.md
@@ -44,12 +44,12 @@ const appInsights = new ApplicationInsights({ config: configObj });
appInsights.loadAppInsights();
```
-## Configuration
+## [Configuration](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-teechannel-js/interfaces/ITeeChannelConfig.html)
| Name | Type | Default | Description
| --------------------- | -----------------------------------| -----------| ----------------------------------------------------------------------------------------------------------------
-| teeChannels | `IChannelControls`[][] | undefined | Defines the Channels specific to the TeeChannel
-| ignoreCoreChannels | boolean | false |By default the TeeChannel will use the core configuration `channels` (starting at index 1 `channels[1.xxx]`) as separate tee'd channel chains for processing events. This configuration allow you to ignore any additional core channels and only use the `teeChannels`
+| [teeChannels](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-teechannel-js/interfaces/ITeeChannelConfig.html#teeChannels) | `IChannelControls`[][] | undefined | Defines the Channels specific to the TeeChannel
+| [ignoreCoreChannels](https://microsoft.github.io/ApplicationInsights-JS/webSdk/applicationinsights-teechannel-js/interfaces/ITeeChannelConfig.html#ignoreCoreChannels) | boolean | false |By default the TeeChannel will use the core configuration `channels` (starting at index 1 `channels[1.xxx]`) as separate tee'd channel chains for processing events. This configuration allow you to ignore any additional core channels and only use the `teeChannels`
## Contributing
diff --git a/channels/tee-channel-js/package.json b/channels/tee-channel-js/package.json
index 0a633b11b..4701afb2e 100644
--- a/channels/tee-channel-js/package.json
+++ b/channels/tee-channel-js/package.json
@@ -1,6 +1,6 @@
{
"name": "@microsoft/applicationinsights-teechannel-js",
- "version": "3.3.8",
+ "version": "3.3.9",
"description": "Microsoft Application Insights JavaScript SDK Tee Channel",
"homepage": "https://github.com/microsoft/ApplicationInsights-JS#readme",
"author": "Microsoft Application Insights Team",
@@ -58,8 +58,8 @@
"dependencies": {
"@microsoft/dynamicproto-js": "^2.0.3",
"@microsoft/applicationinsights-shims": "3.0.1",
- "@microsoft/applicationinsights-core-js": "3.3.8",
- "@microsoft/applicationinsights-common": "3.3.8",
+ "@microsoft/applicationinsights-core-js": "3.3.9",
+ "@microsoft/applicationinsights-common": "3.3.9",
"@nevware21/ts-utils": ">= 0.11.8 < 2.x",
"@nevware21/ts-async": ">= 0.5.4 < 2.x"
},
diff --git a/common/Tests/External/jquery-1.11.1.js b/common/Tests/External/jquery-1.11.1.js
deleted file mode 100644
index 770705448..000000000
--- a/common/Tests/External/jquery-1.11.1.js
+++ /dev/null
@@ -1,10308 +0,0 @@
-/*!
- * jQuery JavaScript Library v1.11.1
- * http://jquery.com/
- *
- * Includes Sizzle.js
- * http://sizzlejs.com/
- *
- * Copyright 2005, 2014 jQuery Foundation, Inc. and other contributors
- * Released under the MIT license
- * http://jquery.org/license
- *
- * Date: 2014-05-01T17:42Z
- */
-
-(function( global, factory ) {
-
- if ( typeof module === "object" && typeof module.exports === "object" ) {
- // For CommonJS and CommonJS-like environments where a proper window is present,
- // execute the factory and get jQuery
- // For environments that do not inherently posses a window with a document
- // (such as Node.js), expose a jQuery-making factory as module.exports
- // This accentuates the need for the creation of a real window
- // e.g. var jQuery = require("jquery")(window);
- // See ticket #14549 for more info
- module.exports = global.document ?
- factory( global, true ) :
- function( w ) {
- if ( !w.document ) {
- throw new Error( "jQuery requires a window with a document" );
- }
- return factory( w );
- };
- } else {
- factory( global );
- }
-
-// Pass this if window is not defined yet
-}(typeof window !== "undefined" ? window : this, function( window, noGlobal ) {
-
-// Can't do this because several apps including ASP.NET trace
-// the stack via arguments.caller.callee and Firefox dies if
-// you try to trace through "use strict" call chains. (#13335)
-// Support: Firefox 18+
-//
-
-var deletedIds = [];
-
-var slice = deletedIds.slice;
-
-var concat = deletedIds.concat;
-
-var push = deletedIds.push;
-
-var indexOf = deletedIds.indexOf;
-
-var class2type = {};
-
-var toString = class2type.toString;
-
-var hasOwn = class2type.hasOwnProperty;
-
-var support = {};
-
-
-
-var
- version = "1.11.1",
-
- // Define a local copy of jQuery
- jQuery = function( selector, context ) {
- // The jQuery object is actually just the init constructor 'enhanced'
- // Need init if jQuery is called (just allow error to be thrown if not included)
- return new jQuery.fn.init( selector, context );
- },
-
- // Support: Android<4.1, IE<9
- // Make sure we trim BOM and NBSP
- rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,
-
- // Matches dashed string for camelizing
- rmsSnippet = /^-ms-/,
- rdashAlpha = /-([\da-z])/gi,
-
- // Used by jQuery.camelCase as callback to replace()
- fcamelCase = function( all, letter ) {
- return letter.toUpperCase();
- };
-
-jQuery.fn = jQuery.prototype = {
- // The current version of jQuery being used
- jquery: version,
-
- constructor: jQuery,
-
- // Start with an empty selector
- selector: "",
-
- // The default length of a jQuery object is 0
- length: 0,
-
- toArray: function() {
- return slice.call( this );
- },
-
- // Get the Nth element in the matched element set OR
- // Get the whole matched element set as a clean array
- get: function( num ) {
- return num != null ?
-
- // Return just the one element from the set
- ( num < 0 ? this[ num + this.length ] : this[ num ] ) :
-
- // Return all the elements in a clean array
- slice.call( this );
- },
-
- // Take an array of elements and push it onto the stack
- // (returning the new matched element set)
- pushStack: function( elems ) {
-
- // Build a new jQuery matched element set
- var ret = jQuery.merge( this.constructor(), elems );
-
- // Add the old object onto the stack (as a reference)
- ret.prevObject = this;
- ret.context = this.context;
-
- // Return the newly-formed element set
- return ret;
- },
-
- // Execute a callback for every element in the matched set.
- // (You can seed the arguments with an array of args, but this is
- // only used internally.)
- each: function( callback, args ) {
- return jQuery.each( this, callback, args );
- },
-
- map: function( callback ) {
- return this.pushStack( jQuery.map(this, function( elem, i ) {
- return callback.call( elem, i, elem );
- }));
- },
-
- slice: function() {
- return this.pushStack( slice.apply( this, arguments ) );
- },
-
- first: function() {
- return this.eq( 0 );
- },
-
- last: function() {
- return this.eq( -1 );
- },
-
- eq: function( i ) {
- var len = this.length,
- j = +i + ( i < 0 ? len : 0 );
- return this.pushStack( j >= 0 && j < len ? [ this[j] ] : [] );
- },
-
- end: function() {
- return this.prevObject || this.constructor(null);
- },
-
- // For internal use only.
- // Behaves like an Array's method, not like a jQuery method.
- push: push,
- sort: deletedIds.sort,
- splice: deletedIds.splice
-};
-
-jQuery.extend = jQuery.fn.extend = function() {
- var src, copyIsArray, copy, name, options, clone,
- target = arguments[0] || {},
- i = 1,
- length = arguments.length,
- deep = false;
-
- // Handle a deep copy situation
- if ( typeof target === "boolean" ) {
- deep = target;
-
- // skip the boolean and the target
- target = arguments[ i ] || {};
- i++;
- }
-
- // Handle case when target is a string or something (possible in deep copy)
- if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
- target = {};
- }
-
- // extend jQuery itself if only one argument is passed
- if ( i === length ) {
- target = this;
- i--;
- }
-
- for ( ; i < length; i++ ) {
- // Only deal with non-null/undefined values
- if ( (options = arguments[ i ]) != null ) {
- // Extend the base object
- for ( name in options ) {
- src = target[ name ];
- copy = options[ name ];
-
- // Prevent never-ending loop
- if ( target === copy ) {
- continue;
- }
-
- // Recurse if we're merging plain objects or arrays
- if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
- if ( copyIsArray ) {
- copyIsArray = false;
- clone = src && jQuery.isArray(src) ? src : [];
-
- } else {
- clone = src && jQuery.isPlainObject(src) ? src : {};
- }
-
- // Never move original objects, clone them
- target[ name ] = jQuery.extend( deep, clone, copy );
-
- // Don't bring in undefined values
- } else if ( copy !== undefined ) {
- target[ name ] = copy;
- }
- }
- }
- }
-
- // Return the modified object
- return target;
-};
-
-jQuery.extend({
- // Unique for each copy of jQuery on the page
- expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ),
-
- // Assume jQuery is ready without the ready module
- isReady: true,
-
- error: function( msg ) {
- throw new Error( msg );
- },
-
- noop: function() {},
-
- // See test/unit/core.js for details concerning isFunction.
- // Since version 1.3, DOM methods and functions like alert
- // aren't supported. They return false on IE (#2968).
- isFunction: function( obj ) {
- return jQuery.type(obj) === "function";
- },
-
- isArray: Array.isArray || function( obj ) {
- return jQuery.type(obj) === "array";
- },
-
- isWindow: function( obj ) {
- /* jshint eqeqeq: false */
- return obj != null && obj == obj.window;
- },
-
- isNumeric: function( obj ) {
- // parseFloat NaNs numeric-cast false positives (null|true|false|"")
- // ...but misinterprets leading-number strings, particularly hex literals ("0x...")
- // subtraction forces infinities to NaN
- return !jQuery.isArray( obj ) && obj - parseFloat( obj ) >= 0;
- },
-
- isEmptyObject: function( obj ) {
- var name;
- for ( name in obj ) {
- return false;
- }
- return true;
- },
-
- isPlainObject: function( obj ) {
- var key;
-
- // Must be an Object.
- // Because of IE, we also have to check the presence of the constructor property.
- // Make sure that DOM nodes and window objects don't pass through, as well
- if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) {
- return false;
- }
-
- try {
- // Not own constructor property must be Object
- if ( obj.constructor &&
- !hasOwn.call(obj, "constructor") &&
- !hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) {
- return false;
- }
- } catch ( e ) {
- // IE8,9 Will throw exceptions on certain host objects #9897
- return false;
- }
-
- // Support: IE<9
- // Handle iteration over inherited properties before own properties.
- if ( support.ownLast ) {
- for ( key in obj ) {
- return hasOwn.call( obj, key );
- }
- }
-
- // Own properties are enumerated firstly, so to speed up,
- // if last one is own, then all properties are own.
- for ( key in obj ) {}
-
- return key === undefined || hasOwn.call( obj, key );
- },
-
- type: function( obj ) {
- if ( obj == null ) {
- return obj + "";
- }
- return typeof obj === "object" || typeof obj === "function" ?
- class2type[ toString.call(obj) ] || "object" :
- typeof obj;
- },
-
- // Evaluates a script in a global context
- // Workarounds based on findings by Jim Driscoll
- // http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context
- globalEval: function( data ) {
- if ( data && jQuery.trim( data ) ) {
- // We use execScript on Internet Explorer
- // We use an anonymous function so that context is window
- // rather than jQuery in Firefox
- ( window.execScript || function( data ) {
- window[ "eval" ].call( window, data );
- } )( data );
- }
- },
-
- // Convert dashed to camelCase; used by the css and data modules
- // Microsoft forgot to hump their vendor snippet (#9572)
- camelCase: function( string ) {
- return string.replace( rmsSnippet, "ms-" ).replace( rdashAlpha, fcamelCase );
- },
-
- nodeName: function( elem, name ) {
- return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();
- },
-
- // args is for internal usage only
- each: function( obj, callback, args ) {
- var value,
- i = 0,
- length = obj.length,
- isArray = isArraylike( obj );
-
- if ( args ) {
- if ( isArray ) {
- for ( ; i < length; i++ ) {
- value = callback.apply( obj[ i ], args );
-
- if ( value === false ) {
- break;
- }
- }
- } else {
- for ( i in obj ) {
- value = callback.apply( obj[ i ], args );
-
- if ( value === false ) {
- break;
- }
- }
- }
-
- // A special, fast, case for the most common use of each
- } else {
- if ( isArray ) {
- for ( ; i < length; i++ ) {
- value = callback.call( obj[ i ], i, obj[ i ] );
-
- if ( value === false ) {
- break;
- }
- }
- } else {
- for ( i in obj ) {
- value = callback.call( obj[ i ], i, obj[ i ] );
-
- if ( value === false ) {
- break;
- }
- }
- }
- }
-
- return obj;
- },
-
- // Support: Android<4.1, IE<9
- trim: function( text ) {
- return text == null ?
- "" :
- ( text + "" ).replace( rtrim, "" );
- },
-
- // results is for internal usage only
- makeArray: function( arr, results ) {
- var ret = results || [];
-
- if ( arr != null ) {
- if ( isArraylike( Object(arr) ) ) {
- jQuery.merge( ret,
- typeof arr === "string" ?
- [ arr ] : arr
- );
- } else {
- push.call( ret, arr );
- }
- }
-
- return ret;
- },
-
- inArray: function( elem, arr, i ) {
- var len;
-
- if ( arr ) {
- if ( indexOf ) {
- return indexOf.call( arr, elem, i );
- }
-
- len = arr.length;
- i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0;
-
- for ( ; i < len; i++ ) {
- // Skip accessing in sparse arrays
- if ( i in arr && arr[ i ] === elem ) {
- return i;
- }
- }
- }
-
- return -1;
- },
-
- merge: function( first, second ) {
- var len = +second.length,
- j = 0,
- i = first.length;
-
- while ( j < len ) {
- first[ i++ ] = second[ j++ ];
- }
-
- // Support: IE<9
- // Workaround casting of .length to NaN on otherwise arraylike objects (e.g., NodeLists)
- if ( len !== len ) {
- while ( second[j] !== undefined ) {
- first[ i++ ] = second[ j++ ];
- }
- }
-
- first.length = i;
-
- return first;
- },
-
- grep: function( elems, callback, invert ) {
- var callbackInverse,
- matches = [],
- i = 0,
- length = elems.length,
- callbackExpect = !invert;
-
- // Go through the array, only saving the items
- // that pass the validator function
- for ( ; i < length; i++ ) {
- callbackInverse = !callback( elems[ i ], i );
- if ( callbackInverse !== callbackExpect ) {
- matches.push( elems[ i ] );
- }
- }
-
- return matches;
- },
-
- // arg is for internal usage only
- map: function( elems, callback, arg ) {
- var value,
- i = 0,
- length = elems.length,
- isArray = isArraylike( elems ),
- ret = [];
-
- // Go through the array, translating each of the items to their new values
- if ( isArray ) {
- for ( ; i < length; i++ ) {
- value = callback( elems[ i ], i, arg );
-
- if ( value != null ) {
- ret.push( value );
- }
- }
-
- // Go through every key on the object,
- } else {
- for ( i in elems ) {
- value = callback( elems[ i ], i, arg );
-
- if ( value != null ) {
- ret.push( value );
- }
- }
- }
-
- // Flatten any nested arrays
- return concat.apply( [], ret );
- },
-
- // A global GUID counter for objects
- guid: 1,
-
- // Bind a function to a context, optionally partially applying any
- // arguments.
- proxy: function( fn, context ) {
- var args, proxy, tmp;
-
- if ( typeof context === "string" ) {
- tmp = fn[ context ];
- context = fn;
- fn = tmp;
- }
-
- // Quick check to determine if target is callable, in the spec
- // this throws a TypeError, but we will just return undefined.
- if ( !jQuery.isFunction( fn ) ) {
- return undefined;
- }
-
- // Simulated bind
- args = slice.call( arguments, 2 );
- proxy = function() {
- return fn.apply( context || this, args.concat( slice.call( arguments ) ) );
- };
-
- // Set the guid of unique handler to the same of original handler, so it can be removed
- proxy.guid = fn.guid = fn.guid || jQuery.guid++;
-
- return proxy;
- },
-
- now: function() {
- return +( new Date() );
- },
-
- // jQuery.support is not used in Core but other projects attach their
- // properties to it so it needs to exist.
- support: support
-});
-
-// Populate the class2type map
-jQuery.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) {
- class2type[ "[object " + name + "]" ] = name.toLowerCase();
-});
-
-function isArraylike( obj ) {
- var length = obj.length,
- type = jQuery.type( obj );
-
- if ( type === "function" || jQuery.isWindow( obj ) ) {
- return false;
- }
-
- if ( obj.nodeType === 1 && length ) {
- return true;
- }
-
- return type === "array" || length === 0 ||
- typeof length === "number" && length > 0 && ( length - 1 ) in obj;
-}
-var Sizzle =
-/*!
- * Sizzle CSS Selector Engine v1.10.19
- * http://sizzlejs.com/
- *
- * Copyright 2013 jQuery Foundation, Inc. and other contributors
- * Released under the MIT license
- * http://jquery.org/license
- *
- * Date: 2014-04-18
- */
-(function( window ) {
-
-var i,
- support,
- Expr,
- getText,
- isXML,
- tokenize,
- compile,
- select,
- outermostContext,
- sortInput,
- hasDuplicate,
-
- // Local document vars
- setDocument,
- document,
- docElem,
- documentIsHTML,
- rbuggyQSA,
- rbuggyMatches,
- matches,
- contains,
-
- // Instance-specific data
- expando = "sizzle" + -(new Date()),
- preferredDoc = window.document,
- dirruns = 0,
- done = 0,
- classCache = createCache(),
- tokenCache = createCache(),
- compilerCache = createCache(),
- sortOrder = function( a, b ) {
- if ( a === b ) {
- hasDuplicate = true;
- }
- return 0;
- },
-
- // General-purpose constants
- strundefined = typeof undefined,
- MAX_NEGATIVE = 1 << 31,
-
- // Instance methods
- hasOwn = ({}).hasOwnProperty,
- arr = [],
- pop = arr.pop,
- push_native = arr.push,
- push = arr.push,
- slice = arr.slice,
- // Use a stripped-down indexOf if we can't use a native one
- indexOf = arr.indexOf || function( elem ) {
- var i = 0,
- len = this.length;
- for ( ; i < len; i++ ) {
- if ( this[i] === elem ) {
- return i;
- }
- }
- return -1;
- },
-
- booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",
-
- // Regular expressions
-
- // Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace
- whitespace = "[\\x20\\t\\r\\n\\f]",
- // http://www.w3.org/TR/css3-syntax/#characters
- characterEncoding = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",
-
- // Loosely modeled on CSS identifier characters
- // An unquoted value should be a CSS identifier http://www.w3.org/TR/css3-selectors/#attribute-selectors
- // Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier
- identifier = characterEncoding.replace( "w", "w#" ),
-
- // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors
- attributes = "\\[" + whitespace + "*(" + characterEncoding + ")(?:" + whitespace +
- // Operator (capture 2)
- "*([*^$|!~]?=)" + whitespace +
- // "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]"
- "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace +
- "*\\]",
-
- pseudos = ":(" + characterEncoding + ")(?:\\((" +
- // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments:
- // 1. quoted (capture 3; capture 4 or capture 5)
- "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" +
- // 2. simple (capture 6)
- "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" +
- // 3. anything else (capture 2)
- ".*" +
- ")\\)|)",
-
- // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter
- rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ),
-
- rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ),
- rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ),
-
- rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g" ),
-
- rpseudo = new RegExp( pseudos ),
- ridentifier = new RegExp( "^" + identifier + "$" ),
-
- matchExpr = {
- "ID": new RegExp( "^#(" + characterEncoding + ")" ),
- "CLASS": new RegExp( "^\\.(" + characterEncoding + ")" ),
- "TAG": new RegExp( "^(" + characterEncoding.replace( "w", "w*" ) + ")" ),
- "ATTR": new RegExp( "^" + attributes ),
- "PSEUDO": new RegExp( "^" + pseudos ),
- "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace +
- "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace +
- "*(\\d+)|))" + whitespace + "*\\)|)", "i" ),
- "bool": new RegExp( "^(?:" + booleans + ")$", "i" ),
- // For use in libraries implementing .is()
- // We use this for POS matching in `select`
- "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" +
- whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" )
- },
-
- rinputs = /^(?:input|select|textarea|button)$/i,
- rheader = /^h\d$/i,
-
- rnative = /^[^{]+\{\s*\[native \w/,
-
- // Easily-parseable/retrievable ID or TAG or CLASS selectors
- rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,
-
- rsibling = /[+~]/,
- rescape = /'|\\/g,
-
- // CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters
- runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ),
- funescape = function( _, escaped, escapedWhitespace ) {
- var high = "0x" + escaped - 0x10000;
- // NaN means non-codepoint
- // Support: Firefox<24
- // Workaround erroneous numeric interpretation of +"0x"
- return high !== high || escapedWhitespace ?
- escaped :
- high < 0 ?
- // BMP codepoint
- String.fromCharCode( high + 0x10000 ) :
- // Supplemental Plane codepoint (surrogate pair)
- String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 );
- };
-
-// Optimize for push.apply( _, NodeList )
-try {
- push.apply(
- (arr = slice.call( preferredDoc.childNodes )),
- preferredDoc.childNodes
- );
- // Support: Android<4.0
- // Detect silently failing push.apply
- arr[ preferredDoc.childNodes.length ].nodeType;
-} catch ( e ) {
- push = { apply: arr.length ?
-
- // Leverage slice if possible
- function( target, els ) {
- push_native.apply( target, slice.call(els) );
- } :
-
- // Support: IE<9
- // Otherwise append directly
- function( target, els ) {
- var j = target.length,
- i = 0;
- // Can't trust NodeList.length
- while ( (target[j++] = els[i++]) ) {}
- target.length = j - 1;
- }
- };
-}
-
-function Sizzle( selector, context, results, seed ) {
- var match, elem, m, nodeType,
- // QSA vars
- i, groups, old, nid, newContext, newSelector;
-
- if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) {
- setDocument( context );
- }
-
- context = context || document;
- results = results || [];
-
- if ( !selector || typeof selector !== "string" ) {
- return results;
- }
-
- if ( (nodeType = context.nodeType) !== 1 && nodeType !== 9 ) {
- return [];
- }
-
- if ( documentIsHTML && !seed ) {
-
- // Shortcuts
- if ( (match = rquickExpr.exec( selector )) ) {
- // Speed-up: Sizzle("#ID")
- if ( (m = match[1]) ) {
- if ( nodeType === 9 ) {
- elem = context.getElementById( m );
- // Check parentNode to catch when Blackberry 4.6 returns
- // nodes that are no longer in the document (jQuery #6963)
- if ( elem && elem.parentNode ) {
- // Handle the case where IE, Opera, and Webkit return items
- // by name instead of ID
- if ( elem.id === m ) {
- results.push( elem );
- return results;
- }
- } else {
- return results;
- }
- } else {
- // Context is not a document
- if ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) &&
- contains( context, elem ) && elem.id === m ) {
- results.push( elem );
- return results;
- }
- }
-
- // Speed-up: Sizzle("TAG")
- } else if ( match[2] ) {
- push.apply( results, context.getElementsByTagName( selector ) );
- return results;
-
- // Speed-up: Sizzle(".CLASS")
- } else if ( (m = match[3]) && support.getElementsByClassName && context.getElementsByClassName ) {
- push.apply( results, context.getElementsByClassName( m ) );
- return results;
- }
- }
-
- // QSA path
- if ( support.qsa && (!rbuggyQSA || !rbuggyQSA.test( selector )) ) {
- nid = old = expando;
- newContext = context;
- newSelector = nodeType === 9 && selector;
-
- // qSA works strangely on Element-rooted queries
- // We can work around this by specifying an extra ID on the root
- // and working up from there (Thanks to Andrew Dupont for the technique)
- // IE 8 doesn't work on object elements
- if ( nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) {
- groups = tokenize( selector );
-
- if ( (old = context.getAttribute("id")) ) {
- nid = old.replace( rescape, "\\$&" );
- } else {
- context.setAttribute( "id", nid );
- }
- nid = "[id='" + nid + "'] ";
-
- i = groups.length;
- while ( i-- ) {
- groups[i] = nid + toSelector( groups[i] );
- }
- newContext = rsibling.test( selector ) && testContext( context.parentNode ) || context;
- newSelector = groups.join(",");
- }
-
- if ( newSelector ) {
- try {
- push.apply( results,
- newContext.querySelectorAll( newSelector )
- );
- return results;
- } catch(qsaError) {
- } finally {
- if ( !old ) {
- context.removeAttribute("id");
- }
- }
- }
- }
- }
-
- // All others
- return select( selector.replace( rtrim, "$1" ), context, results, seed );
-}
-
-/**
- * Create key-value caches of limited size
- * @returns {Function(string, Object)} Returns the Object data after storing it on itself with
- * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength)
- * deleting the oldest entry
- */
-function createCache() {
- var keys = [];
-
- function cache( key, value ) {
- // Use (key + " ") to avoid collision with native prototype properties (see Issue #157)
- if ( keys.push( key + " " ) > Expr.cacheLength ) {
- // Only keep the most recent entries
- delete cache[ keys.shift() ];
- }
- return (cache[ key + " " ] = value);
- }
- return cache;
-}
-
-/**
- * Mark a function for special use by Sizzle
- * @param {Function} fn The function to mark
- */
-function markFunction( fn ) {
- fn[ expando ] = true;
- return fn;
-}
-
-/**
- * Support testing using an element
- * @param {Function} fn Passed the created div and expects a boolean result
- */
-function assert( fn ) {
- var div = document.createElement("div");
-
- try {
- return !!fn( div );
- } catch (e) {
- return false;
- } finally {
- // Remove from its parent by default
- if ( div.parentNode ) {
- div.parentNode.removeChild( div );
- }
- // release memory in IE
- div = null;
- }
-}
-
-/**
- * Adds the same handler for all of the specified attrs
- * @param {String} attrs Pipe-separated list of attributes
- * @param {Function} handler The method that will be applied
- */
-function addHandle( attrs, handler ) {
- var arr = attrs.split("|"),
- i = attrs.length;
-
- while ( i-- ) {
- Expr.attrHandle[ arr[i] ] = handler;
- }
-}
-
-/**
- * Checks document order of two siblings
- * @param {Element} a
- * @param {Element} b
- * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b
- */
-function siblingCheck( a, b ) {
- var cur = b && a,
- diff = cur && a.nodeType === 1 && b.nodeType === 1 &&
- ( ~b.sourceIndex || MAX_NEGATIVE ) -
- ( ~a.sourceIndex || MAX_NEGATIVE );
-
- // Use IE sourceIndex if available on both nodes
- if ( diff ) {
- return diff;
- }
-
- // Check if b follows a
- if ( cur ) {
- while ( (cur = cur.nextSibling) ) {
- if ( cur === b ) {
- return -1;
- }
- }
- }
-
- return a ? 1 : -1;
-}
-
-/**
- * Returns a function to use in pseudos for input types
- * @param {String} type
- */
-function createInputPseudo( type ) {
- return function( elem ) {
- var name = elem.nodeName.toLowerCase();
- return name === "input" && elem.type === type;
- };
-}
-
-/**
- * Returns a function to use in pseudos for buttons
- * @param {String} type
- */
-function createButtonPseudo( type ) {
- return function( elem ) {
- var name = elem.nodeName.toLowerCase();
- return (name === "input" || name === "button") && elem.type === type;
- };
-}
-
-/**
- * Returns a function to use in pseudos for positionals
- * @param {Function} fn
- */
-function createPositionalPseudo( fn ) {
- return markFunction(function( argument ) {
- argument = +argument;
- return markFunction(function( seed, matches ) {
- var j,
- matchIndexes = fn( [], seed.length, argument ),
- i = matchIndexes.length;
-
- // Match elements found at the specified indexes
- while ( i-- ) {
- if ( seed[ (j = matchIndexes[i]) ] ) {
- seed[j] = !(matches[j] = seed[j]);
- }
- }
- });
- });
-}
-
-/**
- * Checks a node for validity as a Sizzle context
- * @param {Element|Object=} context
- * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value
- */
-function testContext( context ) {
- return context && typeof context.getElementsByTagName !== strundefined && context;
-}
-
-// Expose support vars for convenience
-support = Sizzle.support = {};
-
-/**
- * Detects XML nodes
- * @param {Element|Object} elem An element or a document
- * @returns {Boolean} True iff elem is a non-HTML XML node
- */
-isXML = Sizzle.isXML = function( elem ) {
- // documentElement is verified for cases where it doesn't yet exist
- // (such as loading iframes in IE - #4833)
- var documentElement = elem && (elem.ownerDocument || elem).documentElement;
- return documentElement ? documentElement.nodeName !== "HTML" : false;
-};
-
-/**
- * Sets document-related variables once based on the current document
- * @param {Element|Object} [doc] An element or document object to use to set the document
- * @returns {Object} Returns the current document
- */
-setDocument = Sizzle.setDocument = function( node ) {
- var hasCompare,
- doc = node ? node.ownerDocument || node : preferredDoc,
- parent = doc.defaultView;
-
- // If no document and documentElement is available, return
- if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) {
- return document;
- }
-
- // Set our document
- document = doc;
- docElem = doc.documentElement;
-
- // Support tests
- documentIsHTML = !isXML( doc );
-
- // Support: IE>8
- // If iframe document is assigned to "document" variable and if iframe has been reloaded,
- // IE will throw "permission denied" error when accessing "document" variable, see jQuery #13936
- // IE6-8 do not support the defaultView property so parent will be undefined
- if ( parent && parent !== parent.top ) {
- // IE11 does not have attachEvent, so all must suffer
- if ( parent.addEventListener ) {
- parent.addEventListener( "unload", function() {
- setDocument();
- }, false );
- } else if ( parent.attachEvent ) {
- parent.attachEvent( "onunload", function() {
- setDocument();
- });
- }
- }
-
- /* Attributes
- ---------------------------------------------------------------------- */
-
- // Support: IE<8
- // Verify that getAttribute really returns attributes and not properties (excepting IE8 booleans)
- support.attributes = assert(function( div ) {
- div.className = "i";
- return !div.getAttribute("className");
- });
-
- /* getElement(s)By*
- ---------------------------------------------------------------------- */
-
- // Check if getElementsByTagName("*") returns only elements
- support.getElementsByTagName = assert(function( div ) {
- div.appendChild( doc.createComment("") );
- return !div.getElementsByTagName("*").length;
- });
-
- // Check if getElementsByClassName can be trusted
- support.getElementsByClassName = rnative.test( doc.getElementsByClassName ) && assert(function( div ) {
- div.innerHTML = "
";
-
- // Support: Safari<4
- // Catch class over-caching
- div.firstChild.className = "i";
- // Support: Opera<10
- // Catch gEBCN failure to find non-leading classes
- return div.getElementsByClassName("i").length === 2;
- });
-
- // Support: IE<10
- // Check if getElementById returns elements by name
- // The broken getElementById methods don't pick up programatically-set names,
- // so use a roundabout getElementsByName test
- support.getById = assert(function( div ) {
- docElem.appendChild( div ).id = expando;
- return !doc.getElementsByName || !doc.getElementsByName( expando ).length;
- });
-
- // ID find and filter
- if ( support.getById ) {
- Expr.find["ID"] = function( id, context ) {
- if ( typeof context.getElementById !== strundefined && documentIsHTML ) {
- var m = context.getElementById( id );
- // Check parentNode to catch when Blackberry 4.6 returns
- // nodes that are no longer in the document #6963
- return m && m.parentNode ? [ m ] : [];
- }
- };
- Expr.filter["ID"] = function( id ) {
- var attrId = id.replace( runescape, funescape );
- return function( elem ) {
- return elem.getAttribute("id") === attrId;
- };
- };
- } else {
- // Support: IE6/7
- // getElementById is not reliable as a find shortcut
- delete Expr.find["ID"];
-
- Expr.filter["ID"] = function( id ) {
- var attrId = id.replace( runescape, funescape );
- return function( elem ) {
- var node = typeof elem.getAttributeNode !== strundefined && elem.getAttributeNode("id");
- return node && node.value === attrId;
- };
- };
- }
-
- // Tag
- Expr.find["TAG"] = support.getElementsByTagName ?
- function( tag, context ) {
- if ( typeof context.getElementsByTagName !== strundefined ) {
- return context.getElementsByTagName( tag );
- }
- } :
- function( tag, context ) {
- var elem,
- tmp = [],
- i = 0,
- results = context.getElementsByTagName( tag );
-
- // Filter out possible comments
- if ( tag === "*" ) {
- while ( (elem = results[i++]) ) {
- if ( elem.nodeType === 1 ) {
- tmp.push( elem );
- }
- }
-
- return tmp;
- }
- return results;
- };
-
- // Class
- Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) {
- if ( typeof context.getElementsByClassName !== strundefined && documentIsHTML ) {
- return context.getElementsByClassName( className );
- }
- };
-
- /* QSA/matchesSelector
- ---------------------------------------------------------------------- */
-
- // QSA and matchesSelector support
-
- // matchesSelector(:active) reports false when true (IE9/Opera 11.5)
- rbuggyMatches = [];
-
- // qSa(:focus) reports false when true (Chrome 21)
- // We allow this because of a bug in IE8/9 that throws an error
- // whenever `document.activeElement` is accessed on an iframe
- // So, we allow :focus to pass through QSA all the time to avoid the IE error
- // See http://bugs.jquery.com/ticket/13378
- rbuggyQSA = [];
-
- if ( (support.qsa = rnative.test( doc.querySelectorAll )) ) {
- // Build QSA regex
- // Regex strategy adopted from Diego Perini
- assert(function( div ) {
- // Select is set to empty string on purpose
- // This is to test IE's treatment of not explicitly
- // setting a boolean content attribute,
- // since its presence should be enough
- // http://bugs.jquery.com/ticket/12359
- div.innerHTML = "";
-
- // Support: IE8, Opera 11-12.16
- // Nothing should be selected when empty strings follow ^= or $= or *=
- // The test attribute must be unknown in Opera but "safe" for WinRT
- // http://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section
- if ( div.querySelectorAll("[msallowclip^='']").length ) {
- rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" );
- }
-
- // Support: IE8
- // Boolean attributes and "value" are not treated correctly
- if ( !div.querySelectorAll("[selected]").length ) {
- rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" );
- }
-
- // Webkit/Opera - :checked should return selected option elements
- // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
- // IE8 throws error here and will not see later tests
- if ( !div.querySelectorAll(":checked").length ) {
- rbuggyQSA.push(":checked");
- }
- });
-
- assert(function( div ) {
- // Support: Windows 8 Native Apps
- // The type and name attributes are restricted during .innerHTML assignment
- var input = doc.createElement("input");
- input.setAttribute( "type", "hidden" );
- div.appendChild( input ).setAttribute( "name", "D" );
-
- // Support: IE8
- // Enforce case-sensitivity of name attribute
- if ( div.querySelectorAll("[name=d]").length ) {
- rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" );
- }
-
- // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)
- // IE8 throws error here and will not see later tests
- if ( !div.querySelectorAll(":enabled").length ) {
- rbuggyQSA.push( ":enabled", ":disabled" );
- }
-
- // Opera 10-11 does not throw on post-comma invalid pseudos
- div.querySelectorAll("*,:x");
- rbuggyQSA.push(",.*:");
- });
- }
-
- if ( (support.matchesSelector = rnative.test( (matches = docElem.matches ||
- docElem.webkitMatchesSelector ||
- docElem.mozMatchesSelector ||
- docElem.oMatchesSelector ||
- docElem.msMatchesSelector) )) ) {
-
- assert(function( div ) {
- // Check to see if it's possible to do matchesSelector
- // on a disconnected node (IE 9)
- support.disconnectedMatch = matches.call( div, "div" );
-
- // This should fail with an exception
- // Gecko does not error, returns false instead
- matches.call( div, "[s!='']:x" );
- rbuggyMatches.push( "!=", pseudos );
- });
- }
-
- rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") );
- rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") );
-
- /* Contains
- ---------------------------------------------------------------------- */
- hasCompare = rnative.test( docElem.compareDocumentPosition );
-
- // Element contains another
- // Purposefully does not implement inclusive descendent
- // As in, an element does not contain itself
- contains = hasCompare || rnative.test( docElem.contains ) ?
- function( a, b ) {
- var adown = a.nodeType === 9 ? a.documentElement : a,
- bup = b && b.parentNode;
- return a === bup || !!( bup && bup.nodeType === 1 && (
- adown.contains ?
- adown.contains( bup ) :
- a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16
- ));
- } :
- function( a, b ) {
- if ( b ) {
- while ( (b = b.parentNode) ) {
- if ( b === a ) {
- return true;
- }
- }
- }
- return false;
- };
-
- /* Sorting
- ---------------------------------------------------------------------- */
-
- // Document order sorting
- sortOrder = hasCompare ?
- function( a, b ) {
-
- // Flag for duplicate removal
- if ( a === b ) {
- hasDuplicate = true;
- return 0;
- }
-
- // Sort on method existence if only one input has compareDocumentPosition
- var compare = !a.compareDocumentPosition - !b.compareDocumentPosition;
- if ( compare ) {
- return compare;
- }
-
- // Calculate position if both inputs belong to the same document
- compare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ?
- a.compareDocumentPosition( b ) :
-
- // Otherwise we know they are disconnected
- 1;
-
- // Disconnected nodes
- if ( compare & 1 ||
- (!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) {
-
- // Choose the first element that is related to our preferred document
- if ( a === doc || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) {
- return -1;
- }
- if ( b === doc || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) {
- return 1;
- }
-
- // Maintain original order
- return sortInput ?
- ( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) :
- 0;
- }
-
- return compare & 4 ? -1 : 1;
- } :
- function( a, b ) {
- // Exit early if the nodes are identical
- if ( a === b ) {
- hasDuplicate = true;
- return 0;
- }
-
- var cur,
- i = 0,
- aup = a.parentNode,
- bup = b.parentNode,
- ap = [ a ],
- bp = [ b ];
-
- // Parentless nodes are either documents or disconnected
- if ( !aup || !bup ) {
- return a === doc ? -1 :
- b === doc ? 1 :
- aup ? -1 :
- bup ? 1 :
- sortInput ?
- ( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) :
- 0;
-
- // If the nodes are siblings, we can do a quick check
- } else if ( aup === bup ) {
- return siblingCheck( a, b );
- }
-
- // Otherwise we need full lists of their ancestors for comparison
- cur = a;
- while ( (cur = cur.parentNode) ) {
- ap.unshift( cur );
- }
- cur = b;
- while ( (cur = cur.parentNode) ) {
- bp.unshift( cur );
- }
-
- // Walk down the tree looking for a discrepancy
- while ( ap[i] === bp[i] ) {
- i++;
- }
-
- return i ?
- // Do a sibling check if the nodes have a common ancestor
- siblingCheck( ap[i], bp[i] ) :
-
- // Otherwise nodes in our document sort first
- ap[i] === preferredDoc ? -1 :
- bp[i] === preferredDoc ? 1 :
- 0;
- };
-
- return doc;
-};
-
-Sizzle.matches = function( expr, elements ) {
- return Sizzle( expr, null, null, elements );
-};
-
-Sizzle.matchesSelector = function( elem, expr ) {
- // Set document vars if needed
- if ( ( elem.ownerDocument || elem ) !== document ) {
- setDocument( elem );
- }
-
- // Make sure that attribute selectors are quoted
- expr = expr.replace( rattributeQuotes, "='$1']" );
-
- if ( support.matchesSelector && documentIsHTML &&
- ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) &&
- ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) {
-
- try {
- var ret = matches.call( elem, expr );
-
- // IE 9's matchesSelector returns false on disconnected nodes
- if ( ret || support.disconnectedMatch ||
- // As well, disconnected nodes are said to be in a document
- // fragment in IE 9
- elem.document && elem.document.nodeType !== 11 ) {
- return ret;
- }
- } catch(e) {}
- }
-
- return Sizzle( expr, document, null, [ elem ] ).length > 0;
-};
-
-Sizzle.contains = function( context, elem ) {
- // Set document vars if needed
- if ( ( context.ownerDocument || context ) !== document ) {
- setDocument( context );
- }
- return contains( context, elem );
-};
-
-Sizzle.attr = function( elem, name ) {
- // Set document vars if needed
- if ( ( elem.ownerDocument || elem ) !== document ) {
- setDocument( elem );
- }
-
- var fn = Expr.attrHandle[ name.toLowerCase() ],
- // Don't get fooled by Object.prototype properties (jQuery #13807)
- val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ?
- fn( elem, name, !documentIsHTML ) :
- undefined;
-
- return val !== undefined ?
- val :
- support.attributes || !documentIsHTML ?
- elem.getAttribute( name ) :
- (val = elem.getAttributeNode(name)) && val.specified ?
- val.value :
- null;
-};
-
-Sizzle.error = function( msg ) {
- throw new Error( "Syntax error, unrecognized expression: " + msg );
-};
-
-/**
- * Document sorting and removing duplicates
- * @param {ArrayLike} results
- */
-Sizzle.uniqueSort = function( results ) {
- var elem,
- duplicates = [],
- j = 0,
- i = 0;
-
- // Unless we *know* we can detect duplicates, assume their presence
- hasDuplicate = !support.detectDuplicates;
- sortInput = !support.sortStable && results.slice( 0 );
- results.sort( sortOrder );
-
- if ( hasDuplicate ) {
- while ( (elem = results[i++]) ) {
- if ( elem === results[ i ] ) {
- j = duplicates.push( i );
- }
- }
- while ( j-- ) {
- results.splice( duplicates[ j ], 1 );
- }
- }
-
- // Clear input after sorting to release objects
- // See https://github.com/jquery/sizzle/pull/225
- sortInput = null;
-
- return results;
-};
-
-/**
- * Utility function for retrieving the text value of an array of DOM nodes
- * @param {Array|Element} elem
- */
-getText = Sizzle.getText = function( elem ) {
- var node,
- ret = "",
- i = 0,
- nodeType = elem.nodeType;
-
- if ( !nodeType ) {
- // If no nodeType, this is expected to be an array
- while ( (node = elem[i++]) ) {
- // Do not traverse comment nodes
- ret += getText( node );
- }
- } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {
- // Use textContent for elements
- // innerText usage removed for consistency of new lines (jQuery #11153)
- if ( typeof elem.textContent === "string" ) {
- return elem.textContent;
- } else {
- // Traverse its children
- for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
- ret += getText( elem );
- }
- }
- } else if ( nodeType === 3 || nodeType === 4 ) {
- return elem.nodeValue;
- }
- // Do not include comment or processing instruction nodes
-
- return ret;
-};
-
-Expr = Sizzle.selectors = {
-
- // Can be adjusted by the user
- cacheLength: 50,
-
- createPseudo: markFunction,
-
- match: matchExpr,
-
- attrHandle: {},
-
- find: {},
-
- relative: {
- ">": { dir: "parentNode", first: true },
- " ": { dir: "parentNode" },
- "+": { dir: "previousSibling", first: true },
- "~": { dir: "previousSibling" }
- },
-
- preFilter: {
- "ATTR": function( match ) {
- match[1] = match[1].replace( runescape, funescape );
-
- // Move the given value to match[3] whether quoted or unquoted
- match[3] = ( match[3] || match[4] || match[5] || "" ).replace( runescape, funescape );
-
- if ( match[2] === "~=" ) {
- match[3] = " " + match[3] + " ";
- }
-
- return match.slice( 0, 4 );
- },
-
- "CHILD": function( match ) {
- /* matches from matchExpr["CHILD"]
- 1 type (only|nth|...)
- 2 what (child|of-type)
- 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...)
- 4 xn-component of xn+y argument ([+-]?\d*n|)
- 5 sign of xn-component
- 6 x of xn-component
- 7 sign of y-component
- 8 y of y-component
- */
- match[1] = match[1].toLowerCase();
-
- if ( match[1].slice( 0, 3 ) === "nth" ) {
- // nth-* requires argument
- if ( !match[3] ) {
- Sizzle.error( match[0] );
- }
-
- // numeric x and y parameters for Expr.filter.CHILD
- // remember that false/true cast respectively to 0/1
- match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) );
- match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" );
-
- // other types prohibit arguments
- } else if ( match[3] ) {
- Sizzle.error( match[0] );
- }
-
- return match;
- },
-
- "PSEUDO": function( match ) {
- var excess,
- unquoted = !match[6] && match[2];
-
- if ( matchExpr["CHILD"].test( match[0] ) ) {
- return null;
- }
-
- // Accept quoted arguments as-is
- if ( match[3] ) {
- match[2] = match[4] || match[5] || "";
-
- // Strip excess characters from unquoted arguments
- } else if ( unquoted && rpseudo.test( unquoted ) &&
- // Get excess from tokenize (recursively)
- (excess = tokenize( unquoted, true )) &&
- // advance to the next closing parenthesis
- (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) {
-
- // excess is a negative index
- match[0] = match[0].slice( 0, excess );
- match[2] = unquoted.slice( 0, excess );
- }
-
- // Return only captures needed by the pseudo filter method (type and argument)
- return match.slice( 0, 3 );
- }
- },
-
- filter: {
-
- "TAG": function( nodeNameSelector ) {
- var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase();
- return nodeNameSelector === "*" ?
- function() { return true; } :
- function( elem ) {
- return elem.nodeName && elem.nodeName.toLowerCase() === nodeName;
- };
- },
-
- "CLASS": function( className ) {
- var pattern = classCache[ className + " " ];
-
- return pattern ||
- (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) &&
- classCache( className, function( elem ) {
- return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== strundefined && elem.getAttribute("class") || "" );
- });
- },
-
- "ATTR": function( name, operator, check ) {
- return function( elem ) {
- var result = Sizzle.attr( elem, name );
-
- if ( result == null ) {
- return operator === "!=";
- }
- if ( !operator ) {
- return true;
- }
-
- result += "";
-
- return operator === "=" ? result === check :
- operator === "!=" ? result !== check :
- operator === "^=" ? check && result.indexOf( check ) === 0 :
- operator === "*=" ? check && result.indexOf( check ) > -1 :
- operator === "$=" ? check && result.slice( -check.length ) === check :
- operator === "~=" ? ( " " + result + " " ).indexOf( check ) > -1 :
- operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" :
- false;
- };
- },
-
- "CHILD": function( type, what, argument, first, last ) {
- var simple = type.slice( 0, 3 ) !== "nth",
- forward = type.slice( -4 ) !== "last",
- ofType = what === "of-type";
-
- return first === 1 && last === 0 ?
-
- // Shortcut for :nth-*(n)
- function( elem ) {
- return !!elem.parentNode;
- } :
-
- function( elem, context, xml ) {
- var cache, outerCache, node, diff, nodeIndex, start,
- dir = simple !== forward ? "nextSibling" : "previousSibling",
- parent = elem.parentNode,
- name = ofType && elem.nodeName.toLowerCase(),
- useCache = !xml && !ofType;
-
- if ( parent ) {
-
- // :(first|last|only)-(child|of-type)
- if ( simple ) {
- while ( dir ) {
- node = elem;
- while ( (node = node[ dir ]) ) {
- if ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) {
- return false;
- }
- }
- // Reverse direction for :only-* (if we haven't yet done so)
- start = dir = type === "only" && !start && "nextSibling";
- }
- return true;
- }
-
- start = [ forward ? parent.firstChild : parent.lastChild ];
-
- // non-xml :nth-child(...) stores cache data on `parent`
- if ( forward && useCache ) {
- // Seek `elem` from a previously-cached index
- outerCache = parent[ expando ] || (parent[ expando ] = {});
- cache = outerCache[ type ] || [];
- nodeIndex = cache[0] === dirruns && cache[1];
- diff = cache[0] === dirruns && cache[2];
- node = nodeIndex && parent.childNodes[ nodeIndex ];
-
- while ( (node = ++nodeIndex && node && node[ dir ] ||
-
- // Fallback to seeking `elem` from the start
- (diff = nodeIndex = 0) || start.pop()) ) {
-
- // When found, cache indexes on `parent` and break
- if ( node.nodeType === 1 && ++diff && node === elem ) {
- outerCache[ type ] = [ dirruns, nodeIndex, diff ];
- break;
- }
- }
-
- // Use previously-cached element index if available
- } else if ( useCache && (cache = (elem[ expando ] || (elem[ expando ] = {}))[ type ]) && cache[0] === dirruns ) {
- diff = cache[1];
-
- // xml :nth-child(...) or :nth-last-child(...) or :nth(-last)?-of-type(...)
- } else {
- // Use the same loop as above to seek `elem` from the start
- while ( (node = ++nodeIndex && node && node[ dir ] ||
- (diff = nodeIndex = 0) || start.pop()) ) {
-
- if ( ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) && ++diff ) {
- // Cache the index of each encountered element
- if ( useCache ) {
- (node[ expando ] || (node[ expando ] = {}))[ type ] = [ dirruns, diff ];
- }
-
- if ( node === elem ) {
- break;
- }
- }
- }
- }
-
- // Incorporate the offset, then check against cycle size
- diff -= last;
- return diff === first || ( diff % first === 0 && diff / first >= 0 );
- }
- };
- },
-
- "PSEUDO": function( pseudo, argument ) {
- // pseudo-class names are case-insensitive
- // http://www.w3.org/TR/selectors/#pseudo-classes
- // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters
- // Remember that setFilters inherits from pseudos
- var args,
- fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||
- Sizzle.error( "unsupported pseudo: " + pseudo );
-
- // The user may use createPseudo to indicate that
- // arguments are needed to create the filter function
- // just as Sizzle does
- if ( fn[ expando ] ) {
- return fn( argument );
- }
-
- // But maintain support for old signatures
- if ( fn.length > 1 ) {
- args = [ pseudo, pseudo, "", argument ];
- return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ?
- markFunction(function( seed, matches ) {
- var idx,
- matched = fn( seed, argument ),
- i = matched.length;
- while ( i-- ) {
- idx = indexOf.call( seed, matched[i] );
- seed[ idx ] = !( matches[ idx ] = matched[i] );
- }
- }) :
- function( elem ) {
- return fn( elem, 0, args );
- };
- }
-
- return fn;
- }
- },
-
- pseudos: {
- // Potentially complex pseudos
- "not": markFunction(function( selector ) {
- // Trim the selector passed to compile
- // to avoid treating leading and trailing
- // spaces as combinators
- var input = [],
- results = [],
- matcher = compile( selector.replace( rtrim, "$1" ) );
-
- return matcher[ expando ] ?
- markFunction(function( seed, matches, context, xml ) {
- var elem,
- unmatched = matcher( seed, null, xml, [] ),
- i = seed.length;
-
- // Match elements unmatched by `matcher`
- while ( i-- ) {
- if ( (elem = unmatched[i]) ) {
- seed[i] = !(matches[i] = elem);
- }
- }
- }) :
- function( elem, context, xml ) {
- input[0] = elem;
- matcher( input, null, xml, results );
- return !results.pop();
- };
- }),
-
- "has": markFunction(function( selector ) {
- return function( elem ) {
- return Sizzle( selector, elem ).length > 0;
- };
- }),
-
- "contains": markFunction(function( text ) {
- return function( elem ) {
- return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1;
- };
- }),
-
- // "Whether an element is represented by a :lang() selector
- // is based solely on the element's language value
- // being equal to the identifier C,
- // or beginning with the identifier C immediately followed by "-".
- // The matching of C against the element's language value is performed case-insensitively.
- // The identifier C does not have to be a valid language name."
- // http://www.w3.org/TR/selectors/#lang-pseudo
- "lang": markFunction( function( lang ) {
- // lang value must be a valid identifier
- if ( !ridentifier.test(lang || "") ) {
- Sizzle.error( "unsupported lang: " + lang );
- }
- lang = lang.replace( runescape, funescape ).toLowerCase();
- return function( elem ) {
- var elemLang;
- do {
- if ( (elemLang = documentIsHTML ?
- elem.lang :
- elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) {
-
- elemLang = elemLang.toLowerCase();
- return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0;
- }
- } while ( (elem = elem.parentNode) && elem.nodeType === 1 );
- return false;
- };
- }),
-
- // Miscellaneous
- "target": function( elem ) {
- var hash = window.location && window.location.hash;
- return hash && hash.slice( 1 ) === elem.id;
- },
-
- "root": function( elem ) {
- return elem === docElem;
- },
-
- "focus": function( elem ) {
- return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex);
- },
-
- // Boolean properties
- "enabled": function( elem ) {
- return elem.disabled === false;
- },
-
- "disabled": function( elem ) {
- return elem.disabled === true;
- },
-
- "checked": function( elem ) {
- // In CSS3, :checked should return both checked and selected elements
- // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
- var nodeName = elem.nodeName.toLowerCase();
- return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected);
- },
-
- "selected": function( elem ) {
- // Accessing this property makes selected-by-default
- // options in Safari work properly
- if ( elem.parentNode ) {
- elem.parentNode.selectedIndex;
- }
-
- return elem.selected === true;
- },
-
- // Contents
- "empty": function( elem ) {
- // http://www.w3.org/TR/selectors/#empty-pseudo
- // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5),
- // but not by others (comment: 8; processing instruction: 7; etc.)
- // nodeType < 6 works because attributes (2) do not appear as children
- for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
- if ( elem.nodeType < 6 ) {
- return false;
- }
- }
- return true;
- },
-
- "parent": function( elem ) {
- return !Expr.pseudos["empty"]( elem );
- },
-
- // Element/input types
- "header": function( elem ) {
- return rheader.test( elem.nodeName );
- },
-
- "input": function( elem ) {
- return rinputs.test( elem.nodeName );
- },
-
- "button": function( elem ) {
- var name = elem.nodeName.toLowerCase();
- return name === "input" && elem.type === "button" || name === "button";
- },
-
- "text": function( elem ) {
- var attr;
- return elem.nodeName.toLowerCase() === "input" &&
- elem.type === "text" &&
-
- // Support: IE<8
- // New HTML5 attribute values (e.g., "search") appear with elem.type === "text"
- ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === "text" );
- },
-
- // Position-in-collection
- "first": createPositionalPseudo(function() {
- return [ 0 ];
- }),
-
- "last": createPositionalPseudo(function( matchIndexes, length ) {
- return [ length - 1 ];
- }),
-
- "eq": createPositionalPseudo(function( matchIndexes, length, argument ) {
- return [ argument < 0 ? argument + length : argument ];
- }),
-
- "even": createPositionalPseudo(function( matchIndexes, length ) {
- var i = 0;
- for ( ; i < length; i += 2 ) {
- matchIndexes.push( i );
- }
- return matchIndexes;
- }),
-
- "odd": createPositionalPseudo(function( matchIndexes, length ) {
- var i = 1;
- for ( ; i < length; i += 2 ) {
- matchIndexes.push( i );
- }
- return matchIndexes;
- }),
-
- "lt": createPositionalPseudo(function( matchIndexes, length, argument ) {
- var i = argument < 0 ? argument + length : argument;
- for ( ; --i >= 0; ) {
- matchIndexes.push( i );
- }
- return matchIndexes;
- }),
-
- "gt": createPositionalPseudo(function( matchIndexes, length, argument ) {
- var i = argument < 0 ? argument + length : argument;
- for ( ; ++i < length; ) {
- matchIndexes.push( i );
- }
- return matchIndexes;
- })
- }
-};
-
-Expr.pseudos["nth"] = Expr.pseudos["eq"];
-
-// Add button/input type pseudos
-for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) {
- Expr.pseudos[ i ] = createInputPseudo( i );
-}
-for ( i in { submit: true, reset: true } ) {
- Expr.pseudos[ i ] = createButtonPseudo( i );
-}
-
-// Easy API for creating new setFilters
-function setFilters() {}
-setFilters.prototype = Expr.filters = Expr.pseudos;
-Expr.setFilters = new setFilters();
-
-tokenize = Sizzle.tokenize = function( selector, parseOnly ) {
- var matched, match, tokens, type,
- soFar, groups, preFilters,
- cached = tokenCache[ selector + " " ];
-
- if ( cached ) {
- return parseOnly ? 0 : cached.slice( 0 );
- }
-
- soFar = selector;
- groups = [];
- preFilters = Expr.preFilter;
-
- while ( soFar ) {
-
- // Comma and first run
- if ( !matched || (match = rcomma.exec( soFar )) ) {
- if ( match ) {
- // Don't consume trailing commas as valid
- soFar = soFar.slice( match[0].length ) || soFar;
- }
- groups.push( (tokens = []) );
- }
-
- matched = false;
-
- // Combinators
- if ( (match = rcombinators.exec( soFar )) ) {
- matched = match.shift();
- tokens.push({
- value: matched,
- // Cast descendant combinators to space
- type: match[0].replace( rtrim, " " )
- });
- soFar = soFar.slice( matched.length );
- }
-
- // Filters
- for ( type in Expr.filter ) {
- if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] ||
- (match = preFilters[ type ]( match ))) ) {
- matched = match.shift();
- tokens.push({
- value: matched,
- type: type,
- matches: match
- });
- soFar = soFar.slice( matched.length );
- }
- }
-
- if ( !matched ) {
- break;
- }
- }
-
- // Return the length of the invalid excess
- // if we're just parsing
- // Otherwise, throw an error or return tokens
- return parseOnly ?
- soFar.length :
- soFar ?
- Sizzle.error( selector ) :
- // Cache the tokens
- tokenCache( selector, groups ).slice( 0 );
-};
-
-function toSelector( tokens ) {
- var i = 0,
- len = tokens.length,
- selector = "";
- for ( ; i < len; i++ ) {
- selector += tokens[i].value;
- }
- return selector;
-}
-
-function addCombinator( matcher, combinator, base ) {
- var dir = combinator.dir,
- checkNonElements = base && dir === "parentNode",
- doneName = done++;
-
- return combinator.first ?
- // Check against closest ancestor/preceding element
- function( elem, context, xml ) {
- while ( (elem = elem[ dir ]) ) {
- if ( elem.nodeType === 1 || checkNonElements ) {
- return matcher( elem, context, xml );
- }
- }
- } :
-
- // Check against all ancestor/preceding elements
- function( elem, context, xml ) {
- var oldCache, outerCache,
- newCache = [ dirruns, doneName ];
-
- // We can't set arbitrary data on XML nodes, so they don't benefit from dir caching
- if ( xml ) {
- while ( (elem = elem[ dir ]) ) {
- if ( elem.nodeType === 1 || checkNonElements ) {
- if ( matcher( elem, context, xml ) ) {
- return true;
- }
- }
- }
- } else {
- while ( (elem = elem[ dir ]) ) {
- if ( elem.nodeType === 1 || checkNonElements ) {
- outerCache = elem[ expando ] || (elem[ expando ] = {});
- if ( (oldCache = outerCache[ dir ]) &&
- oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) {
-
- // Assign to newCache so results back-propagate to previous elements
- return (newCache[ 2 ] = oldCache[ 2 ]);
- } else {
- // Reuse newcache so results back-propagate to previous elements
- outerCache[ dir ] = newCache;
-
- // A match means we're done; a fail means we have to keep checking
- if ( (newCache[ 2 ] = matcher( elem, context, xml )) ) {
- return true;
- }
- }
- }
- }
- }
- };
-}
-
-function elementMatcher( matchers ) {
- return matchers.length > 1 ?
- function( elem, context, xml ) {
- var i = matchers.length;
- while ( i-- ) {
- if ( !matchers[i]( elem, context, xml ) ) {
- return false;
- }
- }
- return true;
- } :
- matchers[0];
-}
-
-function multipleContexts( selector, contexts, results ) {
- var i = 0,
- len = contexts.length;
- for ( ; i < len; i++ ) {
- Sizzle( selector, contexts[i], results );
- }
- return results;
-}
-
-function condense( unmatched, map, filter, context, xml ) {
- var elem,
- newUnmatched = [],
- i = 0,
- len = unmatched.length,
- mapped = map != null;
-
- for ( ; i < len; i++ ) {
- if ( (elem = unmatched[i]) ) {
- if ( !filter || filter( elem, context, xml ) ) {
- newUnmatched.push( elem );
- if ( mapped ) {
- map.push( i );
- }
- }
- }
- }
-
- return newUnmatched;
-}
-
-function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) {
- if ( postFilter && !postFilter[ expando ] ) {
- postFilter = setMatcher( postFilter );
- }
- if ( postFinder && !postFinder[ expando ] ) {
- postFinder = setMatcher( postFinder, postSelector );
- }
- return markFunction(function( seed, results, context, xml ) {
- var temp, i, elem,
- preMap = [],
- postMap = [],
- preexisting = results.length,
-
- // Get initial elements from seed or context
- elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ),
-
- // Prefilter to get matcher input, preserving a map for seed-results synchronization
- matcherIn = preFilter && ( seed || !selector ) ?
- condense( elems, preMap, preFilter, context, xml ) :
- elems,
-
- matcherOut = matcher ?
- // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results,
- postFinder || ( seed ? preFilter : preexisting || postFilter ) ?
-
- // ...intermediate processing is necessary
- [] :
-
- // ...otherwise use results directly
- results :
- matcherIn;
-
- // Find primary matches
- if ( matcher ) {
- matcher( matcherIn, matcherOut, context, xml );
- }
-
- // Apply postFilter
- if ( postFilter ) {
- temp = condense( matcherOut, postMap );
- postFilter( temp, [], context, xml );
-
- // Un-match failing elements by moving them back to matcherIn
- i = temp.length;
- while ( i-- ) {
- if ( (elem = temp[i]) ) {
- matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem);
- }
- }
- }
-
- if ( seed ) {
- if ( postFinder || preFilter ) {
- if ( postFinder ) {
- // Get the final matcherOut by condensing this intermediate into postFinder contexts
- temp = [];
- i = matcherOut.length;
- while ( i-- ) {
- if ( (elem = matcherOut[i]) ) {
- // Restore matcherIn since elem is not yet a final match
- temp.push( (matcherIn[i] = elem) );
- }
- }
- postFinder( null, (matcherOut = []), temp, xml );
- }
-
- // Move matched elements from seed to results to keep them synchronized
- i = matcherOut.length;
- while ( i-- ) {
- if ( (elem = matcherOut[i]) &&
- (temp = postFinder ? indexOf.call( seed, elem ) : preMap[i]) > -1 ) {
-
- seed[temp] = !(results[temp] = elem);
- }
- }
- }
-
- // Add elements to results, through postFinder if defined
- } else {
- matcherOut = condense(
- matcherOut === results ?
- matcherOut.splice( preexisting, matcherOut.length ) :
- matcherOut
- );
- if ( postFinder ) {
- postFinder( null, results, matcherOut, xml );
- } else {
- push.apply( results, matcherOut );
- }
- }
- });
-}
-
-function matcherFromTokens( tokens ) {
- var checkContext, matcher, j,
- len = tokens.length,
- leadingRelative = Expr.relative[ tokens[0].type ],
- implicitRelative = leadingRelative || Expr.relative[" "],
- i = leadingRelative ? 1 : 0,
-
- // The foundational matcher ensures that elements are reachable from top-level context(s)
- matchContext = addCombinator( function( elem ) {
- return elem === checkContext;
- }, implicitRelative, true ),
- matchAnyContext = addCombinator( function( elem ) {
- return indexOf.call( checkContext, elem ) > -1;
- }, implicitRelative, true ),
- matchers = [ function( elem, context, xml ) {
- return ( !leadingRelative && ( xml || context !== outermostContext ) ) || (
- (checkContext = context).nodeType ?
- matchContext( elem, context, xml ) :
- matchAnyContext( elem, context, xml ) );
- } ];
-
- for ( ; i < len; i++ ) {
- if ( (matcher = Expr.relative[ tokens[i].type ]) ) {
- matchers = [ addCombinator(elementMatcher( matchers ), matcher) ];
- } else {
- matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches );
-
- // Return special upon seeing a positional matcher
- if ( matcher[ expando ] ) {
- // Find the next relative operator (if any) for proper handling
- j = ++i;
- for ( ; j < len; j++ ) {
- if ( Expr.relative[ tokens[j].type ] ) {
- break;
- }
- }
- return setMatcher(
- i > 1 && elementMatcher( matchers ),
- i > 1 && toSelector(
- // If the preceding token was a descendant combinator, insert an implicit any-element `*`
- tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" })
- ).replace( rtrim, "$1" ),
- matcher,
- i < j && matcherFromTokens( tokens.slice( i, j ) ),
- j < len && matcherFromTokens( (tokens = tokens.slice( j )) ),
- j < len && toSelector( tokens )
- );
- }
- matchers.push( matcher );
- }
- }
-
- return elementMatcher( matchers );
-}
-
-function matcherFromGroupMatchers( elementMatchers, setMatchers ) {
- var bySet = setMatchers.length > 0,
- byElement = elementMatchers.length > 0,
- superMatcher = function( seed, context, xml, results, outermost ) {
- var elem, j, matcher,
- matchedCount = 0,
- i = "0",
- unmatched = seed && [],
- setMatched = [],
- contextBackup = outermostContext,
- // We must always have either seed elements or outermost context
- elems = seed || byElement && Expr.find["TAG"]( "*", outermost ),
- // Use integer dirruns iff this is the outermost matcher
- dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1),
- len = elems.length;
-
- if ( outermost ) {
- outermostContext = context !== document && context;
- }
-
- // Add elements passing elementMatchers directly to results
- // Keep `i` a string if there are no elements so `matchedCount` will be "00" below
- // Support: IE<9, Safari
- // Tolerate NodeList properties (IE: "length"; Safari: ) matching elements by id
- for ( ; i !== len && (elem = elems[i]) != null; i++ ) {
- if ( byElement && elem ) {
- j = 0;
- while ( (matcher = elementMatchers[j++]) ) {
- if ( matcher( elem, context, xml ) ) {
- results.push( elem );
- break;
- }
- }
- if ( outermost ) {
- dirruns = dirrunsUnique;
- }
- }
-
- // Track unmatched elements for set filters
- if ( bySet ) {
- // They will have gone through all possible matchers
- if ( (elem = !matcher && elem) ) {
- matchedCount--;
- }
-
- // Lengthen the array for every element, matched or not
- if ( seed ) {
- unmatched.push( elem );
- }
- }
- }
-
- // Apply set filters to unmatched elements
- matchedCount += i;
- if ( bySet && i !== matchedCount ) {
- j = 0;
- while ( (matcher = setMatchers[j++]) ) {
- matcher( unmatched, setMatched, context, xml );
- }
-
- if ( seed ) {
- // Reintegrate element matches to eliminate the need for sorting
- if ( matchedCount > 0 ) {
- while ( i-- ) {
- if ( !(unmatched[i] || setMatched[i]) ) {
- setMatched[i] = pop.call( results );
- }
- }
- }
-
- // Discard index placeholder values to get only actual matches
- setMatched = condense( setMatched );
- }
-
- // Add matches to results
- push.apply( results, setMatched );
-
- // Seedless set matches succeeding multiple successful matchers stipulate sorting
- if ( outermost && !seed && setMatched.length > 0 &&
- ( matchedCount + setMatchers.length ) > 1 ) {
-
- Sizzle.uniqueSort( results );
- }
- }
-
- // Override manipulation of globals by nested matchers
- if ( outermost ) {
- dirruns = dirrunsUnique;
- outermostContext = contextBackup;
- }
-
- return unmatched;
- };
-
- return bySet ?
- markFunction( superMatcher ) :
- superMatcher;
-}
-
-compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) {
- var i,
- setMatchers = [],
- elementMatchers = [],
- cached = compilerCache[ selector + " " ];
-
- if ( !cached ) {
- // Generate a function of recursive functions that can be used to check each element
- if ( !match ) {
- match = tokenize( selector );
- }
- i = match.length;
- while ( i-- ) {
- cached = matcherFromTokens( match[i] );
- if ( cached[ expando ] ) {
- setMatchers.push( cached );
- } else {
- elementMatchers.push( cached );
- }
- }
-
- // Cache the compiled function
- cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) );
-
- // Save selector and tokenization
- cached.selector = selector;
- }
- return cached;
-};
-
-/**
- * A low-level selection function that works with Sizzle's compiled
- * selector functions
- * @param {String|Function} selector A selector or a pre-compiled
- * selector function built with Sizzle.compile
- * @param {Element} context
- * @param {Array} [results]
- * @param {Array} [seed] A set of elements to match against
- */
-select = Sizzle.select = function( selector, context, results, seed ) {
- var i, tokens, token, type, find,
- compiled = typeof selector === "function" && selector,
- match = !seed && tokenize( (selector = compiled.selector || selector) );
-
- results = results || [];
-
- // Try to minimize operations if there is no seed and only one group
- if ( match.length === 1 ) {
-
- // Take a shortcut and set the context if the root selector is an ID
- tokens = match[0] = match[0].slice( 0 );
- if ( tokens.length > 2 && (token = tokens[0]).type === "ID" &&
- support.getById && context.nodeType === 9 && documentIsHTML &&
- Expr.relative[ tokens[1].type ] ) {
-
- context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0];
- if ( !context ) {
- return results;
-
- // Precompiled matchers will still verify ancestry, so step up a level
- } else if ( compiled ) {
- context = context.parentNode;
- }
-
- selector = selector.slice( tokens.shift().value.length );
- }
-
- // Fetch a seed set for right-to-left matching
- i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length;
- while ( i-- ) {
- token = tokens[i];
-
- // Abort if we hit a combinator
- if ( Expr.relative[ (type = token.type) ] ) {
- break;
- }
- if ( (find = Expr.find[ type ]) ) {
- // Search, expanding context for leading sibling combinators
- if ( (seed = find(
- token.matches[0].replace( runescape, funescape ),
- rsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context
- )) ) {
-
- // If seed is empty or no tokens remain, we can return early
- tokens.splice( i, 1 );
- selector = seed.length && toSelector( tokens );
- if ( !selector ) {
- push.apply( results, seed );
- return results;
- }
-
- break;
- }
- }
- }
- }
-
- // Compile and execute a filtering function if one is not provided
- // Provide `match` to avoid retokenization if we modified the selector above
- ( compiled || compile( selector, match ) )(
- seed,
- context,
- !documentIsHTML,
- results,
- rsibling.test( selector ) && testContext( context.parentNode ) || context
- );
- return results;
-};
-
-// One-time assignments
-
-// Sort stability
-support.sortStable = expando.split("").sort( sortOrder ).join("") === expando;
-
-// Support: Chrome<14
-// Always assume duplicates if they aren't passed to the comparison function
-support.detectDuplicates = !!hasDuplicate;
-
-// Initialize against the default document
-setDocument();
-
-// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27)
-// Detached nodes confoundingly follow *each other*
-support.sortDetached = assert(function( div1 ) {
- // Should return 1, but returns 4 (following)
- return div1.compareDocumentPosition( document.createElement("div") ) & 1;
-});
-
-// Support: IE<8
-// Prevent attribute/property "interpolation"
-// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx
-if ( !assert(function( div ) {
- div.innerHTML = "";
- return div.firstChild.getAttribute("href") === "#" ;
-}) ) {
- addHandle( "type|href|height|width", function( elem, name, isXML ) {
- if ( !isXML ) {
- return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 );
- }
- });
-}
-
-// Support: IE<9
-// Use defaultValue in place of getAttribute("value")
-if ( !support.attributes || !assert(function( div ) {
- div.innerHTML = "";
- div.firstChild.setAttribute( "value", "" );
- return div.firstChild.getAttribute( "value" ) === "";
-}) ) {
- addHandle( "value", function( elem, name, isXML ) {
- if ( !isXML && elem.nodeName.toLowerCase() === "input" ) {
- return elem.defaultValue;
- }
- });
-}
-
-// Support: IE<9
-// Use getAttributeNode to fetch booleans when getAttribute lies
-if ( !assert(function( div ) {
- return div.getAttribute("disabled") == null;
-}) ) {
- addHandle( booleans, function( elem, name, isXML ) {
- var val;
- if ( !isXML ) {
- return elem[ name ] === true ? name.toLowerCase() :
- (val = elem.getAttributeNode( name )) && val.specified ?
- val.value :
- null;
- }
- });
-}
-
-return Sizzle;
-
-})( window );
-
-
-
-jQuery.find = Sizzle;
-jQuery.expr = Sizzle.selectors;
-jQuery.expr[":"] = jQuery.expr.pseudos;
-jQuery.unique = Sizzle.uniqueSort;
-jQuery.text = Sizzle.getText;
-jQuery.isXMLDoc = Sizzle.isXML;
-jQuery.contains = Sizzle.contains;
-
-
-
-var rneedsContext = jQuery.expr.match.needsContext;
-
-var rsingleTag = (/^<(\w+)\s*\/?>(?:<\/\1>|)$/);
-
-
-
-var risSimple = /^.[^:#\[\.,]*$/;
-
-// Implement the identical functionality for filter and not
-function winnow( elements, qualifier, not ) {
- if ( jQuery.isFunction( qualifier ) ) {
- return jQuery.grep( elements, function( elem, i ) {
- /* jshint -W018 */
- return !!qualifier.call( elem, i, elem ) !== not;
- });
-
- }
-
- if ( qualifier.nodeType ) {
- return jQuery.grep( elements, function( elem ) {
- return ( elem === qualifier ) !== not;
- });
-
- }
-
- if ( typeof qualifier === "string" ) {
- if ( risSimple.test( qualifier ) ) {
- return jQuery.filter( qualifier, elements, not );
- }
-
- qualifier = jQuery.filter( qualifier, elements );
- }
-
- return jQuery.grep( elements, function( elem ) {
- return ( jQuery.inArray( elem, qualifier ) >= 0 ) !== not;
- });
-}
-
-jQuery.filter = function( expr, elems, not ) {
- var elem = elems[ 0 ];
-
- if ( not ) {
- expr = ":not(" + expr + ")";
- }
-
- return elems.length === 1 && elem.nodeType === 1 ?
- jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [] :
- jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) {
- return elem.nodeType === 1;
- }));
-};
-
-jQuery.fn.extend({
- find: function( selector ) {
- var i,
- ret = [],
- self = this,
- len = self.length;
-
- if ( typeof selector !== "string" ) {
- return this.pushStack( jQuery( selector ).filter(function() {
- for ( i = 0; i < len; i++ ) {
- if ( jQuery.contains( self[ i ], this ) ) {
- return true;
- }
- }
- }) );
- }
-
- for ( i = 0; i < len; i++ ) {
- jQuery.find( selector, self[ i ], ret );
- }
-
- // Needed because $( selector, context ) becomes $( context ).find( selector )
- ret = this.pushStack( len > 1 ? jQuery.unique( ret ) : ret );
- ret.selector = this.selector ? this.selector + " " + selector : selector;
- return ret;
- },
- filter: function( selector ) {
- return this.pushStack( winnow(this, selector || [], false) );
- },
- not: function( selector ) {
- return this.pushStack( winnow(this, selector || [], true) );
- },
- is: function( selector ) {
- return !!winnow(
- this,
-
- // If this is a positional/relative selector, check membership in the returned set
- // so $("p:first").is("p:last") won't return true for a doc with two "p".
- typeof selector === "string" && rneedsContext.test( selector ) ?
- jQuery( selector ) :
- selector || [],
- false
- ).length;
- }
-});
-
-
-// Initialize a jQuery object
-
-
-// A central reference to the root jQuery(document)
-var rootjQuery,
-
- // Use the correct document accordingly with window argument (sandbox)
- document = window.document,
-
- // A simple way to check for HTML strings
- // Prioritize #id over to avoid XSS via location.hash (#9521)
- // Strict HTML recognition (#11290: must start with <)
- rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,
-
- init = jQuery.fn.init = function( selector, context ) {
- var match, elem;
-
- // HANDLE: $(""), $(null), $(undefined), $(false)
- if ( !selector ) {
- return this;
- }
-
- // Handle HTML strings
- if ( typeof selector === "string" ) {
- if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) {
- // Assume that strings that start and end with <> are HTML and skip the regex check
- match = [ null, selector, null ];
-
- } else {
- match = rquickExpr.exec( selector );
- }
-
- // Match html or make sure no context is specified for #id
- if ( match && (match[1] || !context) ) {
-
- // HANDLE: $(html) -> $(array)
- if ( match[1] ) {
- context = context instanceof jQuery ? context[0] : context;
-
- // scripts is true for back-compat
- // Intentionally let the error be thrown if parseHTML is not present
- jQuery.merge( this, jQuery.parseHTML(
- match[1],
- context && context.nodeType ? context.ownerDocument || context : document,
- true
- ) );
-
- // HANDLE: $(html, props)
- if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) {
- for ( match in context ) {
- // Properties of context are called as methods if possible
- if ( jQuery.isFunction( this[ match ] ) ) {
- this[ match ]( context[ match ] );
-
- // ...and otherwise set as attributes
- } else {
- this.attr( match, context[ match ] );
- }
- }
- }
-
- return this;
-
- // HANDLE: $(#id)
- } else {
- elem = document.getElementById( match[2] );
-
- // Check parentNode to catch when Blackberry 4.6 returns
- // nodes that are no longer in the document #6963
- if ( elem && elem.parentNode ) {
- // Handle the case where IE and Opera return items
- // by name instead of ID
- if ( elem.id !== match[2] ) {
- return rootjQuery.find( selector );
- }
-
- // Otherwise, we inject the element directly into the jQuery object
- this.length = 1;
- this[0] = elem;
- }
-
- this.context = document;
- this.selector = selector;
- return this;
- }
-
- // HANDLE: $(expr, $(...))
- } else if ( !context || context.jquery ) {
- return ( context || rootjQuery ).find( selector );
-
- // HANDLE: $(expr, context)
- // (which is just equivalent to: $(context).find(expr)
- } else {
- return this.constructor( context ).find( selector );
- }
-
- // HANDLE: $(DOMElement)
- } else if ( selector.nodeType ) {
- this.context = this[0] = selector;
- this.length = 1;
- return this;
-
- // HANDLE: $(function)
- // Shortcut for document ready
- } else if ( jQuery.isFunction( selector ) ) {
- return typeof rootjQuery.ready !== "undefined" ?
- rootjQuery.ready( selector ) :
- // Execute immediately if ready is not present
- selector( jQuery );
- }
-
- if ( selector.selector !== undefined ) {
- this.selector = selector.selector;
- this.context = selector.context;
- }
-
- return jQuery.makeArray( selector, this );
- };
-
-// Give the init function the jQuery prototype for later instantiation
-init.prototype = jQuery.fn;
-
-// Initialize central reference
-rootjQuery = jQuery( document );
-
-
-var rparentsprev = /^(?:parents|prev(?:Until|All))/,
- // methods guaranteed to produce a unique set when starting from a unique set
- guaranteedUnique = {
- children: true,
- contents: true,
- next: true,
- prev: true
- };
-
-jQuery.extend({
- dir: function( elem, dir, until ) {
- var matched = [],
- cur = elem[ dir ];
-
- while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) {
- if ( cur.nodeType === 1 ) {
- matched.push( cur );
- }
- cur = cur[dir];
- }
- return matched;
- },
-
- sibling: function( n, elem ) {
- var r = [];
-
- for ( ; n; n = n.nextSibling ) {
- if ( n.nodeType === 1 && n !== elem ) {
- r.push( n );
- }
- }
-
- return r;
- }
-});
-
-jQuery.fn.extend({
- has: function( target ) {
- var i,
- targets = jQuery( target, this ),
- len = targets.length;
-
- return this.filter(function() {
- for ( i = 0; i < len; i++ ) {
- if ( jQuery.contains( this, targets[i] ) ) {
- return true;
- }
- }
- });
- },
-
- closest: function( selectors, context ) {
- var cur,
- i = 0,
- l = this.length,
- matched = [],
- pos = rneedsContext.test( selectors ) || typeof selectors !== "string" ?
- jQuery( selectors, context || this.context ) :
- 0;
-
- for ( ; i < l; i++ ) {
- for ( cur = this[i]; cur && cur !== context; cur = cur.parentNode ) {
- // Always skip document fragments
- if ( cur.nodeType < 11 && (pos ?
- pos.index(cur) > -1 :
-
- // Don't pass non-elements to Sizzle
- cur.nodeType === 1 &&
- jQuery.find.matchesSelector(cur, selectors)) ) {
-
- matched.push( cur );
- break;
- }
- }
- }
-
- return this.pushStack( matched.length > 1 ? jQuery.unique( matched ) : matched );
- },
-
- // Determine the position of an element within
- // the matched set of elements
- index: function( elem ) {
-
- // No argument, return index in parent
- if ( !elem ) {
- return ( this[0] && this[0].parentNode ) ? this.first().prevAll().length : -1;
- }
-
- // index in selector
- if ( typeof elem === "string" ) {
- return jQuery.inArray( this[0], jQuery( elem ) );
- }
-
- // Locate the position of the desired element
- return jQuery.inArray(
- // If it receives a jQuery object, the first element is used
- elem.jquery ? elem[0] : elem, this );
- },
-
- add: function( selector, context ) {
- return this.pushStack(
- jQuery.unique(
- jQuery.merge( this.get(), jQuery( selector, context ) )
- )
- );
- },
-
- addBack: function( selector ) {
- return this.add( selector == null ?
- this.prevObject : this.prevObject.filter(selector)
- );
- }
-});
-
-function sibling( cur, dir ) {
- do {
- cur = cur[ dir ];
- } while ( cur && cur.nodeType !== 1 );
-
- return cur;
-}
-
-jQuery.each({
- parent: function( elem ) {
- var parent = elem.parentNode;
- return parent && parent.nodeType !== 11 ? parent : null;
- },
- parents: function( elem ) {
- return jQuery.dir( elem, "parentNode" );
- },
- parentsUntil: function( elem, i, until ) {
- return jQuery.dir( elem, "parentNode", until );
- },
- next: function( elem ) {
- return sibling( elem, "nextSibling" );
- },
- prev: function( elem ) {
- return sibling( elem, "previousSibling" );
- },
- nextAll: function( elem ) {
- return jQuery.dir( elem, "nextSibling" );
- },
- prevAll: function( elem ) {
- return jQuery.dir( elem, "previousSibling" );
- },
- nextUntil: function( elem, i, until ) {
- return jQuery.dir( elem, "nextSibling", until );
- },
- prevUntil: function( elem, i, until ) {
- return jQuery.dir( elem, "previousSibling", until );
- },
- siblings: function( elem ) {
- return jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem );
- },
- children: function( elem ) {
- return jQuery.sibling( elem.firstChild );
- },
- contents: function( elem ) {
- return jQuery.nodeName( elem, "iframe" ) ?
- elem.contentDocument || elem.contentWindow.document :
- jQuery.merge( [], elem.childNodes );
- }
-}, function( name, fn ) {
- jQuery.fn[ name ] = function( until, selector ) {
- var ret = jQuery.map( this, fn, until );
-
- if ( name.slice( -5 ) !== "Until" ) {
- selector = until;
- }
-
- if ( selector && typeof selector === "string" ) {
- ret = jQuery.filter( selector, ret );
- }
-
- if ( this.length > 1 ) {
- // Remove duplicates
- if ( !guaranteedUnique[ name ] ) {
- ret = jQuery.unique( ret );
- }
-
- // Reverse order for parents* and prev-derivatives
- if ( rparentsprev.test( name ) ) {
- ret = ret.reverse();
- }
- }
-
- return this.pushStack( ret );
- };
-});
-var rnotwhite = (/\S+/g);
-
-
-
-// String to Object options format cache
-var optionsCache = {};
-
-// Convert String-formatted options into Object-formatted ones and store in cache
-function createOptions( options ) {
- var object = optionsCache[ options ] = {};
- jQuery.each( options.match( rnotwhite ) || [], function( _, flag ) {
- object[ flag ] = true;
- });
- return object;
-}
-
-/*
- * Create a callback list using the following parameters:
- *
- * options: an optional list of space-separated options that will change how
- * the callback list behaves or a more traditional option object
- *
- * By default a callback list will act like an event callback list and can be
- * "fired" multiple times.
- *
- * Possible options:
- *
- * once: will ensure the callback list can only be fired once (like a Deferred)
- *
- * memory: will keep track of previous values and will call any callback added
- * after the list has been fired right away with the latest "memorized"
- * values (like a Deferred)
- *
- * unique: will ensure a callback can only be added once (no duplicate in the list)
- *
- * stopOnFalse: interrupt callings when a callback returns false
- *
- */
-jQuery.Callbacks = function( options ) {
-
- // Convert options from String-formatted to Object-formatted if needed
- // (we check in cache first)
- options = typeof options === "string" ?
- ( optionsCache[ options ] || createOptions( options ) ) :
- jQuery.extend( {}, options );
-
- var // Flag to know if list is currently firing
- firing,
- // Last fire value (for non-forgettable lists)
- memory,
- // Flag to know if list was already fired
- fired,
- // End of the loop when firing
- firingLength,
- // Index of currently firing callback (modified by remove if needed)
- firingIndex,
- // First callback to fire (used internally by add and fireWith)
- firingStart,
- // Actual callback list
- list = [],
- // Stack of fire calls for repeatable lists
- stack = !options.once && [],
- // Fire callbacks
- fire = function( data ) {
- memory = options.memory && data;
- fired = true;
- firingIndex = firingStart || 0;
- firingStart = 0;
- firingLength = list.length;
- firing = true;
- for ( ; list && firingIndex < firingLength; firingIndex++ ) {
- if ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) {
- memory = false; // To prevent further calls using add
- break;
- }
- }
- firing = false;
- if ( list ) {
- if ( stack ) {
- if ( stack.length ) {
- fire( stack.shift() );
- }
- } else if ( memory ) {
- list = [];
- } else {
- self.disable();
- }
- }
- },
- // Actual Callbacks object
- self = {
- // Add a callback or a collection of callbacks to the list
- add: function() {
- if ( list ) {
- // First, we save the current length
- var start = list.length;
- (function add( args ) {
- jQuery.each( args, function( _, arg ) {
- var type = jQuery.type( arg );
- if ( type === "function" ) {
- if ( !options.unique || !self.has( arg ) ) {
- list.push( arg );
- }
- } else if ( arg && arg.length && type !== "string" ) {
- // Inspect recursively
- add( arg );
- }
- });
- })( arguments );
- // Do we need to add the callbacks to the
- // current firing batch?
- if ( firing ) {
- firingLength = list.length;
- // With memory, if we're not firing then
- // we should call right away
- } else if ( memory ) {
- firingStart = start;
- fire( memory );
- }
- }
- return this;
- },
- // Remove a callback from the list
- remove: function() {
- if ( list ) {
- jQuery.each( arguments, function( _, arg ) {
- var index;
- while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {
- list.splice( index, 1 );
- // Handle firing indexes
- if ( firing ) {
- if ( index <= firingLength ) {
- firingLength--;
- }
- if ( index <= firingIndex ) {
- firingIndex--;
- }
- }
- }
- });
- }
- return this;
- },
- // Check if a given callback is in the list.
- // If no argument is given, return whether or not list has callbacks attached.
- has: function( fn ) {
- return fn ? jQuery.inArray( fn, list ) > -1 : !!( list && list.length );
- },
- // Remove all callbacks from the list
- empty: function() {
- list = [];
- firingLength = 0;
- return this;
- },
- // Have the list do nothing anymore
- disable: function() {
- list = stack = memory = undefined;
- return this;
- },
- // Is it disabled?
- disabled: function() {
- return !list;
- },
- // Lock the list in its current state
- lock: function() {
- stack = undefined;
- if ( !memory ) {
- self.disable();
- }
- return this;
- },
- // Is it locked?
- locked: function() {
- return !stack;
- },
- // Call all callbacks with the given context and arguments
- fireWith: function( context, args ) {
- if ( list && ( !fired || stack ) ) {
- args = args || [];
- args = [ context, args.slice ? args.slice() : args ];
- if ( firing ) {
- stack.push( args );
- } else {
- fire( args );
- }
- }
- return this;
- },
- // Call all the callbacks with the given arguments
- fire: function() {
- self.fireWith( this, arguments );
- return this;
- },
- // To know if the callbacks have already been called at least once
- fired: function() {
- return !!fired;
- }
- };
-
- return self;
-};
-
-
-jQuery.extend({
-
- Deferred: function( func ) {
- var tuples = [
- // action, add listener, listener list, final state
- [ "resolve", "done", jQuery.Callbacks("once memory"), "resolved" ],
- [ "reject", "fail", jQuery.Callbacks("once memory"), "rejected" ],
- [ "notify", "progress", jQuery.Callbacks("memory") ]
- ],
- state = "pending",
- promise = {
- state: function() {
- return state;
- },
- always: function() {
- deferred.done( arguments ).fail( arguments );
- return this;
- },
- then: function( /* fnDone, fnFail, fnProgress */ ) {
- var fns = arguments;
- return jQuery.Deferred(function( newDefer ) {
- jQuery.each( tuples, function( i, tuple ) {
- var fn = jQuery.isFunction( fns[ i ] ) && fns[ i ];
- // deferred[ done | fail | progress ] for forwarding actions to newDefer
- deferred[ tuple[1] ](function() {
- var returned = fn && fn.apply( this, arguments );
- if ( returned && jQuery.isFunction( returned.promise ) ) {
- returned.promise()
- .done( newDefer.resolve )
- .fail( newDefer.reject )
- .progress( newDefer.notify );
- } else {
- newDefer[ tuple[ 0 ] + "With" ]( this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments );
- }
- });
- });
- fns = null;
- }).promise();
- },
- // Get a promise for this deferred
- // If obj is provided, the promise aspect is added to the object
- promise: function( obj ) {
- return obj != null ? jQuery.extend( obj, promise ) : promise;
- }
- },
- deferred = {};
-
- // Keep pipe for back-compat
- promise.pipe = promise.then;
-
- // Add list-specific methods
- jQuery.each( tuples, function( i, tuple ) {
- var list = tuple[ 2 ],
- stateString = tuple[ 3 ];
-
- // promise[ done | fail | progress ] = list.add
- promise[ tuple[1] ] = list.add;
-
- // Handle state
- if ( stateString ) {
- list.add(function() {
- // state = [ resolved | rejected ]
- state = stateString;
-
- // [ reject_list | resolve_list ].disable; progress_list.lock
- }, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock );
- }
-
- // deferred[ resolve | reject | notify ]
- deferred[ tuple[0] ] = function() {
- deferred[ tuple[0] + "With" ]( this === deferred ? promise : this, arguments );
- return this;
- };
- deferred[ tuple[0] + "With" ] = list.fireWith;
- });
-
- // Make the deferred a promise
- promise.promise( deferred );
-
- // Call given func if any
- if ( func ) {
- func.call( deferred, deferred );
- }
-
- // All done!
- return deferred;
- },
-
- // Deferred helper
- when: function( subordinate /* , ..., subordinateN */ ) {
- var i = 0,
- resolveValues = slice.call( arguments ),
- length = resolveValues.length,
-
- // the count of uncompleted subordinates
- remaining = length !== 1 || ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0,
-
- // the master Deferred. If resolveValues consist of only a single Deferred, just use that.
- deferred = remaining === 1 ? subordinate : jQuery.Deferred(),
-
- // Update function for both resolve and progress values
- updateFunc = function( i, contexts, values ) {
- return function( value ) {
- contexts[ i ] = this;
- values[ i ] = arguments.length > 1 ? slice.call( arguments ) : value;
- if ( values === progressValues ) {
- deferred.notifyWith( contexts, values );
-
- } else if ( !(--remaining) ) {
- deferred.resolveWith( contexts, values );
- }
- };
- },
-
- progressValues, progressContexts, resolveContexts;
-
- // add listeners to Deferred subordinates; treat others as resolved
- if ( length > 1 ) {
- progressValues = new Array( length );
- progressContexts = new Array( length );
- resolveContexts = new Array( length );
- for ( ; i < length; i++ ) {
- if ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) {
- resolveValues[ i ].promise()
- .done( updateFunc( i, resolveContexts, resolveValues ) )
- .fail( deferred.reject )
- .progress( updateFunc( i, progressContexts, progressValues ) );
- } else {
- --remaining;
- }
- }
- }
-
- // if we're not waiting on anything, resolve the master
- if ( !remaining ) {
- deferred.resolveWith( resolveContexts, resolveValues );
- }
-
- return deferred.promise();
- }
-});
-
-
-// The deferred used on DOM ready
-var readyList;
-
-jQuery.fn.ready = function( fn ) {
- // Add the callback
- jQuery.ready.promise().done( fn );
-
- return this;
-};
-
-jQuery.extend({
- // Is the DOM ready to be used? Set to true once it occurs.
- isReady: false,
-
- // A counter to track how many items to wait for before
- // the ready event fires. See #6781
- readyWait: 1,
-
- // Hold (or release) the ready event
- holdReady: function( hold ) {
- if ( hold ) {
- jQuery.readyWait++;
- } else {
- jQuery.ready( true );
- }
- },
-
- // Handle when the DOM is ready
- ready: function( wait ) {
-
- // Abort if there are pending holds or we're already ready
- if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {
- return;
- }
-
- // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
- if ( !document.body ) {
- return setTimeout( jQuery.ready );
- }
-
- // Remember that the DOM is ready
- jQuery.isReady = true;
-
- // If a normal DOM Ready event fired, decrement, and wait if need be
- if ( wait !== true && --jQuery.readyWait > 0 ) {
- return;
- }
-
- // If there are functions bound, to execute
- readyList.resolveWith( document, [ jQuery ] );
-
- // Trigger any bound ready events
- if ( jQuery.fn.triggerHandler ) {
- jQuery( document ).triggerHandler( "ready" );
- jQuery( document ).off( "ready" );
- }
- }
-});
-
-/**
- * Clean-up method for dom ready events
- */
-function detach() {
- if ( document.addEventListener ) {
- document.removeEventListener( "DOMContentLoaded", completed, false );
- window.removeEventListener( "load", completed, false );
-
- } else {
- document.detachEvent( "onreadystatechange", completed );
- window.detachEvent( "onload", completed );
- }
-}
-
-/**
- * The ready event handler and self cleanup method
- */
-function completed() {
- // readyState === "complete" is good enough for us to call the dom ready in oldIE
- if ( document.addEventListener || event.type === "load" || document.readyState === "complete" ) {
- detach();
- jQuery.ready();
- }
-}
-
-jQuery.ready.promise = function( obj ) {
- if ( !readyList ) {
-
- readyList = jQuery.Deferred();
-
- // Catch cases where $(document).ready() is called after the browser event has already occurred.
- // we once tried to use readyState "interactive" here, but it caused issues like the one
- // discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15
- if ( document.readyState === "complete" ) {
- // Handle it asynchronously to allow scripts the opportunity to delay ready
- setTimeout( jQuery.ready );
-
- // Standards-based browsers support DOMContentLoaded
- } else if ( document.addEventListener ) {
- // Use the handy event callback
- document.addEventListener( "DOMContentLoaded", completed, false );
-
- // A fallback to window.onload, that will always work
- window.addEventListener( "load", completed, false );
-
- // If IE event model is used
- } else {
- // Ensure firing before onload, maybe late but safe also for iframes
- document.attachEvent( "onreadystatechange", completed );
-
- // A fallback to window.onload, that will always work
- window.attachEvent( "onload", completed );
-
- // If IE and not a frame
- // continually check to see if the document is ready
- var top = false;
-
- try {
- top = window.frameElement == null && document.documentElement;
- } catch(e) {}
-
- if ( top && top.doScroll ) {
- (function doScrollCheck() {
- if ( !jQuery.isReady ) {
-
- try {
- // Use the trick by Diego Perini
- // http://javascript.nwbox.com/IEContentLoaded/
- top.doScroll("left");
- } catch(e) {
- return setTimeout( doScrollCheck, 50 );
- }
-
- // detach all dom ready events
- detach();
-
- // and execute any waiting functions
- jQuery.ready();
- }
- })();
- }
- }
- }
- return readyList.promise( obj );
-};
-
-
-var strundefined = typeof undefined;
-
-
-
-// Support: IE<9
-// Iteration over object's inherited properties before its own
-var i;
-for ( i in jQuery( support ) ) {
- break;
-}
-support.ownLast = i !== "0";
-
-// Note: most support tests are defined in their respective modules.
-// false until the test is run
-support.inlineBlockNeedsLayout = false;
-
-// Execute ASAP in case we need to set body.style.zoom
-jQuery(function() {
- // Minified: var a,b,c,d
- var val, div, body, container;
-
- body = document.getElementsByTagName( "body" )[ 0 ];
- if ( !body || !body.style ) {
- // Return for frameset docs that don't have a body
- return;
- }
-
- // Setup
- div = document.createElement( "div" );
- container = document.createElement( "div" );
- container.style.cssText = "position:absolute;border:0;width:0;height:0;top:0;left:-9999px";
- body.appendChild( container ).appendChild( div );
-
- if ( typeof div.style.zoom !== strundefined ) {
- // Support: IE<8
- // Check if natively block-level elements act like inline-block
- // elements when setting their display to 'inline' and giving
- // them layout
- div.style.cssText = "display:inline;margin:0;border:0;padding:1px;width:1px;zoom:1";
-
- support.inlineBlockNeedsLayout = val = div.offsetWidth === 3;
- if ( val ) {
- // Prevent IE 6 from affecting layout for positioned elements #11048
- // Prevent IE from shrinking the body in IE 7 mode #12869
- // Support: IE<8
- body.style.zoom = 1;
- }
- }
-
- body.removeChild( container );
-});
-
-
-
-
-(function() {
- var div = document.createElement( "div" );
-
- // Execute the test only if not already executed in another module.
- if (support.deleteExpando == null) {
- // Support: IE<9
- support.deleteExpando = true;
- try {
- delete div.test;
- } catch( e ) {
- support.deleteExpando = false;
- }
- }
-
- // Null elements to avoid leaks in IE.
- div = null;
-})();
-
-
-/**
- * Determines whether an object can have data
- */
-jQuery.acceptData = function( elem ) {
- var noData = jQuery.noData[ (elem.nodeName + " ").toLowerCase() ],
- nodeType = +elem.nodeType || 1;
-
- // Do not set data on non-element DOM nodes because it will not be cleared (#8335).
- return nodeType !== 1 && nodeType !== 9 ?
- false :
-
- // Nodes accept data unless otherwise specified; rejection can be conditional
- !noData || noData !== true && elem.getAttribute("classid") === noData;
-};
-
-
-var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,
- rmultiDash = /([A-Z])/g;
-
-function dataAttr( elem, key, data ) {
- // If nothing was found internally, try to fetch any
- // data from the HTML5 data-* attribute
- if ( data === undefined && elem.nodeType === 1 ) {
-
- var name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase();
-
- data = elem.getAttribute( name );
-
- if ( typeof data === "string" ) {
- try {
- data = data === "true" ? true :
- data === "false" ? false :
- data === "null" ? null :
- // Only convert to a number if it doesn't change the string
- +data + "" === data ? +data :
- rbrace.test( data ) ? jQuery.parseJSON( data ) :
- data;
- } catch( e ) {}
-
- // Make sure we set the data so it isn't changed later
- jQuery.data( elem, key, data );
-
- } else {
- data = undefined;
- }
- }
-
- return data;
-}
-
-// checks a cache object for emptiness
-function isEmptyDataObject( obj ) {
- var name;
- for ( name in obj ) {
-
- // if the public data object is empty, the private is still empty
- if ( name === "data" && jQuery.isEmptyObject( obj[name] ) ) {
- continue;
- }
- if ( name !== "toJSON" ) {
- return false;
- }
- }
-
- return true;
-}
-
-function internalData( elem, name, data, pvt /* Internal Use Only */ ) {
- if ( !jQuery.acceptData( elem ) ) {
- return;
- }
-
- var ret, thisCache,
- internalKey = jQuery.expando,
-
- // We have to handle DOM nodes and JS objects differently because IE6-7
- // can't GC object references properly across the DOM-JS boundary
- isNode = elem.nodeType,
-
- // Only DOM nodes need the global jQuery cache; JS object data is
- // attached directly to the object so GC can occur automatically
- cache = isNode ? jQuery.cache : elem,
-
- // Only defining an ID for JS objects if its cache already exists allows
- // the code to shortcut on the same path as a DOM node with no cache
- id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey;
-
- // Avoid doing any more work than we need to when trying to get data on an
- // object that has no data at all
- if ( (!id || !cache[id] || (!pvt && !cache[id].data)) && data === undefined && typeof name === "string" ) {
- return;
- }
-
- if ( !id ) {
- // Only DOM nodes need a new unique ID for each element since their data
- // ends up in the global cache
- if ( isNode ) {
- id = elem[ internalKey ] = deletedIds.pop() || jQuery.guid++;
- } else {
- id = internalKey;
- }
- }
-
- if ( !cache[ id ] ) {
- // Avoid exposing jQuery metadata on plain JS objects when the object
- // is serialized using JSON.stringify
- cache[ id ] = isNode ? {} : { toJSON: jQuery.noop };
- }
-
- // An object can be passed to jQuery.data instead of a key/value pair; this gets
- // shallow copied over onto the existing cache
- if ( typeof name === "object" || typeof name === "function" ) {
- if ( pvt ) {
- cache[ id ] = jQuery.extend( cache[ id ], name );
- } else {
- cache[ id ].data = jQuery.extend( cache[ id ].data, name );
- }
- }
-
- thisCache = cache[ id ];
-
- // jQuery data() is stored in a separate object inside the object's internal data
- // cache in order to avoid key collisions between internal data and user-defined
- // data.
- if ( !pvt ) {
- if ( !thisCache.data ) {
- thisCache.data = {};
- }
-
- thisCache = thisCache.data;
- }
-
- if ( data !== undefined ) {
- thisCache[ jQuery.camelCase( name ) ] = data;
- }
-
- // Check for both converted-to-camel and non-converted data property names
- // If a data property was specified
- if ( typeof name === "string" ) {
-
- // First Try to find as-is property data
- ret = thisCache[ name ];
-
- // Test for null|undefined property data
- if ( ret == null ) {
-
- // Try to find the camelCased property
- ret = thisCache[ jQuery.camelCase( name ) ];
- }
- } else {
- ret = thisCache;
- }
-
- return ret;
-}
-
-function internalRemoveData( elem, name, pvt ) {
- if ( !jQuery.acceptData( elem ) ) {
- return;
- }
-
- var thisCache, i,
- isNode = elem.nodeType,
-
- // See jQuery.data for more information
- cache = isNode ? jQuery.cache : elem,
- id = isNode ? elem[ jQuery.expando ] : jQuery.expando;
-
- // If there is already no cache entry for this object, there is no
- // purpose in continuing
- if ( !cache[ id ] ) {
- return;
- }
-
- if ( name ) {
-
- thisCache = pvt ? cache[ id ] : cache[ id ].data;
-
- if ( thisCache ) {
-
- // Support array or space separated string names for data keys
- if ( !jQuery.isArray( name ) ) {
-
- // try the string as a key before any manipulation
- if ( name in thisCache ) {
- name = [ name ];
- } else {
-
- // split the camel cased version by spaces unless a key with the spaces exists
- name = jQuery.camelCase( name );
- if ( name in thisCache ) {
- name = [ name ];
- } else {
- name = name.split(" ");
- }
- }
- } else {
- // If "name" is an array of keys...
- // When data is initially created, via ("key", "val") signature,
- // keys will be converted to camelCase.
- // Since there is no way to tell _how_ a key was added, remove
- // both plain key and camelCase key. #12786
- // This will only penalize the array argument path.
- name = name.concat( jQuery.map( name, jQuery.camelCase ) );
- }
-
- i = name.length;
- while ( i-- ) {
- delete thisCache[ name[i] ];
- }
-
- // If there is no data left in the cache, we want to continue
- // and let the cache object itself get destroyed
- if ( pvt ? !isEmptyDataObject(thisCache) : !jQuery.isEmptyObject(thisCache) ) {
- return;
- }
- }
- }
-
- // See jQuery.data for more information
- if ( !pvt ) {
- delete cache[ id ].data;
-
- // Don't destroy the parent cache unless the internal data object
- // had been the only thing left in it
- if ( !isEmptyDataObject( cache[ id ] ) ) {
- return;
- }
- }
-
- // Destroy the cache
- if ( isNode ) {
- jQuery.cleanData( [ elem ], true );
-
- // Use delete when supported for expandos or `cache` is not a window per isWindow (#10080)
- /* jshint eqeqeq: false */
- } else if ( support.deleteExpando || cache != cache.window ) {
- /* jshint eqeqeq: true */
- delete cache[ id ];
-
- // When all else fails, null
- } else {
- cache[ id ] = null;
- }
-}
-
-jQuery.extend({
- cache: {},
-
- // The following elements (space-suffixed to avoid Object.prototype collisions)
- // throw uncatchable exceptions if you attempt to set expando properties
- noData: {
- "applet ": true,
- "embed ": true,
- // ...but Flash objects (which have this classid) *can* handle expandos
- "object ": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
- },
-
- hasData: function( elem ) {
- elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ];
- return !!elem && !isEmptyDataObject( elem );
- },
-
- data: function( elem, name, data ) {
- return internalData( elem, name, data );
- },
-
- removeData: function( elem, name ) {
- return internalRemoveData( elem, name );
- },
-
- // For internal use only.
- _data: function( elem, name, data ) {
- return internalData( elem, name, data, true );
- },
-
- _removeData: function( elem, name ) {
- return internalRemoveData( elem, name, true );
- }
-});
-
-jQuery.fn.extend({
- data: function( key, value ) {
- var i, name, data,
- elem = this[0],
- attrs = elem && elem.attributes;
-
- // Special expections of .data basically thwart jQuery.access,
- // so implement the relevant behavior ourselves
-
- // Gets all values
- if ( key === undefined ) {
- if ( this.length ) {
- data = jQuery.data( elem );
-
- if ( elem.nodeType === 1 && !jQuery._data( elem, "parsedAttrs" ) ) {
- i = attrs.length;
- while ( i-- ) {
-
- // Support: IE11+
- // The attrs elements can be null (#14894)
- if ( attrs[ i ] ) {
- name = attrs[ i ].name;
- if ( name.indexOf( "data-" ) === 0 ) {
- name = jQuery.camelCase( name.slice(5) );
- dataAttr( elem, name, data[ name ] );
- }
- }
- }
- jQuery._data( elem, "parsedAttrs", true );
- }
- }
-
- return data;
- }
-
- // Sets multiple values
- if ( typeof key === "object" ) {
- return this.each(function() {
- jQuery.data( this, key );
- });
- }
-
- return arguments.length > 1 ?
-
- // Sets one value
- this.each(function() {
- jQuery.data( this, key, value );
- }) :
-
- // Gets one value
- // Try to fetch any internally stored data first
- elem ? dataAttr( elem, key, jQuery.data( elem, key ) ) : undefined;
- },
-
- removeData: function( key ) {
- return this.each(function() {
- jQuery.removeData( this, key );
- });
- }
-});
-
-
-jQuery.extend({
- queue: function( elem, type, data ) {
- var queue;
-
- if ( elem ) {
- type = ( type || "fx" ) + "queue";
- queue = jQuery._data( elem, type );
-
- // Speed up dequeue by getting out quickly if this is just a lookup
- if ( data ) {
- if ( !queue || jQuery.isArray(data) ) {
- queue = jQuery._data( elem, type, jQuery.makeArray(data) );
- } else {
- queue.push( data );
- }
- }
- return queue || [];
- }
- },
-
- dequeue: function( elem, type ) {
- type = type || "fx";
-
- var queue = jQuery.queue( elem, type ),
- startLength = queue.length,
- fn = queue.shift(),
- hooks = jQuery._queueHooks( elem, type ),
- next = function() {
- jQuery.dequeue( elem, type );
- };
-
- // If the fx queue is dequeued, always remove the progress sentinel
- if ( fn === "inprogress" ) {
- fn = queue.shift();
- startLength--;
- }
-
- if ( fn ) {
-
- // Add a progress sentinel to prevent the fx queue from being
- // automatically dequeued
- if ( type === "fx" ) {
- queue.unshift( "inprogress" );
- }
-
- // clear up the last queue stop function
- delete hooks.stop;
- fn.call( elem, next, hooks );
- }
-
- if ( !startLength && hooks ) {
- hooks.empty.fire();
- }
- },
-
- // not intended for public consumption - generates a queueHooks object, or returns the current one
- _queueHooks: function( elem, type ) {
- var key = type + "queueHooks";
- return jQuery._data( elem, key ) || jQuery._data( elem, key, {
- empty: jQuery.Callbacks("once memory").add(function() {
- jQuery._removeData( elem, type + "queue" );
- jQuery._removeData( elem, key );
- })
- });
- }
-});
-
-jQuery.fn.extend({
- queue: function( type, data ) {
- var setter = 2;
-
- if ( typeof type !== "string" ) {
- data = type;
- type = "fx";
- setter--;
- }
-
- if ( arguments.length < setter ) {
- return jQuery.queue( this[0], type );
- }
-
- return data === undefined ?
- this :
- this.each(function() {
- var queue = jQuery.queue( this, type, data );
-
- // ensure a hooks for this queue
- jQuery._queueHooks( this, type );
-
- if ( type === "fx" && queue[0] !== "inprogress" ) {
- jQuery.dequeue( this, type );
- }
- });
- },
- dequeue: function( type ) {
- return this.each(function() {
- jQuery.dequeue( this, type );
- });
- },
- clearQueue: function( type ) {
- return this.queue( type || "fx", [] );
- },
- // Get a promise resolved when queues of a certain type
- // are emptied (fx is the type by default)
- promise: function( type, obj ) {
- var tmp,
- count = 1,
- defer = jQuery.Deferred(),
- elements = this,
- i = this.length,
- resolve = function() {
- if ( !( --count ) ) {
- defer.resolveWith( elements, [ elements ] );
- }
- };
-
- if ( typeof type !== "string" ) {
- obj = type;
- type = undefined;
- }
- type = type || "fx";
-
- while ( i-- ) {
- tmp = jQuery._data( elements[ i ], type + "queueHooks" );
- if ( tmp && tmp.empty ) {
- count++;
- tmp.empty.add( resolve );
- }
- }
- resolve();
- return defer.promise( obj );
- }
-});
-var pnum = (/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/).source;
-
-var cssExpand = [ "Top", "Right", "Bottom", "Left" ];
-
-var isHidden = function( elem, el ) {
- // isHidden might be called from jQuery#filter function;
- // in that case, element will be second argument
- elem = el || elem;
- return jQuery.css( elem, "display" ) === "none" || !jQuery.contains( elem.ownerDocument, elem );
- };
-
-
-
-// Multifunctional method to get and set values of a collection
-// The value/s can optionally be executed if it's a function
-var access = jQuery.access = function( elems, fn, key, value, chainable, emptyGet, raw ) {
- var i = 0,
- length = elems.length,
- bulk = key == null;
-
- // Sets many values
- if ( jQuery.type( key ) === "object" ) {
- chainable = true;
- for ( i in key ) {
- jQuery.access( elems, fn, i, key[i], true, emptyGet, raw );
- }
-
- // Sets one value
- } else if ( value !== undefined ) {
- chainable = true;
-
- if ( !jQuery.isFunction( value ) ) {
- raw = true;
- }
-
- if ( bulk ) {
- // Bulk operations run against the entire set
- if ( raw ) {
- fn.call( elems, value );
- fn = null;
-
- // ...except when executing function values
- } else {
- bulk = fn;
- fn = function( elem, key, value ) {
- return bulk.call( jQuery( elem ), value );
- };
- }
- }
-
- if ( fn ) {
- for ( ; i < length; i++ ) {
- fn( elems[i], key, raw ? value : value.call( elems[i], i, fn( elems[i], key ) ) );
- }
- }
- }
-
- return chainable ?
- elems :
-
- // Gets
- bulk ?
- fn.call( elems ) :
- length ? fn( elems[0], key ) : emptyGet;
-};
-var rcheckableType = (/^(?:checkbox|radio)$/i);
-
-
-
-(function() {
- // Minified: var a,b,c
- var input = document.createElement( "input" ),
- div = document.createElement( "div" ),
- fragment = document.createDocumentFragment();
-
- // Setup
- div.innerHTML = "
a";
-
- // IE strips leading whitespace when .innerHTML is used
- support.leadingWhitespace = div.firstChild.nodeType === 3;
-
- // Make sure that tbody elements aren't automatically inserted
- // IE will insert them into empty tables
- support.tbody = !div.getElementsByTagName( "tbody" ).length;
-
- // Make sure that link elements get serialized correctly by innerHTML
- // This requires a wrapper element in IE
- support.htmlSerialize = !!div.getElementsByTagName( "link" ).length;
-
- // Makes sure cloning an html5 element does not cause problems
- // Where outerHTML is undefined, this still works
- support.html5Clone =
- document.createElement( "nav" ).cloneNode( true ).outerHTML !== "<:nav>";
-
- // Check if a disconnected checkbox will retain its checked
- // value of true after appended to the DOM (IE6/7)
- input.type = "checkbox";
- input.checked = true;
- fragment.appendChild( input );
- support.appendChecked = input.checked;
-
- // Make sure textarea (and checkbox) defaultValue is properly cloned
- // Support: IE6-IE11+
- div.innerHTML = "";
- support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue;
-
- // #11217 - WebKit loses check when the name is after the checked attribute
- fragment.appendChild( div );
- div.innerHTML = "";
-
- // Support: Safari 5.1, iOS 5.1, Android 4.x, Android 2.3
- // old WebKit doesn't clone checked state correctly in fragments
- support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked;
-
- // Support: IE<9
- // Opera does not clone events (and typeof div.attachEvent === undefined).
- // IE9-10 clones events bound via attachEvent, but they don't trigger with .click()
- support.noCloneEvent = true;
- if ( div.attachEvent ) {
- div.attachEvent( "onclick", function() {
- support.noCloneEvent = false;
- });
-
- div.cloneNode( true ).click();
- }
-
- // Execute the test only if not already executed in another module.
- if (support.deleteExpando == null) {
- // Support: IE<9
- support.deleteExpando = true;
- try {
- delete div.test;
- } catch( e ) {
- support.deleteExpando = false;
- }
- }
-})();
-
-
-(function() {
- var i, eventName,
- div = document.createElement( "div" );
-
- // Support: IE<9 (lack submit/change bubble), Firefox 23+ (lack focusin event)
- for ( i in { submit: true, change: true, focusin: true }) {
- eventName = "on" + i;
-
- if ( !(support[ i + "Bubbles" ] = eventName in window) ) {
- // Beware of CSP restrictions (https://developer.mozilla.org/en/Security/CSP)
- div.setAttribute( eventName, "t" );
- support[ i + "Bubbles" ] = div.attributes[ eventName ].expando === false;
- }
- }
-
- // Null elements to avoid leaks in IE.
- div = null;
-})();
-
-
-var rformElems = /^(?:input|select|textarea)$/i,
- rkeyEvent = /^key/,
- rmouseEvent = /^(?:mouse|pointer|contextmenu)|click/,
- rfocusMorph = /^(?:focusinfocus|focusoutblur)$/,
- rtypenamespace = /^([^.]*)(?:\.(.+)|)$/;
-
-function returnTrue() {
- return true;
-}
-
-function returnFalse() {
- return false;
-}
-
-function safeActiveElement() {
- try {
- return document.activeElement;
- } catch ( err ) { }
-}
-
-/*
- * Helper functions for managing events -- not part of the public interface.
- * Props to Dean Edwards' addEvent library for many of the ideas.
- */
-jQuery.event = {
-
- global: {},
-
- add: function( elem, types, handler, data, selector ) {
- var tmp, events, t, handleObjIn,
- special, eventHandle, handleObj,
- handlers, type, namespaces, origType,
- elemData = jQuery._data( elem );
-
- // Don't attach events to noData or text/comment nodes (but allow plain objects)
- if ( !elemData ) {
- return;
- }
-
- // Caller can pass in an object of custom data in lieu of the handler
- if ( handler.handler ) {
- handleObjIn = handler;
- handler = handleObjIn.handler;
- selector = handleObjIn.selector;
- }
-
- // Make sure that the handler has a unique ID, used to find/remove it later
- if ( !handler.guid ) {
- handler.guid = jQuery.guid++;
- }
-
- // Init the element's event structure and main handler, if this is the first
- if ( !(events = elemData.events) ) {
- events = elemData.events = {};
- }
- if ( !(eventHandle = elemData.handle) ) {
- eventHandle = elemData.handle = function( e ) {
- // Discard the second event of a jQuery.event.trigger() and
- // when an event is called after a page has unloaded
- return typeof jQuery !== strundefined && (!e || jQuery.event.triggered !== e.type) ?
- jQuery.event.dispatch.apply( eventHandle.elem, arguments ) :
- undefined;
- };
- // Add elem as a property of the handle fn to prevent a memory leak with IE non-native events
- eventHandle.elem = elem;
- }
-
- // Handle multiple events separated by a space
- types = ( types || "" ).match( rnotwhite ) || [ "" ];
- t = types.length;
- while ( t-- ) {
- tmp = rtypenamespace.exec( types[t] ) || [];
- type = origType = tmp[1];
- namespaces = ( tmp[2] || "" ).split( "." ).sort();
-
- // There *must* be a type, no attaching namespace-only handlers
- if ( !type ) {
- continue;
- }
-
- // If event changes its type, use the special event handlers for the changed type
- special = jQuery.event.special[ type ] || {};
-
- // If selector defined, determine special event api type, otherwise given type
- type = ( selector ? special.delegateType : special.bindType ) || type;
-
- // Update special based on newly reset type
- special = jQuery.event.special[ type ] || {};
-
- // handleObj is passed to all event handlers
- handleObj = jQuery.extend({
- type: type,
- origType: origType,
- data: data,
- handler: handler,
- guid: handler.guid,
- selector: selector,
- needsContext: selector && jQuery.expr.match.needsContext.test( selector ),
- namespace: namespaces.join(".")
- }, handleObjIn );
-
- // Init the event handler queue if we're the first
- if ( !(handlers = events[ type ]) ) {
- handlers = events[ type ] = [];
- handlers.delegateCount = 0;
-
- // Only use addEventListener/attachEvent if the special events handler returns false
- if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
- // Bind the global event handler to the element
- if ( elem.addEventListener ) {
- elem.addEventListener( type, eventHandle, false );
-
- } else if ( elem.attachEvent ) {
- elem.attachEvent( "on" + type, eventHandle );
- }
- }
- }
-
- if ( special.add ) {
- special.add.call( elem, handleObj );
-
- if ( !handleObj.handler.guid ) {
- handleObj.handler.guid = handler.guid;
- }
- }
-
- // Add to the element's handler list, delegates in front
- if ( selector ) {
- handlers.splice( handlers.delegateCount++, 0, handleObj );
- } else {
- handlers.push( handleObj );
- }
-
- // Keep track of which events have ever been used, for event optimization
- jQuery.event.global[ type ] = true;
- }
-
- // Nullify elem to prevent memory leaks in IE
- elem = null;
- },
-
- // Detach an event or set of events from an element
- remove: function( elem, types, handler, selector, mappedTypes ) {
- var j, handleObj, tmp,
- origCount, t, events,
- special, handlers, type,
- namespaces, origType,
- elemData = jQuery.hasData( elem ) && jQuery._data( elem );
-
- if ( !elemData || !(events = elemData.events) ) {
- return;
- }
-
- // Once for each type.namespace in types; type may be omitted
- types = ( types || "" ).match( rnotwhite ) || [ "" ];
- t = types.length;
- while ( t-- ) {
- tmp = rtypenamespace.exec( types[t] ) || [];
- type = origType = tmp[1];
- namespaces = ( tmp[2] || "" ).split( "." ).sort();
-
- // Unbind all events (on this namespace, if provided) for the element
- if ( !type ) {
- for ( type in events ) {
- jQuery.event.remove( elem, type + types[ t ], handler, selector, true );
- }
- continue;
- }
-
- special = jQuery.event.special[ type ] || {};
- type = ( selector ? special.delegateType : special.bindType ) || type;
- handlers = events[ type ] || [];
- tmp = tmp[2] && new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" );
-
- // Remove matching events
- origCount = j = handlers.length;
- while ( j-- ) {
- handleObj = handlers[ j ];
-
- if ( ( mappedTypes || origType === handleObj.origType ) &&
- ( !handler || handler.guid === handleObj.guid ) &&
- ( !tmp || tmp.test( handleObj.namespace ) ) &&
- ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) {
- handlers.splice( j, 1 );
-
- if ( handleObj.selector ) {
- handlers.delegateCount--;
- }
- if ( special.remove ) {
- special.remove.call( elem, handleObj );
- }
- }
- }
-
- // Remove generic event handler if we removed something and no more handlers exist
- // (avoids potential for endless recursion during removal of special event handlers)
- if ( origCount && !handlers.length ) {
- if ( !special.teardown || special.teardown.call( elem, namespaces, elemData.handle ) === false ) {
- jQuery.removeEvent( elem, type, elemData.handle );
- }
-
- delete events[ type ];
- }
- }
-
- // Remove the expando if it's no longer used
- if ( jQuery.isEmptyObject( events ) ) {
- delete elemData.handle;
-
- // removeData also checks for emptiness and clears the expando if empty
- // so use it instead of delete
- jQuery._removeData( elem, "events" );
- }
- },
-
- trigger: function( event, data, elem, onlyHandlers ) {
- var handle, ontype, cur,
- bubbleType, special, tmp, i,
- eventPath = [ elem || document ],
- type = hasOwn.call( event, "type" ) ? event.type : event,
- namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split(".") : [];
-
- cur = tmp = elem = elem || document;
-
- // Don't do events on text and comment nodes
- if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
- return;
- }
-
- // focus/blur morphs to focusin/out; ensure we're not firing them right now
- if ( rfocusMorph.test( type + jQuery.event.triggered ) ) {
- return;
- }
-
- if ( type.indexOf(".") >= 0 ) {
- // Namespaced trigger; create a regexp to match event type in handle()
- namespaces = type.split(".");
- type = namespaces.shift();
- namespaces.sort();
- }
- ontype = type.indexOf(":") < 0 && "on" + type;
-
- // Caller can pass in a jQuery.Event object, Object, or just an event type string
- event = event[ jQuery.expando ] ?
- event :
- new jQuery.Event( type, typeof event === "object" && event );
-
- // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true)
- event.isTrigger = onlyHandlers ? 2 : 3;
- event.namespace = namespaces.join(".");
- event.namespace_re = event.namespace ?
- new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ) :
- null;
-
- // Clean up the event in case it is being reused
- event.result = undefined;
- if ( !event.target ) {
- event.target = elem;
- }
-
- // Clone any incoming data and prepend the event, creating the handler arg list
- data = data == null ?
- [ event ] :
- jQuery.makeArray( data, [ event ] );
-
- // Allow special events to draw outside the lines
- special = jQuery.event.special[ type ] || {};
- if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) {
- return;
- }
-
- // Determine event propagation path in advance, per W3C events spec (#9951)
- // Bubble up to document, then to window; watch for a global ownerDocument var (#9724)
- if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {
-
- bubbleType = special.delegateType || type;
- if ( !rfocusMorph.test( bubbleType + type ) ) {
- cur = cur.parentNode;
- }
- for ( ; cur; cur = cur.parentNode ) {
- eventPath.push( cur );
- tmp = cur;
- }
-
- // Only add window if we got to document (e.g., not plain obj or detached DOM)
- if ( tmp === (elem.ownerDocument || document) ) {
- eventPath.push( tmp.defaultView || tmp.parentWindow || window );
- }
- }
-
- // Fire handlers on the event path
- i = 0;
- while ( (cur = eventPath[i++]) && !event.isPropagationStopped() ) {
-
- event.type = i > 1 ?
- bubbleType :
- special.bindType || type;
-
- // jQuery handler
- handle = ( jQuery._data( cur, "events" ) || {} )[ event.type ] && jQuery._data( cur, "handle" );
- if ( handle ) {
- handle.apply( cur, data );
- }
-
- // Native handler
- handle = ontype && cur[ ontype ];
- if ( handle && handle.apply && jQuery.acceptData( cur ) ) {
- event.result = handle.apply( cur, data );
- if ( event.result === false ) {
- event.preventDefault();
- }
- }
- }
- event.type = type;
-
- // If nobody prevented the default action, do it now
- if ( !onlyHandlers && !event.isDefaultPrevented() ) {
-
- if ( (!special._default || special._default.apply( eventPath.pop(), data ) === false) &&
- jQuery.acceptData( elem ) ) {
-
- // Call a native DOM method on the target with the same name name as the event.
- // Can't use an .isFunction() check here because IE6/7 fails that test.
- // Don't do default actions on window, that's where global variables be (#6170)
- if ( ontype && elem[ type ] && !jQuery.isWindow( elem ) ) {
-
- // Don't re-trigger an onFOO event when we call its FOO() method
- tmp = elem[ ontype ];
-
- if ( tmp ) {
- elem[ ontype ] = null;
- }
-
- // Prevent re-triggering of the same event, since we already bubbled it above
- jQuery.event.triggered = type;
- try {
- elem[ type ]();
- } catch ( e ) {
- // IE<9 dies on focus/blur to hidden element (#1486,#12518)
- // only reproducible on winXP IE8 native, not IE9 in IE8 mode
- }
- jQuery.event.triggered = undefined;
-
- if ( tmp ) {
- elem[ ontype ] = tmp;
- }
- }
- }
- }
-
- return event.result;
- },
-
- dispatch: function( event ) {
-
- // Make a writable jQuery.Event from the native event object
- event = jQuery.event.fix( event );
-
- var i, ret, handleObj, matched, j,
- handlerQueue = [],
- args = slice.call( arguments ),
- handlers = ( jQuery._data( this, "events" ) || {} )[ event.type ] || [],
- special = jQuery.event.special[ event.type ] || {};
-
- // Use the fix-ed jQuery.Event rather than the (read-only) native event
- args[0] = event;
- event.delegateTarget = this;
-
- // Call the preDispatch hook for the mapped type, and let it bail if desired
- if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {
- return;
- }
-
- // Determine handlers
- handlerQueue = jQuery.event.handlers.call( this, event, handlers );
-
- // Run delegates first; they may want to stop propagation beneath us
- i = 0;
- while ( (matched = handlerQueue[ i++ ]) && !event.isPropagationStopped() ) {
- event.currentTarget = matched.elem;
-
- j = 0;
- while ( (handleObj = matched.handlers[ j++ ]) && !event.isImmediatePropagationStopped() ) {
-
- // Triggered event must either 1) have no namespace, or
- // 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace).
- if ( !event.namespace_re || event.namespace_re.test( handleObj.namespace ) ) {
-
- event.handleObj = handleObj;
- event.data = handleObj.data;
-
- ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler )
- .apply( matched.elem, args );
-
- if ( ret !== undefined ) {
- if ( (event.result = ret) === false ) {
- event.preventDefault();
- event.stopPropagation();
- }
- }
- }
- }
- }
-
- // Call the postDispatch hook for the mapped type
- if ( special.postDispatch ) {
- special.postDispatch.call( this, event );
- }
-
- return event.result;
- },
-
- handlers: function( event, handlers ) {
- var sel, handleObj, matches, i,
- handlerQueue = [],
- delegateCount = handlers.delegateCount,
- cur = event.target;
-
- // Find delegate handlers
- // Black-hole SVG