Update gitignore and remove unnecessary files

This commit is contained in:
Joey Yakimowich-Payne 2025-08-13 13:09:59 -06:00
commit f5e4df10e4
29 changed files with 3 additions and 9795 deletions

4
.gitignore vendored
View file

@ -1 +1,3 @@
node_modules/
node_modules/
.kiro/
.vscode/

View file

@ -1,165 +0,0 @@
# Design Document
## Overview
The copy to clipboard toggle feature will be implemented as an additional setting in the extension popup, similar to the existing background color selector. The feature will use the modern Clipboard API with appropriate fallbacks for older browsers. The implementation will integrate seamlessly with the existing screenshot capture workflow, adding clipboard functionality without disrupting the current download behavior.
## Architecture
The feature will be implemented across three main components:
1. **Popup UI Enhancement**: Add toggle control and persistence logic
2. **Content Script Integration**: Modify screenshot capture to include clipboard operations
3. **Storage Management**: Extend existing preference storage system
The clipboard functionality will be implemented as an optional enhancement to the existing screenshot workflow, ensuring backward compatibility and graceful degradation.
## Components and Interfaces
### Popup Interface (`popup.html` & `popup.js`)
**New UI Elements:**
- Toggle switch control for "Copy to Clipboard" option
- Positioned between background selector and start button
- Consistent styling with existing controls
**Storage Integration:**
- Extend existing `chrome.storage.sync` usage to include `copyToClipboard` preference
- Default value: `true` (enabled by default for better user experience)
- Load and save preferences alongside existing background preference
**Message Passing:**
- Include `copyToClipboard` setting in the `startSelector` message to content script
- No changes needed to existing message structure, just additional property
### Content Script Enhancement (`content.js`)
**ScreenshotSelector Class Modifications:**
- Add `copyToClipboard` property to constructor
- Modify `init()` method to accept and store clipboard preference
- Enhance `captureElement()` method to include clipboard operations
**Clipboard Implementation:**
```javascript
async copyCanvasToClipboard(canvas) {
try {
// Convert canvas to blob
const blob = await new Promise(resolve =>
canvas.toBlob(resolve, 'image/png')
);
// Use Clipboard API
await navigator.clipboard.write([
new ClipboardItem({ 'image/png': blob })
]);
return { success: true };
} catch (error) {
return { success: false, error: error.message };
}
}
```
**Error Handling:**
- Graceful fallback when Clipboard API is unavailable
- User-friendly error messages for clipboard failures
- Ensure screenshot download continues even if clipboard fails
### User Feedback System
**Success States:**
- "Screenshot saved and copied to clipboard!" - when both operations succeed
- "Screenshot saved! (Clipboard copy failed: [reason])" - when download succeeds but clipboard fails
**Loading States:**
- Update existing loading message to indicate clipboard operation when enabled
- "Capturing screenshot and preparing clipboard..." vs "Capturing screenshot..."
## Data Models
### Settings Storage Schema
```javascript
{
backgroundPreference: 'black' | 'transparent' | 'white',
copyToClipboard: boolean // New addition
}
```
### Message Interface Extension
```javascript
// startSelector message
{
action: 'startSelector',
background: string,
copyToClipboard: boolean // New addition
}
```
## Error Handling
### Clipboard API Availability
- Check for `navigator.clipboard` and `ClipboardItem` support
- Provide clear error messages when API is unavailable
- Continue with download-only functionality as fallback
### Permission Handling
- Clipboard write operations may require user gesture
- Handle permission denied scenarios gracefully
- Provide user guidance for enabling clipboard permissions if needed
### Browser Compatibility
- Primary support: Chrome/Edge 76+, Firefox 87+, Safari 13.1+
- Fallback behavior for older browsers: disable clipboard feature with notification
- No impact on core screenshot functionality
## Testing Strategy
### Unit Testing Approach
- Mock Clipboard API for testing clipboard operations
- Test preference storage and retrieval
- Verify message passing between popup and content script
- Test error handling scenarios
### Integration Testing
- Test complete workflow: toggle setting → capture screenshot → verify clipboard content
- Test with different background settings and clipboard combinations
- Verify graceful degradation when Clipboard API unavailable
### Browser Compatibility Testing
- Test across Chrome, Firefox, Safari, Edge
- Verify behavior on older browser versions
- Test permission scenarios and user gesture requirements
### User Experience Testing
- Verify toggle state persistence across browser sessions
- Test visual feedback for success/error states
- Confirm tooltip and help text clarity
## Implementation Considerations
### Performance Impact
- Clipboard operations are asynchronous and won't block screenshot download
- Canvas-to-blob conversion adds minimal overhead
- No impact on screenshot capture performance
### Security Considerations
- Clipboard API requires secure context (HTTPS)
- User gesture requirement for clipboard write operations
- No sensitive data exposure through clipboard operations
### Accessibility
- Toggle control will include proper ARIA labels
- Keyboard navigation support for toggle control
- Screen reader compatible success/error messages
## Browser API Dependencies
### Required APIs
- `navigator.clipboard.write()` - Modern clipboard API
- `ClipboardItem` constructor - For image data handling
- `canvas.toBlob()` - Convert canvas to blob format
### Fallback Strategy
- Detect API availability before attempting clipboard operations
- Provide clear user feedback when clipboard features unavailable
- Maintain full functionality for screenshot download regardless of clipboard support

View file

@ -1,51 +0,0 @@
# Requirements Document
## Introduction
This feature adds a copy to clipboard toggle option to the Full Screenshot Selector extension, allowing users to choose whether captured screenshots should be automatically copied to the clipboard in addition to being downloaded as files. This provides users with more flexibility in how they handle their screenshots, enabling quick pasting into other applications without needing to locate and open the downloaded file.
## Requirements
### Requirement 1
**User Story:** As a user of the screenshot extension, I want to toggle whether screenshots are copied to clipboard, so that I can quickly paste them into other applications without downloading files.
#### Acceptance Criteria
1. WHEN the popup is opened THEN the system SHALL display a toggle control for "Copy to Clipboard"
2. WHEN the user toggles the copy to clipboard option THEN the system SHALL save this preference to browser storage
3. WHEN the extension is reopened THEN the system SHALL restore the previously saved copy to clipboard preference
4. WHEN a screenshot is captured AND copy to clipboard is enabled THEN the system SHALL copy the image data to the clipboard
5. WHEN a screenshot is captured AND copy to clipboard is enabled THEN the system SHALL still download the file as before (both actions occur)
### Requirement 2
**User Story:** As a user, I want the copy to clipboard feature to work reliably across different browsers, so that I can depend on this functionality regardless of my browser choice.
#### Acceptance Criteria
1. WHEN copy to clipboard is enabled THEN the system SHALL use the Clipboard API if available
2. IF the Clipboard API is not available THEN the system SHALL provide appropriate fallback behavior
3. WHEN clipboard copying fails THEN the system SHALL display an error message to the user
4. WHEN clipboard copying succeeds THEN the system SHALL display a success confirmation
### Requirement 3
**User Story:** As a user, I want clear visual feedback about the copy to clipboard feature, so that I understand when it's enabled and when clipboard operations succeed or fail.
#### Acceptance Criteria
1. WHEN the copy to clipboard toggle is enabled THEN the system SHALL display visual indication of the enabled state
2. WHEN a screenshot is captured with clipboard copying enabled THEN the system SHALL show a success message indicating both download and clipboard copy
3. WHEN clipboard copying fails THEN the system SHALL show an error message while still confirming the download succeeded
4. WHEN hovering over the copy to clipboard toggle THEN the system SHALL display helpful tooltip text
### Requirement 4
**User Story:** As a user, I want the copy to clipboard feature to handle different image formats appropriately, so that the clipboard content works well with various applications.
#### Acceptance Criteria
1. WHEN copying to clipboard THEN the system SHALL copy the image in PNG format
2. WHEN copying to clipboard THEN the system SHALL preserve the same image quality as the downloaded file
3. WHEN copying to clipboard THEN the system SHALL handle transparency settings according to the background preference

View file

@ -1,64 +0,0 @@
# Implementation Plan
- [x] 1. Add copy to clipboard toggle UI to popup
- Add HTML toggle control between background selector and start button in popup.html
- Style the toggle control to match existing UI design patterns
- Include proper ARIA labels and accessibility attributes for the toggle
- _Requirements: 1.1, 3.1, 3.4_
- [x] 2. Implement clipboard preference storage in popup
- Extend existing storage logic in popup.js to handle copyToClipboard preference
- Set default value to true for better user experience
- Load saved clipboard preference on popup initialization
- Save clipboard preference changes to chrome.storage.sync
- _Requirements: 1.2, 1.3_
- [x] 3. Update message passing to include clipboard setting
- Modify startSelector message in popup.js to include copyToClipboard property
- Update content script message handler to receive and store clipboard preference
- Ensure backward compatibility with existing message structure
- _Requirements: 1.1, 1.4_
- [x] 4. Implement clipboard API functionality in content script
- Add copyCanvasToClipboard method to ScreenshotSelector class
- Implement canvas to blob conversion for PNG format
- Use navigator.clipboard.write() with ClipboardItem for image data
- Handle async clipboard operations with proper error catching
- _Requirements: 2.1, 4.1, 4.2, 4.3_
- [x] 5. Add clipboard API availability detection
- Create method to check for navigator.clipboard and ClipboardItem support
- Implement graceful fallback when Clipboard API is unavailable
- Provide user feedback when clipboard features are not supported
- _Requirements: 2.2_
- [x] 6. Integrate clipboard operations into screenshot capture workflow
- Modify captureElement method to include clipboard operations when enabled
- Ensure clipboard copying happens after successful canvas generation
- Maintain existing download functionality regardless of clipboard success/failure
- _Requirements: 1.4, 1.5_
- [x] 7. Implement comprehensive error handling for clipboard operations
- Handle clipboard write permission errors gracefully
- Provide specific error messages for different failure scenarios
- Ensure screenshot download continues even when clipboard operations fail
- _Requirements: 2.3_
- [x] 8. Update user feedback messages for clipboard operations
- Modify loading message to indicate clipboard preparation when enabled
- Update success message to confirm both download and clipboard copy
- Create error messages that distinguish between download and clipboard failures
- _Requirements: 2.4, 3.2, 3.3_
- [x] 9. Add tooltip and help text for clipboard toggle
- Implement tooltip showing clipboard feature explanation
- Add help text explaining clipboard functionality and browser requirements
- Ensure tooltip is accessible and keyboard navigable
- _Requirements: 3.4_
- [x] 10. Test clipboard functionality across different scenarios
- Write test cases for clipboard API availability detection
- Test clipboard operations with different background settings (transparent, black, white)
- Verify error handling when clipboard API is unavailable or permissions denied
- Test preference persistence across browser sessions
- _Requirements: 2.1, 2.2, 2.3, 4.3_

View file

@ -1,187 +0,0 @@
# Design Document
## Overview
The save to PC toggle feature will be implemented as an additional setting in the extension popup, positioned alongside the existing clipboard toggle. The feature will modify the existing screenshot capture workflow to conditionally perform file downloads based on user preference. The implementation will ensure that users can independently control both clipboard copying and file downloading, providing maximum flexibility in their screenshot workflow.
## Architecture
The feature will be implemented across three main components:
1. **Popup UI Enhancement**: Add toggle control and persistence logic
2. **Content Script Integration**: Modify screenshot capture to conditionally download files
3. **Storage Management**: Extend existing preference storage system
4. **Validation Logic**: Ensure at least one output method is selected
The save to PC functionality will be implemented as a conditional enhancement to the existing screenshot workflow, maintaining backward compatibility while providing new flexibility.
## Components and Interfaces
### Popup Interface (`popup.html` & `popup.js`)
**New UI Elements:**
- Toggle switch control for "Save to PC" option
- Positioned above the clipboard toggle for logical grouping
- Consistent styling with existing controls
- Warning message when both toggles are disabled
**Storage Integration:**
- Extend existing `chrome.storage.sync` usage to include `saveToPc` preference
- Default value: `true` (enabled by default to maintain existing behavior)
- Load and save preferences alongside existing background and clipboard preferences
**Validation Logic:**
- Check that at least one output method (save to PC or clipboard) is enabled
- Display warning message when both are disabled
- Prevent screenshot capture when no output method is selected
**Message Passing:**
- Include `saveToPc` setting in the `startSelector` message to content script
- No changes needed to existing message structure, just additional property
### Content Script Enhancement (`content.js`)
**ScreenshotSelector Class Modifications:**
- Add `saveToPc` property to constructor
- Modify `init()` method to accept and store save to PC preference
- Enhance `captureElement()` method to conditionally perform file downloads
**Conditional Download Implementation:**
```javascript
// In captureElement method, replace automatic download with conditional logic
if (this.saveToPc) {
const link = document.createElement('a');
link.href = canvas.toDataURL('image/png');
link.download = `screenshot-${new Date().toISOString().slice(0, 19).replace(/[:.]/g, '-')}.png`;
link.click();
}
```
**User Feedback Enhancement:**
- Update success messages to reflect which operations were performed
- Handle cases where no output method is selected (should not occur due to popup validation)
### User Feedback System
**Success States:**
- "Screenshot saved and copied to clipboard!" - when both operations succeed
- "Screenshot saved!" - when only save to PC is enabled and succeeds
- "Screenshot copied to clipboard!" - when only clipboard is enabled and succeeds
- "Screenshot captured!" - fallback message for edge cases
**Error States:**
- "Please enable at least one output method (Save to PC or Copy to Clipboard)" - when both are disabled
- Existing clipboard error messages remain unchanged
**Loading States:**
- Update loading message to reflect enabled operations
- "Capturing screenshot..." - when only save to PC is enabled
- "Capturing screenshot and preparing for clipboard..." - when only clipboard is enabled
- "Capturing screenshot and preparing for clipboard..." - when both are enabled (clipboard preparation is the longer operation)
## Data Models
### Settings Storage Schema
```javascript
{
backgroundPreference: 'black' | 'transparent' | 'white',
copyToClipboard: boolean,
saveToPc: boolean // New addition
}
```
### Message Interface Extension
```javascript
// startSelector message
{
action: 'startSelector',
background: string,
copyToClipboard: boolean,
saveToPc: boolean // New addition
}
```
## Error Handling
### Validation Errors
- Prevent screenshot capture when both save to PC and clipboard are disabled
- Display clear error message in popup when no output method is selected
- Provide guidance on enabling at least one option
### Download Failures
- Handle file download failures gracefully (though these are rare in modern browsers)
- Ensure clipboard operations continue even if download fails (when both are enabled)
- Provide specific error messages for download-related issues
### Backward Compatibility
- Ensure existing users see no change in behavior (save to PC enabled by default)
- Handle cases where preference is not yet set in storage
- Maintain existing error handling for clipboard operations
## Testing Strategy
### Unit Testing Approach
- Test preference storage and retrieval for save to PC setting
- Verify message passing includes new saveToPc property
- Test validation logic for ensuring at least one output method is enabled
- Mock file download operations for testing conditional download logic
### Integration Testing
- Test complete workflow: toggle setting → capture screenshot → verify file download behavior
- Test all four combinations of save to PC and clipboard settings
- Verify error handling when both options are disabled
- Test preference persistence across browser sessions
### User Experience Testing
- Verify toggle state persistence across browser sessions
- Test visual feedback for different operation combinations
- Confirm tooltip and help text clarity
- Test warning messages when both toggles are disabled
## Implementation Considerations
### Performance Impact
- No performance impact when save to PC is enabled (existing behavior)
- Slight performance improvement when save to PC is disabled (no file creation)
- No impact on clipboard operations
### Security Considerations
- File downloads use existing browser download mechanisms
- No new security concerns introduced
- Maintains existing security model for clipboard operations
### Accessibility
- Save to PC toggle will include proper ARIA labels
- Keyboard navigation support for toggle control
- Screen reader compatible success/error messages
- Warning messages will be announced to screen readers
### User Experience Design
- Logical grouping of output method toggles
- Clear visual hierarchy with save to PC above clipboard (primary → secondary)
- Consistent styling with existing UI elements
- Intuitive default settings (both enabled initially)
## Browser Compatibility
### File Download Support
- File downloads work in all modern browsers
- No fallback needed as this is core browser functionality
- Existing implementation already handles download edge cases
### Storage and UI
- Uses existing chrome.storage.sync API (already implemented)
- Toggle UI uses existing CSS patterns
- No new browser API dependencies
## Migration Strategy
### Existing Users
- Default `saveToPc` to `true` when preference doesn't exist
- No change in behavior for existing users
- Seamless upgrade experience
### New Users
- Both save to PC and clipboard enabled by default
- Provides full functionality out of the box
- Users can customize based on their workflow preferences

View file

@ -1,51 +0,0 @@
# Requirements Document
## Introduction
This feature adds a save to PC toggle option to the Full Screenshot Selector extension, allowing users to choose whether captured screenshots should be automatically downloaded as files to their computer. This provides users with more flexibility in how they handle their screenshots, enabling them to use only the clipboard functionality without cluttering their downloads folder with files they may not need.
## Requirements
### Requirement 1
**User Story:** As a user of the screenshot extension, I want to toggle whether screenshots are saved to my PC, so that I can avoid downloading files when I only need to paste the image elsewhere.
#### Acceptance Criteria
1. WHEN the popup is opened THEN the system SHALL display a toggle control for "Save to PC"
2. WHEN the user toggles the save to PC option THEN the system SHALL save this preference to browser storage
3. WHEN the extension is reopened THEN the system SHALL restore the previously saved save to PC preference
4. WHEN a screenshot is captured AND save to PC is enabled THEN the system SHALL download the file as before
5. WHEN a screenshot is captured AND save to PC is disabled THEN the system SHALL NOT download any file
### Requirement 2
**User Story:** As a user, I want clear visual feedback about the save to PC feature, so that I understand when files will be downloaded and when they won't.
#### Acceptance Criteria
1. WHEN the save to PC toggle is enabled THEN the system SHALL display visual indication of the enabled state
2. WHEN a screenshot is captured with save to PC enabled THEN the system SHALL show a success message indicating the download
3. WHEN a screenshot is captured with save to PC disabled THEN the system SHALL show a success message without mentioning download
4. WHEN hovering over the save to PC toggle THEN the system SHALL display helpful tooltip text
### Requirement 3
**User Story:** As a user, I want the save to PC feature to work independently of the clipboard feature, so that I can choose any combination of saving and copying that suits my workflow.
#### Acceptance Criteria
1. WHEN both save to PC and copy to clipboard are enabled THEN the system SHALL perform both operations
2. WHEN only save to PC is enabled THEN the system SHALL only download the file
3. WHEN only copy to clipboard is enabled THEN the system SHALL only copy to clipboard
4. WHEN both features are disabled THEN the system SHALL show an error message and not capture the screenshot
### Requirement 4
**User Story:** As a user, I want sensible default settings for the save to PC feature, so that the extension works intuitively without requiring configuration.
#### Acceptance Criteria
1. WHEN the extension is used for the first time THEN the save to PC option SHALL be enabled by default
2. WHEN upgrading from a previous version THEN the save to PC option SHALL be enabled by default to maintain existing behavior
3. WHEN both save to PC and clipboard options are available THEN users SHALL be able to configure them independently

View file

@ -1,71 +0,0 @@
# Implementation Plan
- [x] 1. Add save to PC toggle UI to popup
- Add HTML toggle control above the clipboard toggle in popup.html
- Style the toggle control to match existing UI design patterns
- Include proper ARIA labels and accessibility attributes for the toggle
- Position the save to PC toggle logically above clipboard toggle
- _Requirements: 1.1, 2.1, 2.4_
- [x] 2. Implement save to PC preference storage in popup
- Extend existing storage logic in popup.js to handle saveToPc preference
- Set default value to true to maintain existing behavior for current users
- Load saved save to PC preference on popup initialization
- Save save to PC preference changes to chrome.storage.sync
- _Requirements: 1.2, 1.3, 4.1, 4.2_
- [x] 3. Add validation logic for output method selection
- Create validation function to ensure at least one output method is enabled
- Display warning message in popup when both save to PC and clipboard are disabled
- Prevent screenshot capture when no output method is selected
- Update start button state based on validation results
- _Requirements: 3.4_
- [x] 4. Update message passing to include save to PC setting
- Modify startSelector message in popup.js to include saveToPc property
- Update content script message handler to receive and store save to PC preference
- Ensure backward compatibility with existing message structure
- _Requirements: 1.1, 1.4_
- [x] 5. Implement conditional file download in content script
- Modify captureElement method in ScreenshotSelector class to conditionally download files
- Wrap existing download logic in conditional check for saveToPc preference
- Ensure canvas generation still occurs regardless of download preference (needed for clipboard)
- Maintain existing download filename generation and format
- _Requirements: 1.4, 1.5, 3.1, 3.2_
- [x] 6. Update user feedback messages for different operation combinations
- Modify success messages to reflect which operations were performed
- Create specific messages for save-only, clipboard-only, and both operations
- Update loading messages to reflect enabled operations
- Ensure error messages are appropriate for each operation combination
- _Requirements: 2.2, 2.3, 3.1, 3.2, 3.3_
- [x] 7. Add tooltip and help text for save to PC toggle
- Implement tooltip showing save to PC feature explanation
- Add help text explaining the relationship between save to PC and clipboard features
- Ensure tooltip is accessible and keyboard navigable
- Include information about default behavior and workflow flexibility
- _Requirements: 2.4_
- [x] 8. Implement warning system for disabled output methods
- Create visual warning when both save to PC and clipboard toggles are disabled
- Display clear guidance on enabling at least one output method
- Make warning accessible to screen readers
- Update warning state dynamically as toggles change
- _Requirements: 3.4_
- [x] 9. Test all combinations of save to PC and clipboard settings
- Write test cases for save-only mode (saveToPc: true, clipboard: false)
- Write test cases for clipboard-only mode (saveToPc: false, clipboard: true)
- Write test cases for both enabled (saveToPc: true, clipboard: true)
- Write test cases for validation when both disabled (saveToPc: false, clipboard: false)
- Verify preference persistence across browser sessions for all combinations
- _Requirements: 3.1, 3.2, 3.3, 3.4, 4.3_
- [ ] 10. Test backward compatibility and migration
- Test behavior when saveToPc preference doesn't exist in storage (new installation)
- Test behavior when upgrading from version without saveToPc preference
- Verify that existing users maintain current behavior (files still download by default)
- Test that new users get both features enabled by default
- _Requirements: 4.1, 4.2_

View file

@ -1,3 +0,0 @@
{
"kiroAgent.configureMCP": "Disabled"
}

View file

@ -1,224 +0,0 @@
body, html {
margin:0; padding: 0;
height: 100%;
}
body {
font-family: Helvetica Neue, Helvetica, Arial;
font-size: 14px;
color:#333;
}
.small { font-size: 12px; }
*, *:after, *:before {
-webkit-box-sizing:border-box;
-moz-box-sizing:border-box;
box-sizing:border-box;
}
h1 { font-size: 20px; margin: 0;}
h2 { font-size: 14px; }
pre {
font: 12px/1.4 Consolas, "Liberation Mono", Menlo, Courier, monospace;
margin: 0;
padding: 0;
-moz-tab-size: 2;
-o-tab-size: 2;
tab-size: 2;
}
a { color:#0074D9; text-decoration:none; }
a:hover { text-decoration:underline; }
.strong { font-weight: bold; }
.space-top1 { padding: 10px 0 0 0; }
.pad2y { padding: 20px 0; }
.pad1y { padding: 10px 0; }
.pad2x { padding: 0 20px; }
.pad2 { padding: 20px; }
.pad1 { padding: 10px; }
.space-left2 { padding-left:55px; }
.space-right2 { padding-right:20px; }
.center { text-align:center; }
.clearfix { display:block; }
.clearfix:after {
content:'';
display:block;
height:0;
clear:both;
visibility:hidden;
}
.fl { float: left; }
@media only screen and (max-width:640px) {
.col3 { width:100%; max-width:100%; }
.hide-mobile { display:none!important; }
}
.quiet {
color: #7f7f7f;
color: rgba(0,0,0,0.5);
}
.quiet a { opacity: 0.7; }
.fraction {
font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace;
font-size: 10px;
color: #555;
background: #E8E8E8;
padding: 4px 5px;
border-radius: 3px;
vertical-align: middle;
}
div.path a:link, div.path a:visited { color: #333; }
table.coverage {
border-collapse: collapse;
margin: 10px 0 0 0;
padding: 0;
}
table.coverage td {
margin: 0;
padding: 0;
vertical-align: top;
}
table.coverage td.line-count {
text-align: right;
padding: 0 5px 0 20px;
}
table.coverage td.line-coverage {
text-align: right;
padding-right: 10px;
min-width:20px;
}
table.coverage td span.cline-any {
display: inline-block;
padding: 0 5px;
width: 100%;
}
.missing-if-branch {
display: inline-block;
margin-right: 5px;
border-radius: 3px;
position: relative;
padding: 0 4px;
background: #333;
color: yellow;
}
.skip-if-branch {
display: none;
margin-right: 10px;
position: relative;
padding: 0 4px;
background: #ccc;
color: white;
}
.missing-if-branch .typ, .skip-if-branch .typ {
color: inherit !important;
}
.coverage-summary {
border-collapse: collapse;
width: 100%;
}
.coverage-summary tr { border-bottom: 1px solid #bbb; }
.keyline-all { border: 1px solid #ddd; }
.coverage-summary td, .coverage-summary th { padding: 10px; }
.coverage-summary tbody { border: 1px solid #bbb; }
.coverage-summary td { border-right: 1px solid #bbb; }
.coverage-summary td:last-child { border-right: none; }
.coverage-summary th {
text-align: left;
font-weight: normal;
white-space: nowrap;
}
.coverage-summary th.file { border-right: none !important; }
.coverage-summary th.pct { }
.coverage-summary th.pic,
.coverage-summary th.abs,
.coverage-summary td.pct,
.coverage-summary td.abs { text-align: right; }
.coverage-summary td.file { white-space: nowrap; }
.coverage-summary td.pic { min-width: 120px !important; }
.coverage-summary tfoot td { }
.coverage-summary .sorter {
height: 10px;
width: 7px;
display: inline-block;
margin-left: 0.5em;
background: url(sort-arrow-sprite.png) no-repeat scroll 0 0 transparent;
}
.coverage-summary .sorted .sorter {
background-position: 0 -20px;
}
.coverage-summary .sorted-desc .sorter {
background-position: 0 -10px;
}
.status-line { height: 10px; }
/* yellow */
.cbranch-no { background: yellow !important; color: #111; }
/* dark red */
.red.solid, .status-line.low, .low .cover-fill { background:#C21F39 }
.low .chart { border:1px solid #C21F39 }
.highlighted,
.highlighted .cstat-no, .highlighted .fstat-no, .highlighted .cbranch-no{
background: #C21F39 !important;
}
/* medium red */
.cstat-no, .fstat-no, .cbranch-no, .cbranch-no { background:#F6C6CE }
/* light red */
.low, .cline-no { background:#FCE1E5 }
/* light green */
.high, .cline-yes { background:rgb(230,245,208) }
/* medium green */
.cstat-yes { background:rgb(161,215,106) }
/* dark green */
.status-line.high, .high .cover-fill { background:rgb(77,146,33) }
.high .chart { border:1px solid rgb(77,146,33) }
/* dark yellow (gold) */
.status-line.medium, .medium .cover-fill { background: #f9cd0b; }
.medium .chart { border:1px solid #f9cd0b; }
/* light yellow */
.medium { background: #fff4c2; }
.cstat-skip { background: #ddd; color: #111; }
.fstat-skip { background: #ddd; color: #111 !important; }
.cbranch-skip { background: #ddd !important; color: #111; }
span.cline-neutral { background: #eaeaea; }
.coverage-summary td.empty {
opacity: .5;
padding-top: 4px;
padding-bottom: 4px;
line-height: 1;
color: #888;
}
.cover-fill, .cover-empty {
display:inline-block;
height: 12px;
}
.chart {
line-height: 0;
}
.cover-empty {
background: white;
}
.cover-full {
border-right: none !important;
}
pre.prettyprint {
border: none !important;
padding: 0 !important;
margin: 0 !important;
}
.com { color: #999 !important; }
.ignore-none { color: #999; font-weight: normal; }
.wrapper {
min-height: 100%;
height: auto !important;
height: 100%;
margin: 0 auto -48px;
}
.footer, .push {
height: 48px;
}

View file

@ -1,87 +0,0 @@
/* eslint-disable */
var jumpToCode = (function init() {
// Classes of code we would like to highlight in the file view
var missingCoverageClasses = ['.cbranch-no', '.cstat-no', '.fstat-no'];
// Elements to highlight in the file listing view
var fileListingElements = ['td.pct.low'];
// We don't want to select elements that are direct descendants of another match
var notSelector = ':not(' + missingCoverageClasses.join('):not(') + ') > '; // becomes `:not(a):not(b) > `
// Selecter that finds elements on the page to which we can jump
var selector =
fileListingElements.join(', ') +
', ' +
notSelector +
missingCoverageClasses.join(', ' + notSelector); // becomes `:not(a):not(b) > a, :not(a):not(b) > b`
// The NodeList of matching elements
var missingCoverageElements = document.querySelectorAll(selector);
var currentIndex;
function toggleClass(index) {
missingCoverageElements
.item(currentIndex)
.classList.remove('highlighted');
missingCoverageElements.item(index).classList.add('highlighted');
}
function makeCurrent(index) {
toggleClass(index);
currentIndex = index;
missingCoverageElements.item(index).scrollIntoView({
behavior: 'smooth',
block: 'center',
inline: 'center'
});
}
function goToPrevious() {
var nextIndex = 0;
if (typeof currentIndex !== 'number' || currentIndex === 0) {
nextIndex = missingCoverageElements.length - 1;
} else if (missingCoverageElements.length > 1) {
nextIndex = currentIndex - 1;
}
makeCurrent(nextIndex);
}
function goToNext() {
var nextIndex = 0;
if (
typeof currentIndex === 'number' &&
currentIndex < missingCoverageElements.length - 1
) {
nextIndex = currentIndex + 1;
}
makeCurrent(nextIndex);
}
return function jump(event) {
if (
document.getElementById('fileSearch') === document.activeElement &&
document.activeElement != null
) {
// if we're currently focused on the search input, we don't want to navigate
return;
}
switch (event.which) {
case 78: // n
case 74: // j
goToNext();
break;
case 66: // b
case 75: // k
case 80: // p
goToPrevious();
break;
}
};
})();
window.addEventListener('keydown', jumpToCode);

File diff suppressed because it is too large Load diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 445 B

View file

@ -1,131 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<title>Code coverage report for All files</title>
<meta charset="utf-8" />
<link rel="stylesheet" href="prettify.css" />
<link rel="stylesheet" href="base.css" />
<link rel="shortcut icon" type="image/x-icon" href="favicon.png" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<style type='text/css'>
.coverage-summary .sorter {
background-image: url(sort-arrow-sprite.png);
}
</style>
</head>
<body>
<div class='wrapper'>
<div class='pad1'>
<h1>All files</h1>
<div class='clearfix'>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Statements</span>
<span class='fraction'>0/463</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Branches</span>
<span class='fraction'>0/263</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Functions</span>
<span class='fraction'>0/61</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Lines</span>
<span class='fraction'>0/445</span>
</div>
</div>
<p class="quiet">
Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block.
</p>
<template id="filterTemplate">
<div class="quiet">
Filter:
<input type="search" id="fileSearch">
</div>
</template>
</div>
<div class='status-line low'></div>
<div class="pad1">
<table class="coverage-summary">
<thead>
<tr>
<th data-col="file" data-fmt="html" data-html="true" class="file">File</th>
<th data-col="pic" data-type="number" data-fmt="html" data-html="true" class="pic"></th>
<th data-col="statements" data-type="number" data-fmt="pct" class="pct">Statements</th>
<th data-col="statements_raw" data-type="number" data-fmt="html" class="abs"></th>
<th data-col="branches" data-type="number" data-fmt="pct" class="pct">Branches</th>
<th data-col="branches_raw" data-type="number" data-fmt="html" class="abs"></th>
<th data-col="functions" data-type="number" data-fmt="pct" class="pct">Functions</th>
<th data-col="functions_raw" data-type="number" data-fmt="html" class="abs"></th>
<th data-col="lines" data-type="number" data-fmt="pct" class="pct">Lines</th>
<th data-col="lines_raw" data-type="number" data-fmt="html" class="abs"></th>
</tr>
</thead>
<tbody><tr>
<td class="file low" data-value="content.js"><a href="content.js.html">content.js</a></td>
<td data-value="0" class="pic low">
<div class="chart"><div class="cover-fill" style="width: 0%"></div><div class="cover-empty" style="width: 100%"></div></div>
</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="371" class="abs low">0/371</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="214" class="abs low">0/214</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="44" class="abs low">0/44</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="356" class="abs low">0/356</td>
</tr>
<tr>
<td class="file low" data-value="popup.js"><a href="popup.js.html">popup.js</a></td>
<td data-value="0" class="pic low">
<div class="chart"><div class="cover-fill" style="width: 0%"></div><div class="cover-empty" style="width: 100%"></div></div>
</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="92" class="abs low">0/92</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="49" class="abs low">0/49</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="17" class="abs low">0/17</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="89" class="abs low">0/89</td>
</tr>
</tbody>
</table>
</div>
<div class='push'></div><!-- for sticky footer -->
</div><!-- /wrapper -->
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2025-08-13T15:07:03.182Z
</div>
<script src="prettify.js"></script>
<script>
window.onload = function () {
prettyPrint();
};
</script>
<script src="sorter.js"></script>
<script src="block-navigation.js"></script>
</body>
</html>

View file

@ -1,224 +0,0 @@
body, html {
margin:0; padding: 0;
height: 100%;
}
body {
font-family: Helvetica Neue, Helvetica, Arial;
font-size: 14px;
color:#333;
}
.small { font-size: 12px; }
*, *:after, *:before {
-webkit-box-sizing:border-box;
-moz-box-sizing:border-box;
box-sizing:border-box;
}
h1 { font-size: 20px; margin: 0;}
h2 { font-size: 14px; }
pre {
font: 12px/1.4 Consolas, "Liberation Mono", Menlo, Courier, monospace;
margin: 0;
padding: 0;
-moz-tab-size: 2;
-o-tab-size: 2;
tab-size: 2;
}
a { color:#0074D9; text-decoration:none; }
a:hover { text-decoration:underline; }
.strong { font-weight: bold; }
.space-top1 { padding: 10px 0 0 0; }
.pad2y { padding: 20px 0; }
.pad1y { padding: 10px 0; }
.pad2x { padding: 0 20px; }
.pad2 { padding: 20px; }
.pad1 { padding: 10px; }
.space-left2 { padding-left:55px; }
.space-right2 { padding-right:20px; }
.center { text-align:center; }
.clearfix { display:block; }
.clearfix:after {
content:'';
display:block;
height:0;
clear:both;
visibility:hidden;
}
.fl { float: left; }
@media only screen and (max-width:640px) {
.col3 { width:100%; max-width:100%; }
.hide-mobile { display:none!important; }
}
.quiet {
color: #7f7f7f;
color: rgba(0,0,0,0.5);
}
.quiet a { opacity: 0.7; }
.fraction {
font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace;
font-size: 10px;
color: #555;
background: #E8E8E8;
padding: 4px 5px;
border-radius: 3px;
vertical-align: middle;
}
div.path a:link, div.path a:visited { color: #333; }
table.coverage {
border-collapse: collapse;
margin: 10px 0 0 0;
padding: 0;
}
table.coverage td {
margin: 0;
padding: 0;
vertical-align: top;
}
table.coverage td.line-count {
text-align: right;
padding: 0 5px 0 20px;
}
table.coverage td.line-coverage {
text-align: right;
padding-right: 10px;
min-width:20px;
}
table.coverage td span.cline-any {
display: inline-block;
padding: 0 5px;
width: 100%;
}
.missing-if-branch {
display: inline-block;
margin-right: 5px;
border-radius: 3px;
position: relative;
padding: 0 4px;
background: #333;
color: yellow;
}
.skip-if-branch {
display: none;
margin-right: 10px;
position: relative;
padding: 0 4px;
background: #ccc;
color: white;
}
.missing-if-branch .typ, .skip-if-branch .typ {
color: inherit !important;
}
.coverage-summary {
border-collapse: collapse;
width: 100%;
}
.coverage-summary tr { border-bottom: 1px solid #bbb; }
.keyline-all { border: 1px solid #ddd; }
.coverage-summary td, .coverage-summary th { padding: 10px; }
.coverage-summary tbody { border: 1px solid #bbb; }
.coverage-summary td { border-right: 1px solid #bbb; }
.coverage-summary td:last-child { border-right: none; }
.coverage-summary th {
text-align: left;
font-weight: normal;
white-space: nowrap;
}
.coverage-summary th.file { border-right: none !important; }
.coverage-summary th.pct { }
.coverage-summary th.pic,
.coverage-summary th.abs,
.coverage-summary td.pct,
.coverage-summary td.abs { text-align: right; }
.coverage-summary td.file { white-space: nowrap; }
.coverage-summary td.pic { min-width: 120px !important; }
.coverage-summary tfoot td { }
.coverage-summary .sorter {
height: 10px;
width: 7px;
display: inline-block;
margin-left: 0.5em;
background: url(sort-arrow-sprite.png) no-repeat scroll 0 0 transparent;
}
.coverage-summary .sorted .sorter {
background-position: 0 -20px;
}
.coverage-summary .sorted-desc .sorter {
background-position: 0 -10px;
}
.status-line { height: 10px; }
/* yellow */
.cbranch-no { background: yellow !important; color: #111; }
/* dark red */
.red.solid, .status-line.low, .low .cover-fill { background:#C21F39 }
.low .chart { border:1px solid #C21F39 }
.highlighted,
.highlighted .cstat-no, .highlighted .fstat-no, .highlighted .cbranch-no{
background: #C21F39 !important;
}
/* medium red */
.cstat-no, .fstat-no, .cbranch-no, .cbranch-no { background:#F6C6CE }
/* light red */
.low, .cline-no { background:#FCE1E5 }
/* light green */
.high, .cline-yes { background:rgb(230,245,208) }
/* medium green */
.cstat-yes { background:rgb(161,215,106) }
/* dark green */
.status-line.high, .high .cover-fill { background:rgb(77,146,33) }
.high .chart { border:1px solid rgb(77,146,33) }
/* dark yellow (gold) */
.status-line.medium, .medium .cover-fill { background: #f9cd0b; }
.medium .chart { border:1px solid #f9cd0b; }
/* light yellow */
.medium { background: #fff4c2; }
.cstat-skip { background: #ddd; color: #111; }
.fstat-skip { background: #ddd; color: #111 !important; }
.cbranch-skip { background: #ddd !important; color: #111; }
span.cline-neutral { background: #eaeaea; }
.coverage-summary td.empty {
opacity: .5;
padding-top: 4px;
padding-bottom: 4px;
line-height: 1;
color: #888;
}
.cover-fill, .cover-empty {
display:inline-block;
height: 12px;
}
.chart {
line-height: 0;
}
.cover-empty {
background: white;
}
.cover-full {
border-right: none !important;
}
pre.prettyprint {
border: none !important;
padding: 0 !important;
margin: 0 !important;
}
.com { color: #999 !important; }
.ignore-none { color: #999; font-weight: normal; }
.wrapper {
min-height: 100%;
height: auto !important;
height: 100%;
margin: 0 auto -48px;
}
.footer, .push {
height: 48px;
}

View file

@ -1,87 +0,0 @@
/* eslint-disable */
var jumpToCode = (function init() {
// Classes of code we would like to highlight in the file view
var missingCoverageClasses = ['.cbranch-no', '.cstat-no', '.fstat-no'];
// Elements to highlight in the file listing view
var fileListingElements = ['td.pct.low'];
// We don't want to select elements that are direct descendants of another match
var notSelector = ':not(' + missingCoverageClasses.join('):not(') + ') > '; // becomes `:not(a):not(b) > `
// Selecter that finds elements on the page to which we can jump
var selector =
fileListingElements.join(', ') +
', ' +
notSelector +
missingCoverageClasses.join(', ' + notSelector); // becomes `:not(a):not(b) > a, :not(a):not(b) > b`
// The NodeList of matching elements
var missingCoverageElements = document.querySelectorAll(selector);
var currentIndex;
function toggleClass(index) {
missingCoverageElements
.item(currentIndex)
.classList.remove('highlighted');
missingCoverageElements.item(index).classList.add('highlighted');
}
function makeCurrent(index) {
toggleClass(index);
currentIndex = index;
missingCoverageElements.item(index).scrollIntoView({
behavior: 'smooth',
block: 'center',
inline: 'center'
});
}
function goToPrevious() {
var nextIndex = 0;
if (typeof currentIndex !== 'number' || currentIndex === 0) {
nextIndex = missingCoverageElements.length - 1;
} else if (missingCoverageElements.length > 1) {
nextIndex = currentIndex - 1;
}
makeCurrent(nextIndex);
}
function goToNext() {
var nextIndex = 0;
if (
typeof currentIndex === 'number' &&
currentIndex < missingCoverageElements.length - 1
) {
nextIndex = currentIndex + 1;
}
makeCurrent(nextIndex);
}
return function jump(event) {
if (
document.getElementById('fileSearch') === document.activeElement &&
document.activeElement != null
) {
// if we're currently focused on the search input, we don't want to navigate
return;
}
switch (event.which) {
case 78: // n
case 74: // j
goToNext();
break;
case 66: // b
case 75: // k
case 80: // p
goToPrevious();
break;
}
};
})();
window.addEventListener('keydown', jumpToCode);

File diff suppressed because it is too large Load diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 445 B

View file

@ -1,131 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<title>Code coverage report for All files</title>
<meta charset="utf-8" />
<link rel="stylesheet" href="prettify.css" />
<link rel="stylesheet" href="base.css" />
<link rel="shortcut icon" type="image/x-icon" href="favicon.png" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<style type='text/css'>
.coverage-summary .sorter {
background-image: url(sort-arrow-sprite.png);
}
</style>
</head>
<body>
<div class='wrapper'>
<div class='pad1'>
<h1>All files</h1>
<div class='clearfix'>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Statements</span>
<span class='fraction'>0/463</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Branches</span>
<span class='fraction'>0/263</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Functions</span>
<span class='fraction'>0/61</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Lines</span>
<span class='fraction'>0/445</span>
</div>
</div>
<p class="quiet">
Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block.
</p>
<template id="filterTemplate">
<div class="quiet">
Filter:
<input type="search" id="fileSearch">
</div>
</template>
</div>
<div class='status-line low'></div>
<div class="pad1">
<table class="coverage-summary">
<thead>
<tr>
<th data-col="file" data-fmt="html" data-html="true" class="file">File</th>
<th data-col="pic" data-type="number" data-fmt="html" data-html="true" class="pic"></th>
<th data-col="statements" data-type="number" data-fmt="pct" class="pct">Statements</th>
<th data-col="statements_raw" data-type="number" data-fmt="html" class="abs"></th>
<th data-col="branches" data-type="number" data-fmt="pct" class="pct">Branches</th>
<th data-col="branches_raw" data-type="number" data-fmt="html" class="abs"></th>
<th data-col="functions" data-type="number" data-fmt="pct" class="pct">Functions</th>
<th data-col="functions_raw" data-type="number" data-fmt="html" class="abs"></th>
<th data-col="lines" data-type="number" data-fmt="pct" class="pct">Lines</th>
<th data-col="lines_raw" data-type="number" data-fmt="html" class="abs"></th>
</tr>
</thead>
<tbody><tr>
<td class="file low" data-value="content.js"><a href="content.js.html">content.js</a></td>
<td data-value="0" class="pic low">
<div class="chart"><div class="cover-fill" style="width: 0%"></div><div class="cover-empty" style="width: 100%"></div></div>
</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="371" class="abs low">0/371</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="214" class="abs low">0/214</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="44" class="abs low">0/44</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="356" class="abs low">0/356</td>
</tr>
<tr>
<td class="file low" data-value="popup.js"><a href="popup.js.html">popup.js</a></td>
<td data-value="0" class="pic low">
<div class="chart"><div class="cover-fill" style="width: 0%"></div><div class="cover-empty" style="width: 100%"></div></div>
</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="92" class="abs low">0/92</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="49" class="abs low">0/49</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="17" class="abs low">0/17</td>
<td data-value="0" class="pct low">0%</td>
<td data-value="89" class="abs low">0/89</td>
</tr>
</tbody>
</table>
</div>
<div class='push'></div><!-- for sticky footer -->
</div><!-- /wrapper -->
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2025-08-13T15:07:03.165Z
</div>
<script src="prettify.js"></script>
<script>
window.onload = function () {
prettyPrint();
};
</script>
<script src="sorter.js"></script>
<script src="block-navigation.js"></script>
</body>
</html>

View file

@ -1,643 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<title>Code coverage report for popup.js</title>
<meta charset="utf-8" />
<link rel="stylesheet" href="prettify.css" />
<link rel="stylesheet" href="base.css" />
<link rel="shortcut icon" type="image/x-icon" href="favicon.png" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<style type='text/css'>
.coverage-summary .sorter {
background-image: url(sort-arrow-sprite.png);
}
</style>
</head>
<body>
<div class='wrapper'>
<div class='pad1'>
<h1><a href="index.html">All files</a> popup.js</h1>
<div class='clearfix'>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Statements</span>
<span class='fraction'>0/92</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Branches</span>
<span class='fraction'>0/49</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Functions</span>
<span class='fraction'>0/17</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Lines</span>
<span class='fraction'>0/89</span>
</div>
</div>
<p class="quiet">
Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block.
</p>
<template id="filterTemplate">
<div class="quiet">
Filter:
<input type="search" id="fileSearch">
</div>
</template>
</div>
<div class='status-line low'></div>
<pre><table class="coverage">
<tr><td class="line-count quiet"><a name='L1'></a><a href='#L1'>1</a>
<a name='L2'></a><a href='#L2'>2</a>
<a name='L3'></a><a href='#L3'>3</a>
<a name='L4'></a><a href='#L4'>4</a>
<a name='L5'></a><a href='#L5'>5</a>
<a name='L6'></a><a href='#L6'>6</a>
<a name='L7'></a><a href='#L7'>7</a>
<a name='L8'></a><a href='#L8'>8</a>
<a name='L9'></a><a href='#L9'>9</a>
<a name='L10'></a><a href='#L10'>10</a>
<a name='L11'></a><a href='#L11'>11</a>
<a name='L12'></a><a href='#L12'>12</a>
<a name='L13'></a><a href='#L13'>13</a>
<a name='L14'></a><a href='#L14'>14</a>
<a name='L15'></a><a href='#L15'>15</a>
<a name='L16'></a><a href='#L16'>16</a>
<a name='L17'></a><a href='#L17'>17</a>
<a name='L18'></a><a href='#L18'>18</a>
<a name='L19'></a><a href='#L19'>19</a>
<a name='L20'></a><a href='#L20'>20</a>
<a name='L21'></a><a href='#L21'>21</a>
<a name='L22'></a><a href='#L22'>22</a>
<a name='L23'></a><a href='#L23'>23</a>
<a name='L24'></a><a href='#L24'>24</a>
<a name='L25'></a><a href='#L25'>25</a>
<a name='L26'></a><a href='#L26'>26</a>
<a name='L27'></a><a href='#L27'>27</a>
<a name='L28'></a><a href='#L28'>28</a>
<a name='L29'></a><a href='#L29'>29</a>
<a name='L30'></a><a href='#L30'>30</a>
<a name='L31'></a><a href='#L31'>31</a>
<a name='L32'></a><a href='#L32'>32</a>
<a name='L33'></a><a href='#L33'>33</a>
<a name='L34'></a><a href='#L34'>34</a>
<a name='L35'></a><a href='#L35'>35</a>
<a name='L36'></a><a href='#L36'>36</a>
<a name='L37'></a><a href='#L37'>37</a>
<a name='L38'></a><a href='#L38'>38</a>
<a name='L39'></a><a href='#L39'>39</a>
<a name='L40'></a><a href='#L40'>40</a>
<a name='L41'></a><a href='#L41'>41</a>
<a name='L42'></a><a href='#L42'>42</a>
<a name='L43'></a><a href='#L43'>43</a>
<a name='L44'></a><a href='#L44'>44</a>
<a name='L45'></a><a href='#L45'>45</a>
<a name='L46'></a><a href='#L46'>46</a>
<a name='L47'></a><a href='#L47'>47</a>
<a name='L48'></a><a href='#L48'>48</a>
<a name='L49'></a><a href='#L49'>49</a>
<a name='L50'></a><a href='#L50'>50</a>
<a name='L51'></a><a href='#L51'>51</a>
<a name='L52'></a><a href='#L52'>52</a>
<a name='L53'></a><a href='#L53'>53</a>
<a name='L54'></a><a href='#L54'>54</a>
<a name='L55'></a><a href='#L55'>55</a>
<a name='L56'></a><a href='#L56'>56</a>
<a name='L57'></a><a href='#L57'>57</a>
<a name='L58'></a><a href='#L58'>58</a>
<a name='L59'></a><a href='#L59'>59</a>
<a name='L60'></a><a href='#L60'>60</a>
<a name='L61'></a><a href='#L61'>61</a>
<a name='L62'></a><a href='#L62'>62</a>
<a name='L63'></a><a href='#L63'>63</a>
<a name='L64'></a><a href='#L64'>64</a>
<a name='L65'></a><a href='#L65'>65</a>
<a name='L66'></a><a href='#L66'>66</a>
<a name='L67'></a><a href='#L67'>67</a>
<a name='L68'></a><a href='#L68'>68</a>
<a name='L69'></a><a href='#L69'>69</a>
<a name='L70'></a><a href='#L70'>70</a>
<a name='L71'></a><a href='#L71'>71</a>
<a name='L72'></a><a href='#L72'>72</a>
<a name='L73'></a><a href='#L73'>73</a>
<a name='L74'></a><a href='#L74'>74</a>
<a name='L75'></a><a href='#L75'>75</a>
<a name='L76'></a><a href='#L76'>76</a>
<a name='L77'></a><a href='#L77'>77</a>
<a name='L78'></a><a href='#L78'>78</a>
<a name='L79'></a><a href='#L79'>79</a>
<a name='L80'></a><a href='#L80'>80</a>
<a name='L81'></a><a href='#L81'>81</a>
<a name='L82'></a><a href='#L82'>82</a>
<a name='L83'></a><a href='#L83'>83</a>
<a name='L84'></a><a href='#L84'>84</a>
<a name='L85'></a><a href='#L85'>85</a>
<a name='L86'></a><a href='#L86'>86</a>
<a name='L87'></a><a href='#L87'>87</a>
<a name='L88'></a><a href='#L88'>88</a>
<a name='L89'></a><a href='#L89'>89</a>
<a name='L90'></a><a href='#L90'>90</a>
<a name='L91'></a><a href='#L91'>91</a>
<a name='L92'></a><a href='#L92'>92</a>
<a name='L93'></a><a href='#L93'>93</a>
<a name='L94'></a><a href='#L94'>94</a>
<a name='L95'></a><a href='#L95'>95</a>
<a name='L96'></a><a href='#L96'>96</a>
<a name='L97'></a><a href='#L97'>97</a>
<a name='L98'></a><a href='#L98'>98</a>
<a name='L99'></a><a href='#L99'>99</a>
<a name='L100'></a><a href='#L100'>100</a>
<a name='L101'></a><a href='#L101'>101</a>
<a name='L102'></a><a href='#L102'>102</a>
<a name='L103'></a><a href='#L103'>103</a>
<a name='L104'></a><a href='#L104'>104</a>
<a name='L105'></a><a href='#L105'>105</a>
<a name='L106'></a><a href='#L106'>106</a>
<a name='L107'></a><a href='#L107'>107</a>
<a name='L108'></a><a href='#L108'>108</a>
<a name='L109'></a><a href='#L109'>109</a>
<a name='L110'></a><a href='#L110'>110</a>
<a name='L111'></a><a href='#L111'>111</a>
<a name='L112'></a><a href='#L112'>112</a>
<a name='L113'></a><a href='#L113'>113</a>
<a name='L114'></a><a href='#L114'>114</a>
<a name='L115'></a><a href='#L115'>115</a>
<a name='L116'></a><a href='#L116'>116</a>
<a name='L117'></a><a href='#L117'>117</a>
<a name='L118'></a><a href='#L118'>118</a>
<a name='L119'></a><a href='#L119'>119</a>
<a name='L120'></a><a href='#L120'>120</a>
<a name='L121'></a><a href='#L121'>121</a>
<a name='L122'></a><a href='#L122'>122</a>
<a name='L123'></a><a href='#L123'>123</a>
<a name='L124'></a><a href='#L124'>124</a>
<a name='L125'></a><a href='#L125'>125</a>
<a name='L126'></a><a href='#L126'>126</a>
<a name='L127'></a><a href='#L127'>127</a>
<a name='L128'></a><a href='#L128'>128</a>
<a name='L129'></a><a href='#L129'>129</a>
<a name='L130'></a><a href='#L130'>130</a>
<a name='L131'></a><a href='#L131'>131</a>
<a name='L132'></a><a href='#L132'>132</a>
<a name='L133'></a><a href='#L133'>133</a>
<a name='L134'></a><a href='#L134'>134</a>
<a name='L135'></a><a href='#L135'>135</a>
<a name='L136'></a><a href='#L136'>136</a>
<a name='L137'></a><a href='#L137'>137</a>
<a name='L138'></a><a href='#L138'>138</a>
<a name='L139'></a><a href='#L139'>139</a>
<a name='L140'></a><a href='#L140'>140</a>
<a name='L141'></a><a href='#L141'>141</a>
<a name='L142'></a><a href='#L142'>142</a>
<a name='L143'></a><a href='#L143'>143</a>
<a name='L144'></a><a href='#L144'>144</a>
<a name='L145'></a><a href='#L145'>145</a>
<a name='L146'></a><a href='#L146'>146</a>
<a name='L147'></a><a href='#L147'>147</a>
<a name='L148'></a><a href='#L148'>148</a>
<a name='L149'></a><a href='#L149'>149</a>
<a name='L150'></a><a href='#L150'>150</a>
<a name='L151'></a><a href='#L151'>151</a>
<a name='L152'></a><a href='#L152'>152</a>
<a name='L153'></a><a href='#L153'>153</a>
<a name='L154'></a><a href='#L154'>154</a>
<a name='L155'></a><a href='#L155'>155</a>
<a name='L156'></a><a href='#L156'>156</a>
<a name='L157'></a><a href='#L157'>157</a>
<a name='L158'></a><a href='#L158'>158</a>
<a name='L159'></a><a href='#L159'>159</a>
<a name='L160'></a><a href='#L160'>160</a>
<a name='L161'></a><a href='#L161'>161</a>
<a name='L162'></a><a href='#L162'>162</a>
<a name='L163'></a><a href='#L163'>163</a>
<a name='L164'></a><a href='#L164'>164</a>
<a name='L165'></a><a href='#L165'>165</a>
<a name='L166'></a><a href='#L166'>166</a>
<a name='L167'></a><a href='#L167'>167</a>
<a name='L168'></a><a href='#L168'>168</a>
<a name='L169'></a><a href='#L169'>169</a>
<a name='L170'></a><a href='#L170'>170</a>
<a name='L171'></a><a href='#L171'>171</a>
<a name='L172'></a><a href='#L172'>172</a>
<a name='L173'></a><a href='#L173'>173</a>
<a name='L174'></a><a href='#L174'>174</a>
<a name='L175'></a><a href='#L175'>175</a>
<a name='L176'></a><a href='#L176'>176</a>
<a name='L177'></a><a href='#L177'>177</a>
<a name='L178'></a><a href='#L178'>178</a>
<a name='L179'></a><a href='#L179'>179</a>
<a name='L180'></a><a href='#L180'>180</a>
<a name='L181'></a><a href='#L181'>181</a>
<a name='L182'></a><a href='#L182'>182</a>
<a name='L183'></a><a href='#L183'>183</a>
<a name='L184'></a><a href='#L184'>184</a>
<a name='L185'></a><a href='#L185'>185</a>
<a name='L186'></a><a href='#L186'>186</a>
<a name='L187'></a><a href='#L187'>187</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">// Popup script for Chrome extension
<span class="cstat-no" title="statement not covered" >document.addEventListener('DOMContentLoaded', <span class="fstat-no" title="function not covered" >as</span>ync () =&gt; {</span>
const backgroundSelect = <span class="cstat-no" title="statement not covered" >document.getElementById('background-select');</span>
const clipboardToggle = <span class="cstat-no" title="statement not covered" >document.getElementById('clipboard-toggle');</span>
const startBtn = <span class="cstat-no" title="statement not covered" >document.getElementById('start-selector');</span>
const stopBtn = <span class="cstat-no" title="statement not covered" >document.getElementById('stop-selector');</span>
const status = <span class="cstat-no" title="statement not covered" >document.getElementById('status');</span>
&nbsp;
// Load saved preferences
const saved = <span class="cstat-no" title="statement not covered" >await chrome.storage.sync.get(['backgroundPreference', 'copyToClipboard']);</span>
<span class="cstat-no" title="statement not covered" > if (saved.backgroundPreference) {</span>
<span class="cstat-no" title="statement not covered" > backgroundSelect.value = saved.backgroundPreference;</span>
}
// Set clipboard preference (default to true if not set)
<span class="cstat-no" title="statement not covered" > clipboardToggle.checked = saved.copyToClipboard !== undefined ? saved.copyToClipboard : true;</span>
&nbsp;
// Save background preference when changed
<span class="cstat-no" title="statement not covered" > backgroundSelect.addEventListener('change', <span class="fstat-no" title="function not covered" >()</span> =&gt; {</span>
<span class="cstat-no" title="statement not covered" > chrome.storage.sync.set({ backgroundPreference: backgroundSelect.value });</span>
});
&nbsp;
// Save clipboard preference when changed
<span class="cstat-no" title="statement not covered" > clipboardToggle.addEventListener('change', <span class="fstat-no" title="function not covered" >()</span> =&gt; {</span>
<span class="cstat-no" title="statement not covered" > chrome.storage.sync.set({ copyToClipboard: clipboardToggle.checked });</span>
});
&nbsp;
// Start selector
<span class="cstat-no" title="statement not covered" > startBtn.addEventListener('click', <span class="fstat-no" title="function not covered" >as</span>ync () =&gt; {</span>
const [tab] = <span class="cstat-no" title="statement not covered" >await chrome.tabs.query({ active: true, currentWindow: true });</span>
&nbsp;
// Check if page is compatible
<span class="cstat-no" title="statement not covered" > if (tab.url.startsWith('chrome://') ||</span>
tab.url.startsWith('chrome-extension://') ||
tab.url.startsWith('edge://') ||
tab.url.startsWith('about:') ||
tab.url === 'chrome://newtab/' ||
tab.url === 'edge://newtab/') {
<span class="cstat-no" title="statement not covered" > showStatus('Error: Cannot capture screenshots on this page type.', 'error');</span>
<span class="cstat-no" title="statement not covered" > return;</span>
}
&nbsp;
<span class="cstat-no" title="statement not covered" > try {</span>
<span class="cstat-no" title="statement not covered" > await chrome.tabs.sendMessage(tab.id, {</span>
action: 'startSelector',
background: backgroundSelect.value,
copyToClipboard: clipboardToggle.checked
});
&nbsp;
<span class="cstat-no" title="statement not covered" > showStatus('Selector activated! Hover over elements and click to capture.', 'success');</span>
<span class="cstat-no" title="statement not covered" > toggleButtons(true);</span>
&nbsp;
// Auto-close popup after starting
<span class="cstat-no" title="statement not covered" > setTimeout(<span class="fstat-no" title="function not covered" >()</span> =&gt; <span class="cstat-no" title="statement not covered" >window.close(),</span> 1500);</span>
&nbsp;
} catch (error) {
<span class="cstat-no" title="statement not covered" > console.error('Full error details:', error);</span>
<span class="cstat-no" title="statement not covered" > if (error.message.includes('Could not establish connection')) {</span>
<span class="cstat-no" title="statement not covered" > showStatus('Error: Content script not loaded. Try refreshing the page.', 'error');</span>
} else {
<span class="cstat-no" title="statement not covered" > showStatus('Error: Could not activate on this page.', 'error');</span>
}
}
});
&nbsp;
// Stop selector
<span class="cstat-no" title="statement not covered" > stopBtn.addEventListener('click', <span class="fstat-no" title="function not covered" >as</span>ync () =&gt; {</span>
const [tab] = <span class="cstat-no" title="statement not covered" >await chrome.tabs.query({ active: true, currentWindow: true });</span>
&nbsp;
<span class="cstat-no" title="statement not covered" > try {</span>
<span class="cstat-no" title="statement not covered" > await chrome.tabs.sendMessage(tab.id, { action: 'stopSelector' });</span>
<span class="cstat-no" title="statement not covered" > showStatus('Selector stopped.', 'success');</span>
<span class="cstat-no" title="statement not covered" > toggleButtons(false);</span>
} catch (error) {
<span class="cstat-no" title="statement not covered" > console.error('Error stopping selector:', error);</span>
}
});
&nbsp;
// Check current state
<span class="cstat-no" title="statement not covered" > checkSelectorState();</span>
&nbsp;
// Handle tooltip keyboard navigation
<span class="cstat-no" title="statement not covered" > setupTooltipAccessibility();</span>
&nbsp;
function <span class="fstat-no" title="function not covered" >toggleButtons(</span>isActive) {
<span class="cstat-no" title="statement not covered" > if (isActive) {</span>
<span class="cstat-no" title="statement not covered" > startBtn.style.display = 'none';</span>
<span class="cstat-no" title="statement not covered" > stopBtn.style.display = 'block';</span>
} else {
<span class="cstat-no" title="statement not covered" > startBtn.style.display = 'block';</span>
<span class="cstat-no" title="statement not covered" > stopBtn.style.display = 'none';</span>
}
}
&nbsp;
function <span class="fstat-no" title="function not covered" >showStatus(</span>message, type = <span class="branch-0 cbranch-no" title="branch not covered" >'success')</span> {
<span class="cstat-no" title="statement not covered" > status.textContent = message;</span>
<span class="cstat-no" title="statement not covered" > status.className = `status ${type}`;</span>
<span class="cstat-no" title="statement not covered" > status.style.display = 'block';</span>
&nbsp;
<span class="cstat-no" title="statement not covered" > setTimeout(<span class="fstat-no" title="function not covered" >()</span> =&gt; {</span>
<span class="cstat-no" title="statement not covered" > status.style.display = 'none';</span>
}, 3000);
}
&nbsp;
async function <span class="fstat-no" title="function not covered" >checkSelectorState(</span>) {
const [tab] = <span class="cstat-no" title="statement not covered" >await chrome.tabs.query({ active: true, currentWindow: true });</span>
&nbsp;
// Skip check for incompatible pages
<span class="cstat-no" title="statement not covered" > if (tab.url.startsWith('chrome://') ||</span>
tab.url.startsWith('chrome-extension://') ||
tab.url.startsWith('edge://') ||
tab.url.startsWith('about:')) {
<span class="cstat-no" title="statement not covered" > return;</span>
}
&nbsp;
<span class="cstat-no" title="statement not covered" > try {</span>
const response = <span class="cstat-no" title="statement not covered" >await chrome.tabs.sendMessage(tab.id, { action: 'checkState' });</span>
<span class="cstat-no" title="statement not covered" > if (response &amp;&amp; response.isActive) {</span>
<span class="cstat-no" title="statement not covered" > toggleButtons(true);</span>
<span class="cstat-no" title="statement not covered" > showStatus('Selector is currently active', 'success');</span>
}
} catch (error) {
// Content script not ready or selector not active
<span class="cstat-no" title="statement not covered" > console.log('Content script not ready or selector inactive:', error.message);</span>
}
}
&nbsp;
function <span class="fstat-no" title="function not covered" >setupTooltipAccessibility(</span>) {
const tooltipIcon = <span class="cstat-no" title="statement not covered" >document.querySelector('.tooltip-icon');</span>
const tooltipContent = <span class="cstat-no" title="statement not covered" >document.querySelector('.tooltip-content');</span>
<span class="cstat-no" title="statement not covered" > if (!tooltipIcon || !tooltipContent) <span class="cstat-no" title="statement not covered" >return;</span></span>
&nbsp;
// Handle keyboard events for tooltip
<span class="cstat-no" title="statement not covered" > tooltipIcon.addEventListener('keydown', <span class="fstat-no" title="function not covered" >(e</span>) =&gt; {</span>
<span class="cstat-no" title="statement not covered" > if (e.key === 'Enter' || e.key === ' ') {</span>
<span class="cstat-no" title="statement not covered" > e.preventDefault();</span>
// Toggle tooltip visibility on Enter/Space
const isVisible = <span class="cstat-no" title="statement not covered" >tooltipContent.style.visibility === 'visible';</span>
<span class="cstat-no" title="statement not covered" > tooltipContent.style.visibility = isVisible ? 'hidden' : 'visible';</span>
<span class="cstat-no" title="statement not covered" > tooltipContent.style.opacity = isVisible ? '0' : '1';</span>
} else <span class="cstat-no" title="statement not covered" >if (e.key === 'Escape') {</span>
// Hide tooltip on Escape
<span class="cstat-no" title="statement not covered" > tooltipContent.style.visibility = 'hidden';</span>
<span class="cstat-no" title="statement not covered" > tooltipContent.style.opacity = '0';</span>
}
});
&nbsp;
// Hide tooltip when clicking outside
<span class="cstat-no" title="statement not covered" > document.addEventListener('click', <span class="fstat-no" title="function not covered" >(e</span>) =&gt; {</span>
<span class="cstat-no" title="statement not covered" > if (!tooltipIcon.contains(e.target)) {</span>
<span class="cstat-no" title="statement not covered" > tooltipContent.style.visibility = 'hidden';</span>
<span class="cstat-no" title="statement not covered" > tooltipContent.style.opacity = '0';</span>
}
});
&nbsp;
// Handle focus loss
<span class="cstat-no" title="statement not covered" > tooltipIcon.addEventListener('blur', <span class="fstat-no" title="function not covered" >(e</span>) =&gt; {</span>
// Small delay to allow for focus to move to tooltip content if needed
<span class="cstat-no" title="statement not covered" > setTimeout(<span class="fstat-no" title="function not covered" >()</span> =&gt; {</span>
<span class="cstat-no" title="statement not covered" > if (!tooltipIcon.matches(':focus-within')) {</span>
<span class="cstat-no" title="statement not covered" > tooltipContent.style.visibility = 'hidden';</span>
<span class="cstat-no" title="statement not covered" > tooltipContent.style.opacity = '0';</span>
}
}, 100);
});
}
});
&nbsp;
// Listen for messages from content script
<span class="cstat-no" title="statement not covered" >chrome.runtime.onMessage.addListener(<span class="fstat-no" title="function not covered" >(m</span>essage, sender, sendResponse) =&gt; {</span>
<span class="cstat-no" title="statement not covered" > if (message.action === 'selectorStopped') {</span>
const startBtn = <span class="cstat-no" title="statement not covered" >document.getElementById('start-selector');</span>
const stopBtn = <span class="cstat-no" title="statement not covered" >document.getElementById('stop-selector');</span>
const status = <span class="cstat-no" title="statement not covered" >document.getElementById('status');</span>
&nbsp;
<span class="cstat-no" title="statement not covered" > startBtn.style.display = 'block';</span>
<span class="cstat-no" title="statement not covered" > stopBtn.style.display = 'none';</span>
&nbsp;
<span class="cstat-no" title="statement not covered" > if (message.reason === 'screenshot-taken') {</span>
<span class="cstat-no" title="statement not covered" > status.textContent = 'Screenshot captured!';</span>
<span class="cstat-no" title="statement not covered" > status.className = 'status success';</span>
<span class="cstat-no" title="statement not covered" > status.style.display = 'block';</span>
<span class="cstat-no" title="statement not covered" > setTimeout(<span class="fstat-no" title="function not covered" >()</span> =&gt; <span class="cstat-no" title="statement not covered" >status.style.display = 'none',</span> 2000);</span>
}
}
});</pre></td></tr></table></pre>
<div class='push'></div><!-- for sticky footer -->
</div><!-- /wrapper -->
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2025-08-13T15:07:03.165Z
</div>
<script src="prettify.js"></script>
<script>
window.onload = function () {
prettyPrint();
};
</script>
<script src="sorter.js"></script>
<script src="block-navigation.js"></script>
</body>
</html>

View file

@ -1 +0,0 @@
.pln{color:#000}@media screen{.str{color:#080}.kwd{color:#008}.com{color:#800}.typ{color:#606}.lit{color:#066}.pun,.opn,.clo{color:#660}.tag{color:#008}.atn{color:#606}.atv{color:#080}.dec,.var{color:#606}.fun{color:red}}@media print,projection{.str{color:#060}.kwd{color:#006;font-weight:bold}.com{color:#600;font-style:italic}.typ{color:#404;font-weight:bold}.lit{color:#044}.pun,.opn,.clo{color:#440}.tag{color:#006;font-weight:bold}.atn{color:#404}.atv{color:#060}}pre.prettyprint{padding:2px;border:1px solid #888}ol.linenums{margin-top:0;margin-bottom:0}li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8{list-style-type:none}li.L1,li.L3,li.L5,li.L7,li.L9{background:#eee}

File diff suppressed because one or more lines are too long

Binary file not shown.

Before

Width:  |  Height:  |  Size: 138 B

View file

@ -1,196 +0,0 @@
/* eslint-disable */
var addSorting = (function() {
'use strict';
var cols,
currentSort = {
index: 0,
desc: false
};
// returns the summary table element
function getTable() {
return document.querySelector('.coverage-summary');
}
// returns the thead element of the summary table
function getTableHeader() {
return getTable().querySelector('thead tr');
}
// returns the tbody element of the summary table
function getTableBody() {
return getTable().querySelector('tbody');
}
// returns the th element for nth column
function getNthColumn(n) {
return getTableHeader().querySelectorAll('th')[n];
}
function onFilterInput() {
const searchValue = document.getElementById('fileSearch').value;
const rows = document.getElementsByTagName('tbody')[0].children;
for (let i = 0; i < rows.length; i++) {
const row = rows[i];
if (
row.textContent
.toLowerCase()
.includes(searchValue.toLowerCase())
) {
row.style.display = '';
} else {
row.style.display = 'none';
}
}
}
// loads the search box
function addSearchBox() {
var template = document.getElementById('filterTemplate');
var templateClone = template.content.cloneNode(true);
templateClone.getElementById('fileSearch').oninput = onFilterInput;
template.parentElement.appendChild(templateClone);
}
// loads all columns
function loadColumns() {
var colNodes = getTableHeader().querySelectorAll('th'),
colNode,
cols = [],
col,
i;
for (i = 0; i < colNodes.length; i += 1) {
colNode = colNodes[i];
col = {
key: colNode.getAttribute('data-col'),
sortable: !colNode.getAttribute('data-nosort'),
type: colNode.getAttribute('data-type') || 'string'
};
cols.push(col);
if (col.sortable) {
col.defaultDescSort = col.type === 'number';
colNode.innerHTML =
colNode.innerHTML + '<span class="sorter"></span>';
}
}
return cols;
}
// attaches a data attribute to every tr element with an object
// of data values keyed by column name
function loadRowData(tableRow) {
var tableCols = tableRow.querySelectorAll('td'),
colNode,
col,
data = {},
i,
val;
for (i = 0; i < tableCols.length; i += 1) {
colNode = tableCols[i];
col = cols[i];
val = colNode.getAttribute('data-value');
if (col.type === 'number') {
val = Number(val);
}
data[col.key] = val;
}
return data;
}
// loads all row data
function loadData() {
var rows = getTableBody().querySelectorAll('tr'),
i;
for (i = 0; i < rows.length; i += 1) {
rows[i].data = loadRowData(rows[i]);
}
}
// sorts the table using the data for the ith column
function sortByIndex(index, desc) {
var key = cols[index].key,
sorter = function(a, b) {
a = a.data[key];
b = b.data[key];
return a < b ? -1 : a > b ? 1 : 0;
},
finalSorter = sorter,
tableBody = document.querySelector('.coverage-summary tbody'),
rowNodes = tableBody.querySelectorAll('tr'),
rows = [],
i;
if (desc) {
finalSorter = function(a, b) {
return -1 * sorter(a, b);
};
}
for (i = 0; i < rowNodes.length; i += 1) {
rows.push(rowNodes[i]);
tableBody.removeChild(rowNodes[i]);
}
rows.sort(finalSorter);
for (i = 0; i < rows.length; i += 1) {
tableBody.appendChild(rows[i]);
}
}
// removes sort indicators for current column being sorted
function removeSortIndicators() {
var col = getNthColumn(currentSort.index),
cls = col.className;
cls = cls.replace(/ sorted$/, '').replace(/ sorted-desc$/, '');
col.className = cls;
}
// adds sort indicators for current column being sorted
function addSortIndicators() {
getNthColumn(currentSort.index).className += currentSort.desc
? ' sorted-desc'
: ' sorted';
}
// adds event listeners for all sorter widgets
function enableUI() {
var i,
el,
ithSorter = function ithSorter(i) {
var col = cols[i];
return function() {
var desc = col.defaultDescSort;
if (currentSort.index === i) {
desc = !currentSort.desc;
}
sortByIndex(i, desc);
removeSortIndicators();
currentSort.index = i;
currentSort.desc = desc;
addSortIndicators();
};
};
for (i = 0; i < cols.length; i += 1) {
if (cols[i].sortable) {
// add the click event handler on the th so users
// dont have to click on those tiny arrows
el = getNthColumn(i).querySelector('.sorter').parentElement;
if (el.addEventListener) {
el.addEventListener('click', ithSorter(i));
} else {
el.attachEvent('onclick', ithSorter(i));
}
}
}
}
// adds sorting functionality to the UI
return function() {
if (!getTable()) {
return;
}
cols = loadColumns();
loadData();
addSearchBox();
addSortIndicators();
enableUI();
};
})();
window.addEventListener('load', addSorting);

View file

@ -1,848 +0,0 @@
TN:
SF:content.js
FN:3,(anonymous_0)
FN:12,(anonymous_1)
FN:26,(anonymous_2)
FN:76,(anonymous_3)
FN:79,(anonymous_4)
FN:89,(anonymous_5)
FN:105,(anonymous_6)
FN:114,(anonymous_7)
FN:120,(anonymous_8)
FN:176,(anonymous_9)
FN:178,(anonymous_10)
FN:182,(anonymous_11)
FN:184,(anonymous_12)
FN:201,(anonymous_13)
FN:215,(anonymous_14)
FN:249,(anonymous_15)
FN:273,(anonymous_16)
FN:275,(anonymous_17)
FN:291,(anonymous_18)
FN:311,(anonymous_19)
FN:332,(anonymous_20)
FN:336,(anonymous_21)
FN:346,(anonymous_22)
FN:347,(anonymous_23)
FN:361,(anonymous_24)
FN:366,(anonymous_25)
FN:435,(anonymous_26)
FN:441,(anonymous_27)
FN:455,(anonymous_28)
FN:544,(anonymous_29)
FN:578,(anonymous_30)
FN:586,(anonymous_31)
FN:628,(anonymous_32)
FN:662,(anonymous_33)
FN:728,(anonymous_34)
FN:742,(anonymous_35)
FN:743,(anonymous_36)
FN:751,(anonymous_37)
FN:752,(anonymous_38)
FN:783,(anonymous_39)
FN:784,(anonymous_40)
FN:856,(anonymous_41)
FN:890,(anonymous_42)
FN:931,(anonymous_43)
FNF:44
FNH:0
FNDA:0,(anonymous_0)
FNDA:0,(anonymous_1)
FNDA:0,(anonymous_2)
FNDA:0,(anonymous_3)
FNDA:0,(anonymous_4)
FNDA:0,(anonymous_5)
FNDA:0,(anonymous_6)
FNDA:0,(anonymous_7)
FNDA:0,(anonymous_8)
FNDA:0,(anonymous_9)
FNDA:0,(anonymous_10)
FNDA:0,(anonymous_11)
FNDA:0,(anonymous_12)
FNDA:0,(anonymous_13)
FNDA:0,(anonymous_14)
FNDA:0,(anonymous_15)
FNDA:0,(anonymous_16)
FNDA:0,(anonymous_17)
FNDA:0,(anonymous_18)
FNDA:0,(anonymous_19)
FNDA:0,(anonymous_20)
FNDA:0,(anonymous_21)
FNDA:0,(anonymous_22)
FNDA:0,(anonymous_23)
FNDA:0,(anonymous_24)
FNDA:0,(anonymous_25)
FNDA:0,(anonymous_26)
FNDA:0,(anonymous_27)
FNDA:0,(anonymous_28)
FNDA:0,(anonymous_29)
FNDA:0,(anonymous_30)
FNDA:0,(anonymous_31)
FNDA:0,(anonymous_32)
FNDA:0,(anonymous_33)
FNDA:0,(anonymous_34)
FNDA:0,(anonymous_35)
FNDA:0,(anonymous_36)
FNDA:0,(anonymous_37)
FNDA:0,(anonymous_38)
FNDA:0,(anonymous_39)
FNDA:0,(anonymous_40)
FNDA:0,(anonymous_41)
FNDA:0,(anonymous_42)
FNDA:0,(anonymous_43)
DA:4,0
DA:5,0
DA:6,0
DA:7,0
DA:8,0
DA:9,0
DA:13,0
DA:14,0
DA:15,0
DA:18,0
DA:19,0
DA:20,0
DA:22,0
DA:23,0
DA:28,0
DA:29,0
DA:30,0
DA:41,0
DA:42,0
DA:72,0
DA:73,0
DA:76,0
DA:80,0
DA:81,0
DA:82,0
DA:84,0
DA:85,0
DA:86,0
DA:90,0
DA:93,0
DA:94,0
DA:95,0
DA:98,0
DA:99,0
DA:102,0
DA:106,0
DA:107,0
DA:108,0
DA:110,0
DA:111,0
DA:115,0
DA:116,0
DA:121,0
DA:122,0
DA:123,0
DA:125,0
DA:128,0
DA:129,0
DA:130,0
DA:131,0
DA:134,0
DA:135,0
DA:136,0
DA:137,0
DA:140,0
DA:147,0
DA:148,0
DA:151,0
DA:152,0
DA:153,0
DA:167,0
DA:168,0
DA:169,0
DA:170,0
DA:172,0
DA:177,0
DA:178,0
DA:184,0
DA:185,0
DA:186,0
DA:187,0
DA:191,0
DA:194,0
DA:195,0
DA:198,0
DA:199,0
DA:201,0
DA:203,0
DA:204,0
DA:209,0
DA:210,0
DA:211,0
DA:216,0
DA:218,0
DA:221,0
DA:249,0
DA:250,0
DA:251,0
DA:252,0
DA:253,0
DA:261,0
DA:264,0
DA:265,0
DA:267,0
DA:268,0
DA:274,0
DA:275,0
DA:276,0
DA:277,0
DA:280,0
DA:281,0
DA:289,0
DA:290,0
DA:291,0
DA:292,0
DA:293,0
DA:294,0
DA:297,0
DA:300,0
DA:301,0
DA:302,0
DA:313,0
DA:314,0
DA:315,0
DA:322,0
DA:329,0
DA:330,0
DA:332,0
DA:333,0
DA:334,0
DA:336,0
DA:337,0
DA:339,0
DA:340,0
DA:341,0
DA:342,0
DA:343,0
DA:344,0
DA:346,0
DA:347,0
DA:348,0
DA:349,0
DA:352,0
DA:358,0
DA:361,0
DA:367,0
DA:369,0
DA:370,0
DA:371,0
DA:372,0
DA:373,0
DA:375,0
DA:380,0
DA:396,0
DA:397,0
DA:400,0
DA:411,0
DA:412,0
DA:413,0
DA:414,0
DA:415,0
DA:418,0
DA:421,0
DA:437,0
DA:438,0
DA:441,0
DA:442,0
DA:443,0
DA:445,0
DA:446,0
DA:447,0
DA:448,0
DA:449,0
DA:450,0
DA:452,0
DA:453,0
DA:454,0
DA:455,0
DA:456,0
DA:459,0
DA:461,0
DA:465,0
DA:470,0
DA:471,0
DA:472,0
DA:473,0
DA:476,0
DA:481,0
DA:484,0
DA:485,0
DA:486,0
DA:487,0
DA:490,0
DA:491,0
DA:492,0
DA:493,0
DA:494,0
DA:496,0
DA:500,0
DA:501,0
DA:508,0
DA:517,0
DA:518,0
DA:520,0
DA:521,0
DA:522,0
DA:526,0
DA:527,0
DA:528,0
DA:532,0
DA:542,0
DA:544,0
DA:547,0
DA:550,0
DA:552,0
DA:553,0
DA:554,0
DA:555,0
DA:556,0
DA:557,0
DA:558,0
DA:559,0
DA:560,0
DA:561,0
DA:562,0
DA:566,0
DA:576,0
DA:578,0
DA:588,0
DA:589,0
DA:596,0
DA:597,0
DA:604,0
DA:605,0
DA:612,0
DA:613,0
DA:619,0
DA:629,0
DA:631,0
DA:632,0
DA:639,0
DA:641,0
DA:642,0
DA:643,0
DA:644,0
DA:645,0
DA:646,0
DA:648,0
DA:651,0
DA:663,0
DA:664,0
DA:667,0
DA:668,0
DA:671,0
DA:673,0
DA:677,0
DA:680,0
DA:684,0
DA:687,0
DA:690,0
DA:693,0
DA:696,0
DA:699,0
DA:702,0
DA:705,0
DA:709,0
DA:710,0
DA:711,0
DA:712,0
DA:713,0
DA:714,0
DA:715,0
DA:716,0
DA:718,0
DA:729,0
DA:731,0
DA:732,0
DA:733,0
DA:741,0
DA:743,0
DA:744,0
DA:745,0
DA:747,0
DA:752,0
DA:757,0
DA:758,0
DA:759,0
DA:768,0
DA:769,0
DA:773,0
DA:781,0
DA:784,0
DA:788,0
DA:791,0
DA:794,0
DA:795,0
DA:798,0
DA:799,0
DA:800,0
DA:803,0
DA:804,0
DA:805,0
DA:808,0
DA:809,0
DA:810,0
DA:813,0
DA:814,0
DA:815,0
DA:818,0
DA:819,0
DA:820,0
DA:823,0
DA:824,0
DA:825,0
DA:828,0
DA:829,0
DA:830,0
DA:833,0
DA:834,0
DA:835,0
DA:838,0
DA:839,0
DA:840,0
DA:844,0
DA:845,0
DA:848,0
DA:857,0
DA:858,0
DA:859,0
DA:861,0
DA:862,0
DA:866,0
DA:868,0
DA:869,0
DA:870,0
DA:873,0
DA:874,0
DA:875,0
DA:878,0
DA:879,0
DA:884,0
DA:887,0
DA:890,0
DA:891,0
DA:892,0
DA:895,0
DA:896,0
DA:897,0
DA:898,0
DA:901,0
DA:902,0
DA:903,0
DA:906,0
DA:907,0
DA:910,0
DA:911,0
DA:912,0
DA:916,0
DA:919,0
DA:922,0
DA:923,0
DA:927,0
DA:931,0
DA:932,0
DA:933,0
DA:934,0
LF:356
LH:0
BRDA:12,0,0,0
BRDA:12,1,0,0
BRDA:13,2,0,0
BRDA:13,2,1,0
BRDA:90,3,0,0
BRDA:90,3,1,0
BRDA:93,4,0,0
BRDA:93,4,1,0
BRDA:106,5,0,0
BRDA:106,5,1,0
BRDA:115,6,0,0
BRDA:115,6,1,0
BRDA:125,7,0,0
BRDA:125,7,1,0
BRDA:125,8,0,0
BRDA:125,8,1,0
BRDA:134,9,0,0
BRDA:134,9,1,0
BRDA:134,10,0,0
BRDA:134,10,1,0
BRDA:143,11,0,0
BRDA:143,11,1,0
BRDA:144,12,0,0
BRDA:144,12,1,0
BRDA:168,13,0,0
BRDA:168,13,1,0
BRDA:169,14,0,0
BRDA:169,14,1,0
BRDA:186,15,0,0
BRDA:186,15,1,0
BRDA:186,16,0,0
BRDA:186,16,1,0
BRDA:194,17,0,0
BRDA:194,17,1,0
BRDA:198,18,0,0
BRDA:198,18,1,0
BRDA:198,19,0,0
BRDA:198,19,1,0
BRDA:203,20,0,0
BRDA:203,20,1,0
BRDA:209,21,0,0
BRDA:209,21,1,0
BRDA:216,22,0,0
BRDA:216,22,1,0
BRDA:216,23,0,0
BRDA:216,23,1,0
BRDA:251,24,0,0
BRDA:251,24,1,0
BRDA:251,25,0,0
BRDA:251,25,1,0
BRDA:251,25,2,0
BRDA:251,25,3,0
BRDA:251,25,4,0
BRDA:280,26,0,0
BRDA:280,26,1,0
BRDA:280,27,0,0
BRDA:280,27,1,0
BRDA:280,27,2,0
BRDA:293,28,0,0
BRDA:293,28,1,0
BRDA:293,29,0,0
BRDA:293,29,1,0
BRDA:293,29,2,0
BRDA:313,30,0,0
BRDA:313,30,1,0
BRDA:313,31,0,0
BRDA:313,31,1,0
BRDA:337,32,0,0
BRDA:337,32,1,0
BRDA:370,33,0,0
BRDA:370,33,1,0
BRDA:372,34,0,0
BRDA:372,34,1,0
BRDA:424,35,0,0
BRDA:424,35,1,0
BRDA:425,36,0,0
BRDA:425,36,1,0
BRDA:428,37,0,0
BRDA:428,37,1,0
BRDA:443,38,0,0
BRDA:443,38,1,0
BRDA:450,39,0,0
BRDA:450,39,1,0
BRDA:450,40,0,0
BRDA:450,40,1,0
BRDA:472,41,0,0
BRDA:472,41,1,0
BRDA:472,42,0,0
BRDA:472,42,1,0
BRDA:491,43,0,0
BRDA:491,43,1,0
BRDA:493,44,0,0
BRDA:493,44,1,0
BRDA:520,45,0,0
BRDA:520,45,1,0
BRDA:521,46,0,0
BRDA:521,46,1,0
BRDA:521,47,0,0
BRDA:521,47,1,0
BRDA:552,48,0,0
BRDA:552,48,1,0
BRDA:553,49,0,0
BRDA:553,49,1,0
BRDA:555,50,0,0
BRDA:555,50,1,0
BRDA:557,51,0,0
BRDA:557,51,1,0
BRDA:557,52,0,0
BRDA:557,52,1,0
BRDA:559,53,0,0
BRDA:559,53,1,0
BRDA:559,54,0,0
BRDA:559,54,1,0
BRDA:561,55,0,0
BRDA:561,55,1,0
BRDA:588,56,0,0
BRDA:588,56,1,0
BRDA:596,57,0,0
BRDA:596,57,1,0
BRDA:604,58,0,0
BRDA:604,58,1,0
BRDA:612,59,0,0
BRDA:612,59,1,0
BRDA:631,60,0,0
BRDA:631,60,1,0
BRDA:641,61,0,0
BRDA:641,61,1,0
BRDA:641,62,0,0
BRDA:641,62,1,0
BRDA:643,63,0,0
BRDA:643,63,1,0
BRDA:645,64,0,0
BRDA:645,64,1,0
BRDA:663,65,0,0
BRDA:663,65,1,0
BRDA:663,66,0,0
BRDA:663,66,1,0
BRDA:671,67,0,0
BRDA:671,67,1,0
BRDA:671,67,2,0
BRDA:671,67,3,0
BRDA:671,67,4,0
BRDA:671,67,5,0
BRDA:671,67,6,0
BRDA:671,67,7,0
BRDA:671,67,8,0
BRDA:671,67,9,0
BRDA:671,67,10,0
BRDA:671,67,11,0
BRDA:671,67,12,0
BRDA:671,67,13,0
BRDA:709,68,0,0
BRDA:709,68,1,0
BRDA:709,69,0,0
BRDA:709,69,1,0
BRDA:711,70,0,0
BRDA:711,70,1,0
BRDA:711,71,0,0
BRDA:711,71,1,0
BRDA:713,72,0,0
BRDA:713,72,1,0
BRDA:713,73,0,0
BRDA:713,73,1,0
BRDA:715,74,0,0
BRDA:715,74,1,0
BRDA:715,75,0,0
BRDA:715,75,1,0
BRDA:732,76,0,0
BRDA:732,76,1,0
BRDA:744,77,0,0
BRDA:744,77,1,0
BRDA:758,78,0,0
BRDA:758,78,1,0
BRDA:794,79,0,0
BRDA:794,79,1,0
BRDA:798,80,0,0
BRDA:798,80,1,0
BRDA:803,81,0,0
BRDA:803,81,1,0
BRDA:808,82,0,0
BRDA:808,82,1,0
BRDA:813,83,0,0
BRDA:813,83,1,0
BRDA:818,84,0,0
BRDA:818,84,1,0
BRDA:823,85,0,0
BRDA:823,85,1,0
BRDA:823,86,0,0
BRDA:823,86,1,0
BRDA:828,87,0,0
BRDA:828,87,1,0
BRDA:828,88,0,0
BRDA:828,88,1,0
BRDA:833,89,0,0
BRDA:833,89,1,0
BRDA:838,90,0,0
BRDA:838,90,1,0
BRDA:861,91,0,0
BRDA:861,91,1,0
BRDA:868,92,0,0
BRDA:868,92,1,0
BRDA:873,93,0,0
BRDA:873,93,1,0
BRDA:892,94,0,0
BRDA:892,94,1,0
BRDA:892,94,2,0
BRDA:892,94,3,0
BRDA:892,94,4,0
BRDA:895,95,0,0
BRDA:895,95,1,0
BRDA:932,96,0,0
BRDA:932,96,1,0
BRDA:933,97,0,0
BRDA:933,97,1,0
BRF:214
BRH:0
end_of_record
TN:
SF:popup.js
FN:2,(anonymous_0)
FN:19,(anonymous_1)
FN:24,(anonymous_2)
FN:29,(anonymous_3)
FN:54,(anonymous_4)
FN:67,(anonymous_5)
FN:85,toggleButtons
FN:95,showStatus
FN:100,(anonymous_8)
FN:105,checkSelectorState
FN:128,setupTooltipAccessibility
FN:135,(anonymous_11)
FN:150,(anonymous_12)
FN:158,(anonymous_13)
FN:160,(anonymous_14)
FN:171,(anonymous_15)
FN:184,(anonymous_16)
FNF:17
FNH:0
FNDA:0,(anonymous_0)
FNDA:0,(anonymous_1)
FNDA:0,(anonymous_2)
FNDA:0,(anonymous_3)
FNDA:0,(anonymous_4)
FNDA:0,(anonymous_5)
FNDA:0,toggleButtons
FNDA:0,showStatus
FNDA:0,(anonymous_8)
FNDA:0,checkSelectorState
FNDA:0,setupTooltipAccessibility
FNDA:0,(anonymous_11)
FNDA:0,(anonymous_12)
FNDA:0,(anonymous_13)
FNDA:0,(anonymous_14)
FNDA:0,(anonymous_15)
FNDA:0,(anonymous_16)
DA:2,0
DA:3,0
DA:4,0
DA:5,0
DA:6,0
DA:7,0
DA:10,0
DA:11,0
DA:12,0
DA:16,0
DA:19,0
DA:20,0
DA:24,0
DA:25,0
DA:29,0
DA:30,0
DA:33,0
DA:39,0
DA:40,0
DA:43,0
DA:44,0
DA:50,0
DA:51,0
DA:54,0
DA:57,0
DA:58,0
DA:59,0
DA:61,0
DA:67,0
DA:68,0
DA:70,0
DA:71,0
DA:72,0
DA:73,0
DA:75,0
DA:80,0
DA:83,0
DA:86,0
DA:87,0
DA:88,0
DA:90,0
DA:91,0
DA:96,0
DA:97,0
DA:98,0
DA:100,0
DA:101,0
DA:106,0
DA:109,0
DA:113,0
DA:116,0
DA:117,0
DA:118,0
DA:119,0
DA:120,0
DA:124,0
DA:129,0
DA:130,0
DA:132,0
DA:135,0
DA:136,0
DA:137,0
DA:139,0
DA:140,0
DA:141,0
DA:142,0
DA:144,0
DA:145,0
DA:150,0
DA:151,0
DA:152,0
DA:153,0
DA:158,0
DA:160,0
DA:161,0
DA:162,0
DA:163,0
DA:171,0
DA:172,0
DA:173,0
DA:174,0
DA:175,0
DA:177,0
DA:178,0
DA:180,0
DA:181,0
DA:182,0
DA:183,0
DA:184,0
LF:89
LH:0
BRDA:11,0,0,0
BRDA:11,0,1,0
BRDA:16,1,0,0
BRDA:16,1,1,0
BRDA:33,2,0,0
BRDA:33,2,1,0
BRDA:33,3,0,0
BRDA:33,3,1,0
BRDA:33,3,2,0
BRDA:33,3,3,0
BRDA:33,3,4,0
BRDA:33,3,5,0
BRDA:58,4,0,0
BRDA:58,4,1,0
BRDA:86,5,0,0
BRDA:86,5,1,0
BRDA:95,6,0,0
BRDA:109,7,0,0
BRDA:109,7,1,0
BRDA:109,8,0,0
BRDA:109,8,1,0
BRDA:109,8,2,0
BRDA:109,8,3,0
BRDA:118,9,0,0
BRDA:118,9,1,0
BRDA:118,10,0,0
BRDA:118,10,1,0
BRDA:132,11,0,0
BRDA:132,11,1,0
BRDA:132,12,0,0
BRDA:132,12,1,0
BRDA:136,13,0,0
BRDA:136,13,1,0
BRDA:136,14,0,0
BRDA:136,14,1,0
BRDA:140,15,0,0
BRDA:140,15,1,0
BRDA:141,16,0,0
BRDA:141,16,1,0
BRDA:142,17,0,0
BRDA:142,17,1,0
BRDA:151,18,0,0
BRDA:151,18,1,0
BRDA:161,19,0,0
BRDA:161,19,1,0
BRDA:172,20,0,0
BRDA:172,20,1,0
BRDA:180,21,0,0
BRDA:180,21,1,0
BRF:49
BRH:0
end_of_record

View file

@ -1,643 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<title>Code coverage report for popup.js</title>
<meta charset="utf-8" />
<link rel="stylesheet" href="prettify.css" />
<link rel="stylesheet" href="base.css" />
<link rel="shortcut icon" type="image/x-icon" href="favicon.png" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<style type='text/css'>
.coverage-summary .sorter {
background-image: url(sort-arrow-sprite.png);
}
</style>
</head>
<body>
<div class='wrapper'>
<div class='pad1'>
<h1><a href="index.html">All files</a> popup.js</h1>
<div class='clearfix'>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Statements</span>
<span class='fraction'>0/92</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Branches</span>
<span class='fraction'>0/49</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Functions</span>
<span class='fraction'>0/17</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Lines</span>
<span class='fraction'>0/89</span>
</div>
</div>
<p class="quiet">
Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block.
</p>
<template id="filterTemplate">
<div class="quiet">
Filter:
<input type="search" id="fileSearch">
</div>
</template>
</div>
<div class='status-line low'></div>
<pre><table class="coverage">
<tr><td class="line-count quiet"><a name='L1'></a><a href='#L1'>1</a>
<a name='L2'></a><a href='#L2'>2</a>
<a name='L3'></a><a href='#L3'>3</a>
<a name='L4'></a><a href='#L4'>4</a>
<a name='L5'></a><a href='#L5'>5</a>
<a name='L6'></a><a href='#L6'>6</a>
<a name='L7'></a><a href='#L7'>7</a>
<a name='L8'></a><a href='#L8'>8</a>
<a name='L9'></a><a href='#L9'>9</a>
<a name='L10'></a><a href='#L10'>10</a>
<a name='L11'></a><a href='#L11'>11</a>
<a name='L12'></a><a href='#L12'>12</a>
<a name='L13'></a><a href='#L13'>13</a>
<a name='L14'></a><a href='#L14'>14</a>
<a name='L15'></a><a href='#L15'>15</a>
<a name='L16'></a><a href='#L16'>16</a>
<a name='L17'></a><a href='#L17'>17</a>
<a name='L18'></a><a href='#L18'>18</a>
<a name='L19'></a><a href='#L19'>19</a>
<a name='L20'></a><a href='#L20'>20</a>
<a name='L21'></a><a href='#L21'>21</a>
<a name='L22'></a><a href='#L22'>22</a>
<a name='L23'></a><a href='#L23'>23</a>
<a name='L24'></a><a href='#L24'>24</a>
<a name='L25'></a><a href='#L25'>25</a>
<a name='L26'></a><a href='#L26'>26</a>
<a name='L27'></a><a href='#L27'>27</a>
<a name='L28'></a><a href='#L28'>28</a>
<a name='L29'></a><a href='#L29'>29</a>
<a name='L30'></a><a href='#L30'>30</a>
<a name='L31'></a><a href='#L31'>31</a>
<a name='L32'></a><a href='#L32'>32</a>
<a name='L33'></a><a href='#L33'>33</a>
<a name='L34'></a><a href='#L34'>34</a>
<a name='L35'></a><a href='#L35'>35</a>
<a name='L36'></a><a href='#L36'>36</a>
<a name='L37'></a><a href='#L37'>37</a>
<a name='L38'></a><a href='#L38'>38</a>
<a name='L39'></a><a href='#L39'>39</a>
<a name='L40'></a><a href='#L40'>40</a>
<a name='L41'></a><a href='#L41'>41</a>
<a name='L42'></a><a href='#L42'>42</a>
<a name='L43'></a><a href='#L43'>43</a>
<a name='L44'></a><a href='#L44'>44</a>
<a name='L45'></a><a href='#L45'>45</a>
<a name='L46'></a><a href='#L46'>46</a>
<a name='L47'></a><a href='#L47'>47</a>
<a name='L48'></a><a href='#L48'>48</a>
<a name='L49'></a><a href='#L49'>49</a>
<a name='L50'></a><a href='#L50'>50</a>
<a name='L51'></a><a href='#L51'>51</a>
<a name='L52'></a><a href='#L52'>52</a>
<a name='L53'></a><a href='#L53'>53</a>
<a name='L54'></a><a href='#L54'>54</a>
<a name='L55'></a><a href='#L55'>55</a>
<a name='L56'></a><a href='#L56'>56</a>
<a name='L57'></a><a href='#L57'>57</a>
<a name='L58'></a><a href='#L58'>58</a>
<a name='L59'></a><a href='#L59'>59</a>
<a name='L60'></a><a href='#L60'>60</a>
<a name='L61'></a><a href='#L61'>61</a>
<a name='L62'></a><a href='#L62'>62</a>
<a name='L63'></a><a href='#L63'>63</a>
<a name='L64'></a><a href='#L64'>64</a>
<a name='L65'></a><a href='#L65'>65</a>
<a name='L66'></a><a href='#L66'>66</a>
<a name='L67'></a><a href='#L67'>67</a>
<a name='L68'></a><a href='#L68'>68</a>
<a name='L69'></a><a href='#L69'>69</a>
<a name='L70'></a><a href='#L70'>70</a>
<a name='L71'></a><a href='#L71'>71</a>
<a name='L72'></a><a href='#L72'>72</a>
<a name='L73'></a><a href='#L73'>73</a>
<a name='L74'></a><a href='#L74'>74</a>
<a name='L75'></a><a href='#L75'>75</a>
<a name='L76'></a><a href='#L76'>76</a>
<a name='L77'></a><a href='#L77'>77</a>
<a name='L78'></a><a href='#L78'>78</a>
<a name='L79'></a><a href='#L79'>79</a>
<a name='L80'></a><a href='#L80'>80</a>
<a name='L81'></a><a href='#L81'>81</a>
<a name='L82'></a><a href='#L82'>82</a>
<a name='L83'></a><a href='#L83'>83</a>
<a name='L84'></a><a href='#L84'>84</a>
<a name='L85'></a><a href='#L85'>85</a>
<a name='L86'></a><a href='#L86'>86</a>
<a name='L87'></a><a href='#L87'>87</a>
<a name='L88'></a><a href='#L88'>88</a>
<a name='L89'></a><a href='#L89'>89</a>
<a name='L90'></a><a href='#L90'>90</a>
<a name='L91'></a><a href='#L91'>91</a>
<a name='L92'></a><a href='#L92'>92</a>
<a name='L93'></a><a href='#L93'>93</a>
<a name='L94'></a><a href='#L94'>94</a>
<a name='L95'></a><a href='#L95'>95</a>
<a name='L96'></a><a href='#L96'>96</a>
<a name='L97'></a><a href='#L97'>97</a>
<a name='L98'></a><a href='#L98'>98</a>
<a name='L99'></a><a href='#L99'>99</a>
<a name='L100'></a><a href='#L100'>100</a>
<a name='L101'></a><a href='#L101'>101</a>
<a name='L102'></a><a href='#L102'>102</a>
<a name='L103'></a><a href='#L103'>103</a>
<a name='L104'></a><a href='#L104'>104</a>
<a name='L105'></a><a href='#L105'>105</a>
<a name='L106'></a><a href='#L106'>106</a>
<a name='L107'></a><a href='#L107'>107</a>
<a name='L108'></a><a href='#L108'>108</a>
<a name='L109'></a><a href='#L109'>109</a>
<a name='L110'></a><a href='#L110'>110</a>
<a name='L111'></a><a href='#L111'>111</a>
<a name='L112'></a><a href='#L112'>112</a>
<a name='L113'></a><a href='#L113'>113</a>
<a name='L114'></a><a href='#L114'>114</a>
<a name='L115'></a><a href='#L115'>115</a>
<a name='L116'></a><a href='#L116'>116</a>
<a name='L117'></a><a href='#L117'>117</a>
<a name='L118'></a><a href='#L118'>118</a>
<a name='L119'></a><a href='#L119'>119</a>
<a name='L120'></a><a href='#L120'>120</a>
<a name='L121'></a><a href='#L121'>121</a>
<a name='L122'></a><a href='#L122'>122</a>
<a name='L123'></a><a href='#L123'>123</a>
<a name='L124'></a><a href='#L124'>124</a>
<a name='L125'></a><a href='#L125'>125</a>
<a name='L126'></a><a href='#L126'>126</a>
<a name='L127'></a><a href='#L127'>127</a>
<a name='L128'></a><a href='#L128'>128</a>
<a name='L129'></a><a href='#L129'>129</a>
<a name='L130'></a><a href='#L130'>130</a>
<a name='L131'></a><a href='#L131'>131</a>
<a name='L132'></a><a href='#L132'>132</a>
<a name='L133'></a><a href='#L133'>133</a>
<a name='L134'></a><a href='#L134'>134</a>
<a name='L135'></a><a href='#L135'>135</a>
<a name='L136'></a><a href='#L136'>136</a>
<a name='L137'></a><a href='#L137'>137</a>
<a name='L138'></a><a href='#L138'>138</a>
<a name='L139'></a><a href='#L139'>139</a>
<a name='L140'></a><a href='#L140'>140</a>
<a name='L141'></a><a href='#L141'>141</a>
<a name='L142'></a><a href='#L142'>142</a>
<a name='L143'></a><a href='#L143'>143</a>
<a name='L144'></a><a href='#L144'>144</a>
<a name='L145'></a><a href='#L145'>145</a>
<a name='L146'></a><a href='#L146'>146</a>
<a name='L147'></a><a href='#L147'>147</a>
<a name='L148'></a><a href='#L148'>148</a>
<a name='L149'></a><a href='#L149'>149</a>
<a name='L150'></a><a href='#L150'>150</a>
<a name='L151'></a><a href='#L151'>151</a>
<a name='L152'></a><a href='#L152'>152</a>
<a name='L153'></a><a href='#L153'>153</a>
<a name='L154'></a><a href='#L154'>154</a>
<a name='L155'></a><a href='#L155'>155</a>
<a name='L156'></a><a href='#L156'>156</a>
<a name='L157'></a><a href='#L157'>157</a>
<a name='L158'></a><a href='#L158'>158</a>
<a name='L159'></a><a href='#L159'>159</a>
<a name='L160'></a><a href='#L160'>160</a>
<a name='L161'></a><a href='#L161'>161</a>
<a name='L162'></a><a href='#L162'>162</a>
<a name='L163'></a><a href='#L163'>163</a>
<a name='L164'></a><a href='#L164'>164</a>
<a name='L165'></a><a href='#L165'>165</a>
<a name='L166'></a><a href='#L166'>166</a>
<a name='L167'></a><a href='#L167'>167</a>
<a name='L168'></a><a href='#L168'>168</a>
<a name='L169'></a><a href='#L169'>169</a>
<a name='L170'></a><a href='#L170'>170</a>
<a name='L171'></a><a href='#L171'>171</a>
<a name='L172'></a><a href='#L172'>172</a>
<a name='L173'></a><a href='#L173'>173</a>
<a name='L174'></a><a href='#L174'>174</a>
<a name='L175'></a><a href='#L175'>175</a>
<a name='L176'></a><a href='#L176'>176</a>
<a name='L177'></a><a href='#L177'>177</a>
<a name='L178'></a><a href='#L178'>178</a>
<a name='L179'></a><a href='#L179'>179</a>
<a name='L180'></a><a href='#L180'>180</a>
<a name='L181'></a><a href='#L181'>181</a>
<a name='L182'></a><a href='#L182'>182</a>
<a name='L183'></a><a href='#L183'>183</a>
<a name='L184'></a><a href='#L184'>184</a>
<a name='L185'></a><a href='#L185'>185</a>
<a name='L186'></a><a href='#L186'>186</a>
<a name='L187'></a><a href='#L187'>187</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-no">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span>
<span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">// Popup script for Chrome extension
<span class="cstat-no" title="statement not covered" >document.addEventListener('DOMContentLoaded', <span class="fstat-no" title="function not covered" >as</span>ync () =&gt; {</span>
const backgroundSelect = <span class="cstat-no" title="statement not covered" >document.getElementById('background-select');</span>
const clipboardToggle = <span class="cstat-no" title="statement not covered" >document.getElementById('clipboard-toggle');</span>
const startBtn = <span class="cstat-no" title="statement not covered" >document.getElementById('start-selector');</span>
const stopBtn = <span class="cstat-no" title="statement not covered" >document.getElementById('stop-selector');</span>
const status = <span class="cstat-no" title="statement not covered" >document.getElementById('status');</span>
&nbsp;
// Load saved preferences
const saved = <span class="cstat-no" title="statement not covered" >await chrome.storage.sync.get(['backgroundPreference', 'copyToClipboard']);</span>
<span class="cstat-no" title="statement not covered" > if (saved.backgroundPreference) {</span>
<span class="cstat-no" title="statement not covered" > backgroundSelect.value = saved.backgroundPreference;</span>
}
// Set clipboard preference (default to true if not set)
<span class="cstat-no" title="statement not covered" > clipboardToggle.checked = saved.copyToClipboard !== undefined ? saved.copyToClipboard : true;</span>
&nbsp;
// Save background preference when changed
<span class="cstat-no" title="statement not covered" > backgroundSelect.addEventListener('change', <span class="fstat-no" title="function not covered" >()</span> =&gt; {</span>
<span class="cstat-no" title="statement not covered" > chrome.storage.sync.set({ backgroundPreference: backgroundSelect.value });</span>
});
&nbsp;
// Save clipboard preference when changed
<span class="cstat-no" title="statement not covered" > clipboardToggle.addEventListener('change', <span class="fstat-no" title="function not covered" >()</span> =&gt; {</span>
<span class="cstat-no" title="statement not covered" > chrome.storage.sync.set({ copyToClipboard: clipboardToggle.checked });</span>
});
&nbsp;
// Start selector
<span class="cstat-no" title="statement not covered" > startBtn.addEventListener('click', <span class="fstat-no" title="function not covered" >as</span>ync () =&gt; {</span>
const [tab] = <span class="cstat-no" title="statement not covered" >await chrome.tabs.query({ active: true, currentWindow: true });</span>
&nbsp;
// Check if page is compatible
<span class="cstat-no" title="statement not covered" > if (tab.url.startsWith('chrome://') ||</span>
tab.url.startsWith('chrome-extension://') ||
tab.url.startsWith('edge://') ||
tab.url.startsWith('about:') ||
tab.url === 'chrome://newtab/' ||
tab.url === 'edge://newtab/') {
<span class="cstat-no" title="statement not covered" > showStatus('Error: Cannot capture screenshots on this page type.', 'error');</span>
<span class="cstat-no" title="statement not covered" > return;</span>
}
&nbsp;
<span class="cstat-no" title="statement not covered" > try {</span>
<span class="cstat-no" title="statement not covered" > await chrome.tabs.sendMessage(tab.id, {</span>
action: 'startSelector',
background: backgroundSelect.value,
copyToClipboard: clipboardToggle.checked
});
&nbsp;
<span class="cstat-no" title="statement not covered" > showStatus('Selector activated! Hover over elements and click to capture.', 'success');</span>
<span class="cstat-no" title="statement not covered" > toggleButtons(true);</span>
&nbsp;
// Auto-close popup after starting
<span class="cstat-no" title="statement not covered" > setTimeout(<span class="fstat-no" title="function not covered" >()</span> =&gt; <span class="cstat-no" title="statement not covered" >window.close(),</span> 1500);</span>
&nbsp;
} catch (error) {
<span class="cstat-no" title="statement not covered" > console.error('Full error details:', error);</span>
<span class="cstat-no" title="statement not covered" > if (error.message.includes('Could not establish connection')) {</span>
<span class="cstat-no" title="statement not covered" > showStatus('Error: Content script not loaded. Try refreshing the page.', 'error');</span>
} else {
<span class="cstat-no" title="statement not covered" > showStatus('Error: Could not activate on this page.', 'error');</span>
}
}
});
&nbsp;
// Stop selector
<span class="cstat-no" title="statement not covered" > stopBtn.addEventListener('click', <span class="fstat-no" title="function not covered" >as</span>ync () =&gt; {</span>
const [tab] = <span class="cstat-no" title="statement not covered" >await chrome.tabs.query({ active: true, currentWindow: true });</span>
&nbsp;
<span class="cstat-no" title="statement not covered" > try {</span>
<span class="cstat-no" title="statement not covered" > await chrome.tabs.sendMessage(tab.id, { action: 'stopSelector' });</span>
<span class="cstat-no" title="statement not covered" > showStatus('Selector stopped.', 'success');</span>
<span class="cstat-no" title="statement not covered" > toggleButtons(false);</span>
} catch (error) {
<span class="cstat-no" title="statement not covered" > console.error('Error stopping selector:', error);</span>
}
});
&nbsp;
// Check current state
<span class="cstat-no" title="statement not covered" > checkSelectorState();</span>
&nbsp;
// Handle tooltip keyboard navigation
<span class="cstat-no" title="statement not covered" > setupTooltipAccessibility();</span>
&nbsp;
function <span class="fstat-no" title="function not covered" >toggleButtons(</span>isActive) {
<span class="cstat-no" title="statement not covered" > if (isActive) {</span>
<span class="cstat-no" title="statement not covered" > startBtn.style.display = 'none';</span>
<span class="cstat-no" title="statement not covered" > stopBtn.style.display = 'block';</span>
} else {
<span class="cstat-no" title="statement not covered" > startBtn.style.display = 'block';</span>
<span class="cstat-no" title="statement not covered" > stopBtn.style.display = 'none';</span>
}
}
&nbsp;
function <span class="fstat-no" title="function not covered" >showStatus(</span>message, type = <span class="branch-0 cbranch-no" title="branch not covered" >'success')</span> {
<span class="cstat-no" title="statement not covered" > status.textContent = message;</span>
<span class="cstat-no" title="statement not covered" > status.className = `status ${type}`;</span>
<span class="cstat-no" title="statement not covered" > status.style.display = 'block';</span>
&nbsp;
<span class="cstat-no" title="statement not covered" > setTimeout(<span class="fstat-no" title="function not covered" >()</span> =&gt; {</span>
<span class="cstat-no" title="statement not covered" > status.style.display = 'none';</span>
}, 3000);
}
&nbsp;
async function <span class="fstat-no" title="function not covered" >checkSelectorState(</span>) {
const [tab] = <span class="cstat-no" title="statement not covered" >await chrome.tabs.query({ active: true, currentWindow: true });</span>
&nbsp;
// Skip check for incompatible pages
<span class="cstat-no" title="statement not covered" > if (tab.url.startsWith('chrome://') ||</span>
tab.url.startsWith('chrome-extension://') ||
tab.url.startsWith('edge://') ||
tab.url.startsWith('about:')) {
<span class="cstat-no" title="statement not covered" > return;</span>
}
&nbsp;
<span class="cstat-no" title="statement not covered" > try {</span>
const response = <span class="cstat-no" title="statement not covered" >await chrome.tabs.sendMessage(tab.id, { action: 'checkState' });</span>
<span class="cstat-no" title="statement not covered" > if (response &amp;&amp; response.isActive) {</span>
<span class="cstat-no" title="statement not covered" > toggleButtons(true);</span>
<span class="cstat-no" title="statement not covered" > showStatus('Selector is currently active', 'success');</span>
}
} catch (error) {
// Content script not ready or selector not active
<span class="cstat-no" title="statement not covered" > console.log('Content script not ready or selector inactive:', error.message);</span>
}
}
&nbsp;
function <span class="fstat-no" title="function not covered" >setupTooltipAccessibility(</span>) {
const tooltipIcon = <span class="cstat-no" title="statement not covered" >document.querySelector('.tooltip-icon');</span>
const tooltipContent = <span class="cstat-no" title="statement not covered" >document.querySelector('.tooltip-content');</span>
<span class="cstat-no" title="statement not covered" > if (!tooltipIcon || !tooltipContent) <span class="cstat-no" title="statement not covered" >return;</span></span>
&nbsp;
// Handle keyboard events for tooltip
<span class="cstat-no" title="statement not covered" > tooltipIcon.addEventListener('keydown', <span class="fstat-no" title="function not covered" >(e</span>) =&gt; {</span>
<span class="cstat-no" title="statement not covered" > if (e.key === 'Enter' || e.key === ' ') {</span>
<span class="cstat-no" title="statement not covered" > e.preventDefault();</span>
// Toggle tooltip visibility on Enter/Space
const isVisible = <span class="cstat-no" title="statement not covered" >tooltipContent.style.visibility === 'visible';</span>
<span class="cstat-no" title="statement not covered" > tooltipContent.style.visibility = isVisible ? 'hidden' : 'visible';</span>
<span class="cstat-no" title="statement not covered" > tooltipContent.style.opacity = isVisible ? '0' : '1';</span>
} else <span class="cstat-no" title="statement not covered" >if (e.key === 'Escape') {</span>
// Hide tooltip on Escape
<span class="cstat-no" title="statement not covered" > tooltipContent.style.visibility = 'hidden';</span>
<span class="cstat-no" title="statement not covered" > tooltipContent.style.opacity = '0';</span>
}
});
&nbsp;
// Hide tooltip when clicking outside
<span class="cstat-no" title="statement not covered" > document.addEventListener('click', <span class="fstat-no" title="function not covered" >(e</span>) =&gt; {</span>
<span class="cstat-no" title="statement not covered" > if (!tooltipIcon.contains(e.target)) {</span>
<span class="cstat-no" title="statement not covered" > tooltipContent.style.visibility = 'hidden';</span>
<span class="cstat-no" title="statement not covered" > tooltipContent.style.opacity = '0';</span>
}
});
&nbsp;
// Handle focus loss
<span class="cstat-no" title="statement not covered" > tooltipIcon.addEventListener('blur', <span class="fstat-no" title="function not covered" >(e</span>) =&gt; {</span>
// Small delay to allow for focus to move to tooltip content if needed
<span class="cstat-no" title="statement not covered" > setTimeout(<span class="fstat-no" title="function not covered" >()</span> =&gt; {</span>
<span class="cstat-no" title="statement not covered" > if (!tooltipIcon.matches(':focus-within')) {</span>
<span class="cstat-no" title="statement not covered" > tooltipContent.style.visibility = 'hidden';</span>
<span class="cstat-no" title="statement not covered" > tooltipContent.style.opacity = '0';</span>
}
}, 100);
});
}
});
&nbsp;
// Listen for messages from content script
<span class="cstat-no" title="statement not covered" >chrome.runtime.onMessage.addListener(<span class="fstat-no" title="function not covered" >(m</span>essage, sender, sendResponse) =&gt; {</span>
<span class="cstat-no" title="statement not covered" > if (message.action === 'selectorStopped') {</span>
const startBtn = <span class="cstat-no" title="statement not covered" >document.getElementById('start-selector');</span>
const stopBtn = <span class="cstat-no" title="statement not covered" >document.getElementById('stop-selector');</span>
const status = <span class="cstat-no" title="statement not covered" >document.getElementById('status');</span>
&nbsp;
<span class="cstat-no" title="statement not covered" > startBtn.style.display = 'block';</span>
<span class="cstat-no" title="statement not covered" > stopBtn.style.display = 'none';</span>
&nbsp;
<span class="cstat-no" title="statement not covered" > if (message.reason === 'screenshot-taken') {</span>
<span class="cstat-no" title="statement not covered" > status.textContent = 'Screenshot captured!';</span>
<span class="cstat-no" title="statement not covered" > status.className = 'status success';</span>
<span class="cstat-no" title="statement not covered" > status.style.display = 'block';</span>
<span class="cstat-no" title="statement not covered" > setTimeout(<span class="fstat-no" title="function not covered" >()</span> =&gt; <span class="cstat-no" title="statement not covered" >status.style.display = 'none',</span> 2000);</span>
}
}
});</pre></td></tr></table></pre>
<div class='push'></div><!-- for sticky footer -->
</div><!-- /wrapper -->
<div class='footer quiet pad2 space-top1 center small'>
Code coverage generated by
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
at 2025-08-13T15:07:03.182Z
</div>
<script src="prettify.js"></script>
<script>
window.onload = function () {
prettyPrint();
};
</script>
<script src="sorter.js"></script>
<script src="block-navigation.js"></script>
</body>
</html>

View file

@ -1 +0,0 @@
.pln{color:#000}@media screen{.str{color:#080}.kwd{color:#008}.com{color:#800}.typ{color:#606}.lit{color:#066}.pun,.opn,.clo{color:#660}.tag{color:#008}.atn{color:#606}.atv{color:#080}.dec,.var{color:#606}.fun{color:red}}@media print,projection{.str{color:#060}.kwd{color:#006;font-weight:bold}.com{color:#600;font-style:italic}.typ{color:#404;font-weight:bold}.lit{color:#044}.pun,.opn,.clo{color:#440}.tag{color:#006;font-weight:bold}.atn{color:#404}.atv{color:#060}}pre.prettyprint{padding:2px;border:1px solid #888}ol.linenums{margin-top:0;margin-bottom:0}li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8{list-style-type:none}li.L1,li.L3,li.L5,li.L7,li.L9{background:#eee}

File diff suppressed because one or more lines are too long

Binary file not shown.

Before

Width:  |  Height:  |  Size: 138 B

View file

@ -1,196 +0,0 @@
/* eslint-disable */
var addSorting = (function() {
'use strict';
var cols,
currentSort = {
index: 0,
desc: false
};
// returns the summary table element
function getTable() {
return document.querySelector('.coverage-summary');
}
// returns the thead element of the summary table
function getTableHeader() {
return getTable().querySelector('thead tr');
}
// returns the tbody element of the summary table
function getTableBody() {
return getTable().querySelector('tbody');
}
// returns the th element for nth column
function getNthColumn(n) {
return getTableHeader().querySelectorAll('th')[n];
}
function onFilterInput() {
const searchValue = document.getElementById('fileSearch').value;
const rows = document.getElementsByTagName('tbody')[0].children;
for (let i = 0; i < rows.length; i++) {
const row = rows[i];
if (
row.textContent
.toLowerCase()
.includes(searchValue.toLowerCase())
) {
row.style.display = '';
} else {
row.style.display = 'none';
}
}
}
// loads the search box
function addSearchBox() {
var template = document.getElementById('filterTemplate');
var templateClone = template.content.cloneNode(true);
templateClone.getElementById('fileSearch').oninput = onFilterInput;
template.parentElement.appendChild(templateClone);
}
// loads all columns
function loadColumns() {
var colNodes = getTableHeader().querySelectorAll('th'),
colNode,
cols = [],
col,
i;
for (i = 0; i < colNodes.length; i += 1) {
colNode = colNodes[i];
col = {
key: colNode.getAttribute('data-col'),
sortable: !colNode.getAttribute('data-nosort'),
type: colNode.getAttribute('data-type') || 'string'
};
cols.push(col);
if (col.sortable) {
col.defaultDescSort = col.type === 'number';
colNode.innerHTML =
colNode.innerHTML + '<span class="sorter"></span>';
}
}
return cols;
}
// attaches a data attribute to every tr element with an object
// of data values keyed by column name
function loadRowData(tableRow) {
var tableCols = tableRow.querySelectorAll('td'),
colNode,
col,
data = {},
i,
val;
for (i = 0; i < tableCols.length; i += 1) {
colNode = tableCols[i];
col = cols[i];
val = colNode.getAttribute('data-value');
if (col.type === 'number') {
val = Number(val);
}
data[col.key] = val;
}
return data;
}
// loads all row data
function loadData() {
var rows = getTableBody().querySelectorAll('tr'),
i;
for (i = 0; i < rows.length; i += 1) {
rows[i].data = loadRowData(rows[i]);
}
}
// sorts the table using the data for the ith column
function sortByIndex(index, desc) {
var key = cols[index].key,
sorter = function(a, b) {
a = a.data[key];
b = b.data[key];
return a < b ? -1 : a > b ? 1 : 0;
},
finalSorter = sorter,
tableBody = document.querySelector('.coverage-summary tbody'),
rowNodes = tableBody.querySelectorAll('tr'),
rows = [],
i;
if (desc) {
finalSorter = function(a, b) {
return -1 * sorter(a, b);
};
}
for (i = 0; i < rowNodes.length; i += 1) {
rows.push(rowNodes[i]);
tableBody.removeChild(rowNodes[i]);
}
rows.sort(finalSorter);
for (i = 0; i < rows.length; i += 1) {
tableBody.appendChild(rows[i]);
}
}
// removes sort indicators for current column being sorted
function removeSortIndicators() {
var col = getNthColumn(currentSort.index),
cls = col.className;
cls = cls.replace(/ sorted$/, '').replace(/ sorted-desc$/, '');
col.className = cls;
}
// adds sort indicators for current column being sorted
function addSortIndicators() {
getNthColumn(currentSort.index).className += currentSort.desc
? ' sorted-desc'
: ' sorted';
}
// adds event listeners for all sorter widgets
function enableUI() {
var i,
el,
ithSorter = function ithSorter(i) {
var col = cols[i];
return function() {
var desc = col.defaultDescSort;
if (currentSort.index === i) {
desc = !currentSort.desc;
}
sortByIndex(i, desc);
removeSortIndicators();
currentSort.index = i;
currentSort.desc = desc;
addSortIndicators();
};
};
for (i = 0; i < cols.length; i += 1) {
if (cols[i].sortable) {
// add the click event handler on the th so users
// dont have to click on those tiny arrows
el = getNthColumn(i).querySelector('.sorter').parentElement;
if (el.addEventListener) {
el.addEventListener('click', ithSorter(i));
} else {
el.attachEvent('onclick', ithSorter(i));
}
}
}
}
// adds sorting functionality to the UI
return function() {
if (!getTable()) {
return;
}
cols = loadColumns();
loadData();
addSearchBox();
addSortIndicators();
enableUI();
};
})();
window.addEventListener('load', addSorting);