Added tab-content-service base class
This commit is contained in:
parent
12da6f7776
commit
3cc3652275
54
content.js
54
content.js
@ -2,7 +2,8 @@ class MessagingService {
|
||||
|
||||
async GetHyperlinkNodes(sender, callback) {
|
||||
const a = this;
|
||||
const nodes = await document.body.getElementsByTagName("a");
|
||||
const nodes = await document.querySelectorAll("a");
|
||||
|
||||
let result = [];
|
||||
|
||||
for (let i=0; i<nodes.length; i++) {
|
||||
@ -18,16 +19,13 @@ class MessagingService {
|
||||
});
|
||||
}
|
||||
|
||||
// for (let i=0; i<result.length; i++) {
|
||||
// result[i].occurrence = result.filter(item => JSON.stringify(item) === JSON.stringify(result[i])).length;
|
||||
// }
|
||||
|
||||
await callback(result);
|
||||
}
|
||||
|
||||
async GetImageNodes(sender, callback) {
|
||||
const a = this;
|
||||
const nodes = await document.body.getElementsByTagName("img");
|
||||
const nodes = await document.querySelectorAll("img");
|
||||
|
||||
let result = [];
|
||||
|
||||
for (let i=0; i<nodes.length; i++) {
|
||||
@ -49,6 +47,41 @@ class MessagingService {
|
||||
callback(document.location.href);
|
||||
}
|
||||
|
||||
async GetMetaNodes(sender, callback) {
|
||||
const a = this;
|
||||
const nodes = await document.querySelectorAll("meta");
|
||||
|
||||
let result = [];
|
||||
|
||||
for (let i=0; i<nodes.length; i++) {
|
||||
result.push({
|
||||
content: (nodes[i].getAttribute("content") ?? ""),
|
||||
name: (nodes[i].getAttribute("name") ?? ""),
|
||||
httpEquiv: (nodes[i].getAttribute("http-equiv") ?? ""),
|
||||
occurrence: 1
|
||||
});
|
||||
}
|
||||
|
||||
await callback(result);
|
||||
}
|
||||
|
||||
async GetScriptNodes(sender, callback) {
|
||||
const a = this;
|
||||
const nodes = await document.querySelectorAll("script");
|
||||
|
||||
let result = [];
|
||||
|
||||
for (let i=0; i<nodes.length; i++) {
|
||||
result.push({
|
||||
src: (nodes[i].getAttribute("src") ?? ""),
|
||||
type: (nodes[i].getAttribute("type") ?? ""),
|
||||
occurrence: 1
|
||||
});
|
||||
}
|
||||
|
||||
await callback(result);
|
||||
}
|
||||
|
||||
#encodeHtml(htmlContent) {
|
||||
const map = {
|
||||
"&": "&",
|
||||
@ -79,12 +112,3 @@ chrome.runtime.onMessage.addListener(async function(request, sender, callback) {
|
||||
await messageService[request.event](sender, callback);
|
||||
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
// var optHideWatchedVideos = new Promise(function(resolve) {
|
||||
// chrome.storage.local.get(['switch1'], function(result) {
|
||||
// resolve(result.switch1);
|
||||
// });
|
||||
// });
|
||||
|
File diff suppressed because one or more lines are too long
192
popup.html
192
popup.html
@ -21,12 +21,32 @@
|
||||
<button class="nav-link active" id="nav-home-tab" data-bs-toggle="tab" data-bs-target="#nav-home" type="button" role="tab" aria-controls="nav-home" aria-selected="true">Home</button>
|
||||
<button class="nav-link" id="nav-hyperlinks-tab" data-bs-toggle="tab" data-bs-target="#nav-hyperlinks" type="button" role="tab" aria-controls="nav-hyperlinks" aria-selected="false">Hyperlinks</button>
|
||||
<button class="nav-link" id="nav-images-tab" data-bs-toggle="tab" data-bs-target="#nav-images" type="button" role="tab" aria-controls="nav-images" aria-selected="false">Images</button>
|
||||
<button class="nav-link" id="nav-disabled-tab" data-bs-toggle="tab" data-bs-target="#nav-disabled" type="button" role="tab" aria-controls="nav-disabled" aria-selected="false" disabled>Disabled</button>
|
||||
<button class="nav-link" id="nav-scripts-tab" data-bs-toggle="tab" data-bs-target="#nav-scripts" type="button" role="tab" aria-controls="nav-scripts" aria-selected="false">Scripts</button>
|
||||
<button class="nav-link" id="nav-metas-tab" data-bs-toggle="tab" data-bs-target="#nav-metas" type="button" role="tab" aria-controls="nav-metas" aria-selected="false">Metas</button>
|
||||
</div>
|
||||
</nav>
|
||||
<div class="tab-content" id="nav-tabContent">
|
||||
<div class="tab-pane fade show active" id="nav-home" role="tabpanel" aria-labelledby="nav-home-tab" tabindex="0">...</div>
|
||||
<div class="tab-pane py-3 fade" id="nav-hyperlinks" role="tabpanel" aria-labelledby="nav-hyperlinks-tab" tabindex="0">
|
||||
<div class="tab-pane fade show active" id="nav-home" role="tabpanel" aria-labelledby="nav-home-tab" tabindex="0">
|
||||
|
||||
<div class="container-fluid py-4">
|
||||
<div class="row mb-2">
|
||||
<div class="col-sm-12">
|
||||
<img src="./icon128.png" class="mx-auto d-block" alt="Logo" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-12 text-center">
|
||||
<h3>Peji Inspektor</h3>
|
||||
<p>
|
||||
Peji Inspektor is a browser extension for finding nodes on a web page.
|
||||
These nodes (or tags) can be filtered and searched to find hyperlinks, images and other assets.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="tab-pane py-3 fade" id="nav-hyperlinks" role="tabpanel" aria-labelledby="nav-hyperlinks-tab" tabindex="1">
|
||||
|
||||
<div class="container-fluid">
|
||||
<div class="pt-2 pb-2 mb-2 border-bottom">
|
||||
@ -34,11 +54,11 @@
|
||||
<label for="textBox1" class="col-sm-2 col-form-label fw-bold">Search</label>
|
||||
<div class="col-sm-10">
|
||||
<div class="input-group input-group-sm">
|
||||
<input type="text" class="form-control" role="textbox" id="textBox1" />
|
||||
<input type="text" class="form-control" id="textBox1" />
|
||||
|
||||
<select class="form-select pe-0 input-group-text" name="comboBox1">
|
||||
<option value="anchor">Anchor</option>
|
||||
<option value="link" selected>Link</option>
|
||||
<select class="form-select pe-0 input-group-text">
|
||||
<option value="text">Anchor</option>
|
||||
<option value="href" selected>Link</option>
|
||||
</select>
|
||||
|
||||
<button type="button" class="btn btn-secondary input-group-text">✕</button>
|
||||
@ -50,7 +70,7 @@
|
||||
<div class="col-5">
|
||||
<div class="input-group input-group-sm">
|
||||
<button class="btn btn-primary" type="button">Load Results</button>
|
||||
<select class="form-select" name="comboBox2">
|
||||
<select class="form-select">
|
||||
<option value="table" selected>Table</option>
|
||||
<option value="csv">CSV</option>
|
||||
<option value="links">Links</option>
|
||||
@ -82,22 +102,13 @@
|
||||
<div class="row pb-2 mb-2 border-bottom"></div>
|
||||
|
||||
<div class="row pt-2 mb-2">
|
||||
<div class="col px-0">
|
||||
|
||||
<table class="table table-bordered table-hover table-sm table-striped">
|
||||
<thead></thead>
|
||||
<tbody></tbody>
|
||||
</table>
|
||||
|
||||
<textarea class="form-control font-monospace text-sm px-1 py-1" rows="16"></textarea>
|
||||
|
||||
</div>
|
||||
<div class="col px-0" role="results"></div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="tab-pane fade" id="nav-images" role="tabpanel" aria-labelledby="nav-images-tab" tabindex="0">
|
||||
<div class="tab-pane py-3 fade" id="nav-images" role="tabpanel" aria-labelledby="nav-images-tab" tabindex="2">
|
||||
|
||||
<div class="container-fluid">
|
||||
<div class="pt-2 pb-2 mb-2 border-bottom">
|
||||
@ -105,9 +116,9 @@
|
||||
<label for="textBox2" class="col-sm-2 col-form-label fw-bold">Search</label>
|
||||
<div class="col-sm-10">
|
||||
<div class="input-group input-group-sm">
|
||||
<input type="text" class="form-control" role="textbox" id="textBox2" />
|
||||
<input type="text" class="form-control" id="textBox2" />
|
||||
|
||||
<select class="form-select pe-0 input-group-text" name="comboBox1">
|
||||
<select class="form-select pe-0 input-group-text">
|
||||
<option value="alt">Alternative Text</option>
|
||||
<option value="src" selected>Source</option>
|
||||
</select>
|
||||
@ -121,7 +132,7 @@
|
||||
<div class="col-5">
|
||||
<div class="input-group input-group-sm">
|
||||
<button class="btn btn-primary" type="button">Load Results</button>
|
||||
<select class="form-select" name="comboBox2">
|
||||
<select class="form-select">
|
||||
<option value="table" selected>Table</option>
|
||||
<option value="csv">CSV</option>
|
||||
<option value="links">Links</option>
|
||||
@ -153,22 +164,137 @@
|
||||
<div class="row pb-2 mb-2 border-bottom"></div>
|
||||
|
||||
<div class="row pt-2 mb-2">
|
||||
<div class="col px-0">
|
||||
|
||||
<table class="table table-bordered table-hover table-sm table-striped">
|
||||
<thead></thead>
|
||||
<tbody></tbody>
|
||||
</table>
|
||||
|
||||
<textarea class="form-control font-monospace text-sm px-1 py-1" rows="16"></textarea>
|
||||
|
||||
</div>
|
||||
<div class="col px-0"role="results"></div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="tab-pane fade" id="nav-disabled" role="tabpanel" aria-labelledby="nav-disabled-tab" tabindex="0">...</div>
|
||||
<div class="tab-pane py-3 fade" id="nav-scripts" role="tabpanel" aria-labelledby="nav-scripts-tab" tabindex="3">
|
||||
|
||||
<div class="container-fluid">
|
||||
<div class="pt-2 pb-2 mb-2 border-bottom">
|
||||
<div class="row mb-2">
|
||||
<label for="textBox3" class="col-sm-2 col-form-label fw-bold">Search</label>
|
||||
<div class="col-sm-10">
|
||||
<div class="input-group input-group-sm">
|
||||
<input type="text" class="form-control" id="textBox3" />
|
||||
|
||||
<select class="form-select pe-0 input-group-text">
|
||||
<option value="type">Type</option>
|
||||
<option value="src" selected>Source</option>
|
||||
</select>
|
||||
|
||||
<button type="button" class="btn btn-secondary input-group-text">✕</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mt-2 mb-2">
|
||||
<div class="col-2"></div>
|
||||
<div class="col-5">
|
||||
<div class="input-group input-group-sm">
|
||||
<button class="btn btn-primary" type="button">Load Results</button>
|
||||
<select class="form-select">
|
||||
<option value="table" selected>Table</option>
|
||||
<option value="csv">CSV</option>
|
||||
<option value="links">Links</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-5 px-0">
|
||||
<div class="pt-2" role="label"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="fw-bold clearfix cursor-pointer" data-bs-toggle="collapse" data-bs-target="#collapsPanel5" aria-expanded="false" aria-controls="collapsPanel5">⯈ Options</div>
|
||||
<div class="row pb-2 mb-2 border-bottom collapse" id="collapsPanel5">
|
||||
<div class="col-sm-2"></div>
|
||||
<div class="col-sm-10">
|
||||
<div class="row px-0" role="options"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="fw-bold clearfix cursor-pointer" data-bs-toggle="collapse" data-bs-target="#collapsPanel6" aria-expanded="false" aria-controls="collapsPanel6">⯈ Filters</div>
|
||||
<div class="row collapse" id="collapsPanel6">
|
||||
<div class="col-sm-2"></div>
|
||||
<div class="col-sm-10">
|
||||
<div class="row px-0" role="filters"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row pb-2 mb-2 border-bottom"></div>
|
||||
|
||||
<div class="row pt-2 mb-2">
|
||||
<div class="col px-0"role="results"></div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="tab-pane py-3 fade" id="nav-metas" role="tabpanel" aria-labelledby="nav-metas-tab" tabindex="3">
|
||||
|
||||
<div class="container-fluid">
|
||||
<div class="pt-2 pb-2 mb-2 border-bottom">
|
||||
<div class="row mb-2">
|
||||
<label for="textBox3" class="col-sm-2 col-form-label fw-bold">Search</label>
|
||||
<div class="col-sm-10">
|
||||
<div class="input-group input-group-sm">
|
||||
<input type="text" class="form-control" id="textBox3" />
|
||||
|
||||
<select class="form-select pe-0 input-group-text">
|
||||
<option value="content">Content</option>
|
||||
<option value="name" selected>Name</option>
|
||||
</select>
|
||||
|
||||
<button type="button" class="btn btn-secondary input-group-text">✕</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mt-2 mb-2">
|
||||
<div class="col-2"></div>
|
||||
<div class="col-5">
|
||||
<div class="input-group input-group-sm">
|
||||
<button type="button" class="btn btn-primary">Load Results</button>
|
||||
<select class="form-select">
|
||||
<option value="table" selected>Table</option>
|
||||
<option value="csv">CSV</option>
|
||||
<option value="links">Links</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-5 px-0">
|
||||
<div class="pt-2" role="label"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="fw-bold clearfix cursor-pointer" data-bs-toggle="collapse" data-bs-target="#collapsPanel7" aria-expanded="false" aria-controls="collapsPanel7">⯈ Options</div>
|
||||
<div class="row pb-2 mb-2 border-bottom collapse" id="collapsPanel7">
|
||||
<div class="col-sm-2"></div>
|
||||
<div class="col-sm-10">
|
||||
<div class="row px-0" role="options"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="fw-bold clearfix cursor-pointer" data-bs-toggle="collapse" data-bs-target="#collapsPanel8" aria-expanded="false" aria-controls="collapsPanel8">⯈ Filters</div>
|
||||
<div class="row collapse" id="collapsPanel8">
|
||||
<div class="col-sm-2"></div>
|
||||
<div class="col-sm-10">
|
||||
<div class="row px-0" role="filters"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row pb-2 mb-2 border-bottom"></div>
|
||||
|
||||
<div class="row pt-2 mb-2">
|
||||
<div class="col px-0"role="results"></div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
@ -1,17 +1,23 @@
|
||||
// src/popup.js
|
||||
import PopupService from './popup/popup-service.js';
|
||||
import AContentService from './popup/acontent-service.js';
|
||||
import ImgContentService from './popup/imgcontent-service.js';
|
||||
import AContentService from './popup/a-content-service.js';
|
||||
import ImgContentService from './popup/img-content-service.js';
|
||||
import ScriptContentService from './popup/script-content-service.js';
|
||||
import MetaContentService from './popup/meta-content-service.js';
|
||||
|
||||
|
||||
const popupService = new PopupService();
|
||||
const aContentService = new AContentService(popupService);
|
||||
const imgContentService = new ImgContentService(popupService);
|
||||
const scriptContentService = new ScriptContentService(popupService);
|
||||
const metaContentService = new MetaContentService(popupService);
|
||||
|
||||
|
||||
document.addEventListener("DOMContentLoaded", async function(event) {
|
||||
document.addEventListener("DOMContentLoaded", function(event) {
|
||||
|
||||
aContentService.InitialiseComponents();
|
||||
imgContentService.InitialiseComponents();
|
||||
scriptContentService.InitialiseComponents();
|
||||
metaContentService.InitialiseComponents();
|
||||
|
||||
});
|
280
src/src/popup/a-content-service.js
Normal file
280
src/src/popup/a-content-service.js
Normal file
@ -0,0 +1,280 @@
|
||||
import '../../../literyz-js/extensions.dist.js';
|
||||
|
||||
import TabContentService from './tab-content-service.js';
|
||||
|
||||
|
||||
class AContentService extends TabContentService {
|
||||
|
||||
constructor(popupService) {
|
||||
super(popupService);
|
||||
|
||||
const a = this;
|
||||
|
||||
a._containerId = "nav-hyperlinks";
|
||||
a._optionsCol1 = [
|
||||
{ id: 1, text: "Show Anchor as HTML", checked: false },
|
||||
{ id: 4, text: "Resolve Relative URL", checked: false }
|
||||
];
|
||||
a._optionsCol2 = [
|
||||
{ id: 3, text: "Sort By Anchor Text", checked: true },
|
||||
{ id: 2, text: "Trim Anchor Text", checked: true }
|
||||
];
|
||||
a._filtersCol1 = [
|
||||
{ id: 12, text: "Hide External Links", checked: true },
|
||||
{ id: 5, text: "Hide Duplicates", checked: true },
|
||||
{ id: 14, text: "Hide Blank Anchors", checked: true },
|
||||
{ id: 15, text: "Hide Blank Links", checked: true },
|
||||
{ id: 11, text: "Hide Fragments", checked: true },
|
||||
{ id: 13, text: "Hide Mailto/Tel", checked: true },
|
||||
{ id: 16, text: "Hide Javascript", checked: true }
|
||||
];
|
||||
a._filtersCol2 = [
|
||||
{ id: 6, text: "Show Title", checked: true },
|
||||
{ id: 7, text: "Show Target", checked: false },
|
||||
{ id: 8, text: "Show Rel", checked: false },
|
||||
{ id: 9, text: "Show Type", checked: false },
|
||||
{ id: 10, text: "Show Count", checked: false }
|
||||
];
|
||||
|
||||
}
|
||||
|
||||
async _retrieveResult() {
|
||||
return await this._popupService.GetHyperlinks();
|
||||
}
|
||||
|
||||
async _filterResult(items) {
|
||||
const a = this;
|
||||
const currentUrl = await a._popupService.GetLocation();
|
||||
const currentHostname = (new URL(currentUrl)).hostname;
|
||||
|
||||
let result = [];
|
||||
|
||||
for (let i=0; i<items.length; i++) {
|
||||
const item = items[i];
|
||||
|
||||
// Hide fragments
|
||||
if (a._getCheckBox(11)) {
|
||||
if (item.href.startsWith("#")) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Hide Blank Links
|
||||
if (a._getCheckBox(15)) {
|
||||
if (String.isNullOrWhitespace(item.href)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Hide mailto/tel
|
||||
if (a._getCheckBox(13)) {
|
||||
if (item.href.toLowerCase().startsWith("telno:") || item.href.toLowerCase().startsWith("mailto:")) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Hide javascript
|
||||
if (a._getCheckBox(16)) {
|
||||
if (item.href.toLowerCase().startsWith("javascript:")) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
const absoluteUrl = new URL(item.href, currentUrl);
|
||||
|
||||
// Hide external links
|
||||
if (a._getCheckBox(12)) {
|
||||
if (currentHostname != absoluteUrl.hostname) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Show anchor as html
|
||||
let text = (a._getCheckBox(1) ? item.innerHTML : item.innerText);
|
||||
|
||||
// Hide Blank Anchors
|
||||
if (a._getCheckBox(14)) {
|
||||
if (String.isNullOrWhitespace(text)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Resolve relative url
|
||||
const href = (a._getCheckBox(4) ? absoluteUrl.href : item.href);
|
||||
|
||||
// Trim anchor text
|
||||
if (a._getCheckBox(2)) {
|
||||
text = text.trim();
|
||||
}
|
||||
|
||||
// Search term
|
||||
if (!String.isNullOrWhitespace(a._textBox1.value)) {
|
||||
if (a._getComboBox(1) == "href") {
|
||||
if (!href.toLowerCase().includes(a._textBox1.value.toLowerCase())) {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
if (!text.toLowerCase().includes(a._textBox1.value.toLowerCase())) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result.push({
|
||||
text: text,
|
||||
href: href,
|
||||
title: (a._getCheckBox(6) ? item.title : ""),
|
||||
target: (a._getCheckBox(7) ? item.target : ""),
|
||||
rel: (a._getCheckBox(8) ? item.rel : ""),
|
||||
type: (a._getCheckBox(9) ? item.type : ""),
|
||||
occurrence: ""
|
||||
});
|
||||
}
|
||||
|
||||
// Show occurrence
|
||||
if (a._getCheckBox(10)) {
|
||||
// Calc occurrences, store in cache
|
||||
let occurrenceCache = [];
|
||||
for (let i=0; i<result.length; i++) {
|
||||
const occurrence = result.filter(item => JSON.stringify(item) === JSON.stringify(result[i])).length;
|
||||
|
||||
occurrenceCache.push(occurrence);
|
||||
}
|
||||
|
||||
// Update result with occurrence
|
||||
for (let i=0; i<result.length; i++) {
|
||||
result[i].occurrence = occurrenceCache[i];
|
||||
}
|
||||
}
|
||||
|
||||
// Hide duplicates
|
||||
if (a._getCheckBox(5)) {
|
||||
result = result.distinct();
|
||||
}
|
||||
|
||||
// Sort by anchor text
|
||||
if (a._getCheckBox(3)) {
|
||||
result = result.orderBy("text");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
_renderTable(results) {
|
||||
const a = this;
|
||||
const table = a._generateTable();
|
||||
|
||||
a._setHtml(a._panel3, table);
|
||||
|
||||
const thead = a._panel3.querySelectorAll("thead")[0];
|
||||
const tbody = a._panel3.querySelectorAll("tbody")[0];
|
||||
|
||||
// Write thead
|
||||
thead.innerHTML = "<tr>" + a.#generateTableHeader() + "</tr>";
|
||||
|
||||
// Write tbody
|
||||
for (let i=0; i<results.length; i++) {
|
||||
const item = results[i];
|
||||
|
||||
let row = [ item.text, item.href ];
|
||||
|
||||
if (a._getCheckBox(6)) {
|
||||
row.push(item.title);
|
||||
}
|
||||
|
||||
if (a._getCheckBox(7)) {
|
||||
row.push(item.target);
|
||||
}
|
||||
|
||||
if (a._getCheckBox(8)) {
|
||||
row.push(item.rel);
|
||||
}
|
||||
|
||||
if (a._getCheckBox(9)) {
|
||||
row.push(item.type);
|
||||
}
|
||||
|
||||
if (a._getCheckBox(10)) {
|
||||
row.push(item.occurrence);
|
||||
}
|
||||
|
||||
tbody.innerHTML += a.GenerateRow(row);
|
||||
}
|
||||
}
|
||||
|
||||
_renderCSV(results) {
|
||||
const a = this;
|
||||
const textarea = a._generateTextarea();
|
||||
|
||||
a._setHtml(a._panel3, textarea);
|
||||
|
||||
const tbody = a._panel3.querySelectorAll("textarea")[0];
|
||||
|
||||
for (let i=0; i<results.length; i++) {
|
||||
const item = results[i];
|
||||
|
||||
let row = [ item.text, item.href ];
|
||||
|
||||
if (a._getCheckBox(6)) {
|
||||
row.push(item.title);
|
||||
}
|
||||
|
||||
if (a._getCheckBox(7)) {
|
||||
row.push(item.target);
|
||||
}
|
||||
|
||||
if (a._getCheckBox(8)) {
|
||||
row.push(item.rel);
|
||||
}
|
||||
|
||||
if (a._getCheckBox(9)) {
|
||||
row.push(item.type);
|
||||
}
|
||||
|
||||
if (a._getCheckBox(10)) {
|
||||
row.push(item.occurrence);
|
||||
}
|
||||
|
||||
tbody.value += a.GenerateCSVLine("\t", row);
|
||||
tbody.value += "\n";
|
||||
}
|
||||
}
|
||||
|
||||
_renderLinks(results) {
|
||||
const a = this;
|
||||
const textarea = a._generateTextarea();
|
||||
|
||||
a._setHtml(a._panel3, textarea);
|
||||
|
||||
const tbody = a._panel3.querySelectorAll("textarea")[0];
|
||||
|
||||
for (let i=0; i<results.length; i++) {
|
||||
const item = results[i];
|
||||
|
||||
tbody.value += a.GenerateCSVLine("\t", [ item.href ]);
|
||||
tbody.value += "\n";
|
||||
}
|
||||
}
|
||||
|
||||
#generateTableHeader() {
|
||||
const a = this;
|
||||
|
||||
const columns1 = [
|
||||
"Anchor Text",
|
||||
"Address"
|
||||
];
|
||||
const columns2 = [
|
||||
{ id: 6, name: "Title" },
|
||||
{ id: 7, name: "Target" },
|
||||
{ id: 8, name: "Rel" },
|
||||
{ id: 9, name: "Type" },
|
||||
{ id: 10, name: "Count" }
|
||||
];
|
||||
|
||||
return a._generateTableHeader(columns1, columns2);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
export default AContentService;
|
@ -1,502 +0,0 @@
|
||||
import '../../../literyz-js/extensions.dist.js';
|
||||
|
||||
import ContentService from './content-service.js';
|
||||
|
||||
|
||||
class AContentService extends ContentService {
|
||||
#containerPanel = null;
|
||||
#popupService = null;
|
||||
|
||||
|
||||
constructor(popupService) {
|
||||
super();
|
||||
|
||||
this.#popupService = popupService;
|
||||
}
|
||||
|
||||
InitialiseComponents() {
|
||||
const a = this;
|
||||
|
||||
a.Clear();
|
||||
|
||||
a.#initialiseComponents_Options();
|
||||
a.#initialiseComponents_Filters();
|
||||
|
||||
a.Button1.addEventListener('click', async function (e) {
|
||||
a.Button2.disabled = true;
|
||||
|
||||
a.TextBox1.value = "";
|
||||
|
||||
await a.Search();
|
||||
|
||||
a.Button2.disabled = false;
|
||||
});
|
||||
|
||||
a.Button2.addEventListener('click', async function (e) {
|
||||
a.Button2.disabled = true;
|
||||
|
||||
await a.Search();
|
||||
|
||||
a.Button2.disabled = false;
|
||||
});
|
||||
}
|
||||
|
||||
#initialiseComponents_Options() {
|
||||
const a = this;
|
||||
|
||||
let col1 = "";
|
||||
col1 += a.GenerateCheckBox(1, "Show Anchor as HTML", false);
|
||||
col1 += a.GenerateCheckBox(4, "Resolve Relative URL", false);
|
||||
|
||||
let col2 = "";
|
||||
col2 += a.GenerateCheckBox(3, "Sort By Anchor Text", true);
|
||||
col2 += a.GenerateCheckBox(2, "Trim Anchor Text", true);
|
||||
|
||||
let html = a.GenerateCols(col1, col2);
|
||||
|
||||
a.SetHtml(a.Panel1, html);
|
||||
}
|
||||
|
||||
#initialiseComponents_Filters() {
|
||||
const a = this;
|
||||
|
||||
let col1 = "";
|
||||
col1 += a.GenerateCheckBox(12, "Hide External Links", true);
|
||||
col1 += a.GenerateCheckBox(5, "Hide Duplicates", true);
|
||||
col1 += a.GenerateCheckBox(14, "Hide Blank Anchors", true);
|
||||
col1 += a.GenerateCheckBox(15, "Hide Blank Links", true);
|
||||
col1 += a.GenerateCheckBox(11, "Hide Fragments", true);
|
||||
col1 += a.GenerateCheckBox(13, "Hide Mailto/Tel", true);
|
||||
col1 += a.GenerateCheckBox(16, "Hide Javascript", true);
|
||||
|
||||
let col2 = "";
|
||||
col2 += a.GenerateCheckBox(6, "Show Title", true);
|
||||
col2 += a.GenerateCheckBox(7, "Show Target", false);
|
||||
col2 += a.GenerateCheckBox(8, "Show Rel", false);
|
||||
col2 += a.GenerateCheckBox(9, "Show Type", false);
|
||||
col2 += a.GenerateCheckBox(10, "Show Count", false);
|
||||
|
||||
let html = a.GenerateCols(col1, col2);
|
||||
|
||||
a.SetHtml(a.Panel2, html);
|
||||
}
|
||||
|
||||
|
||||
get Button1() {
|
||||
const a = this;
|
||||
|
||||
if (a.Container == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return a.Container.querySelectorAll("button")[0];
|
||||
}
|
||||
|
||||
get Button2() {
|
||||
const a = this;
|
||||
|
||||
if (a.Container == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return a.Container.querySelectorAll("button")[1];
|
||||
}
|
||||
|
||||
get Container() {
|
||||
const a = this;
|
||||
|
||||
if (a.#containerPanel == null) {
|
||||
a.#containerPanel = document.getElementById("nav-hyperlinks");
|
||||
}
|
||||
|
||||
return a.#containerPanel;
|
||||
}
|
||||
|
||||
get Label1() {
|
||||
const a = this;
|
||||
|
||||
if (a.Container == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return a.Container.querySelectorAll("[role='label']")[0];
|
||||
}
|
||||
|
||||
get MemoBox1() {
|
||||
const a = this;
|
||||
|
||||
if (a.Container == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return a.Container.querySelectorAll("textarea")[0];
|
||||
}
|
||||
|
||||
get Panel1() {
|
||||
const a = this;
|
||||
|
||||
if (a.Container == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return a.Container.querySelectorAll("div[role='options']")[0];
|
||||
}
|
||||
|
||||
get Panel2() {
|
||||
const a = this;
|
||||
|
||||
if (a.Container == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return a.Container.querySelectorAll("div[role='filters']")[0];
|
||||
}
|
||||
|
||||
get Table1() {
|
||||
const a = this;
|
||||
|
||||
if (a.Container == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return a.Container.querySelectorAll("table")[0];
|
||||
}
|
||||
|
||||
get TextBox1() {
|
||||
const a = this;
|
||||
|
||||
if (a.Container == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return a.Container.querySelectorAll("input[role='textbox']")[0];
|
||||
}
|
||||
|
||||
|
||||
Clear() {
|
||||
const a = this;
|
||||
|
||||
a.Table1.style.display = 'none';
|
||||
a.MemoBox1.style.display = 'none';
|
||||
|
||||
a.SetHtml(a.Panel1, "");
|
||||
a.SetHtml(a.Panel2, "");
|
||||
}
|
||||
|
||||
async Search() {
|
||||
const a = this;
|
||||
|
||||
a.Label1.innerText = "";
|
||||
|
||||
a.Table1.style.display = 'none';
|
||||
a.MemoBox1.style.display = 'none';
|
||||
|
||||
const result = await a.#popupService.GetHyperlinks();
|
||||
const totalCount = result.length;
|
||||
|
||||
const newResults = await a.#filterResult(result.copy());
|
||||
|
||||
if (newResults.length == totalCount) {
|
||||
a.Label1.innerText = "Showing " + totalCount + " result" + (totalCount == 1 ? "" : "s");
|
||||
} else {
|
||||
a.Label1.innerText = "Showing " + newResults.length + " of " + totalCount + " result" + (totalCount == 1 ? "" : "s");
|
||||
}
|
||||
|
||||
switch (a.#getComboBox(2)) {
|
||||
case "table":
|
||||
a.#renderTable(newResults);
|
||||
break;
|
||||
case "csv":
|
||||
a.#renderCSV(newResults);
|
||||
break;
|
||||
case "links":
|
||||
a.#renderLinks(newResults);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
async #filterResult(items) {
|
||||
const a = this;
|
||||
const currentUrl = await a.#popupService.GetLocation();
|
||||
const currentHostname = (new URL(currentUrl)).hostname;
|
||||
|
||||
let result = [];
|
||||
|
||||
for (let i=0; i<items.length; i++) {
|
||||
const item = items[i];
|
||||
|
||||
// Hide fragments
|
||||
if (a.#getCheckBox(11)) {
|
||||
if (item.href.startsWith("#")) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Hide blank links
|
||||
if (a.#getCheckBox(15)) {
|
||||
if (String.isNullOrWhitespace(item.href)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Hide mailto/tel
|
||||
if (a.#getCheckBox(13)) {
|
||||
if (item.href.toLowerCase().startsWith("telno:") || item.href.toLowerCase().startsWith("mailto:")) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Hide javascript
|
||||
if (a.#getCheckBox(16)) {
|
||||
if (item.href.toLowerCase().startsWith("javascript:")) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
const absoluteUrl = new URL(item.href, currentUrl);
|
||||
|
||||
// Hide external links
|
||||
if (a.#getCheckBox(12)) {
|
||||
if (currentHostname != absoluteUrl.hostname) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Show anchor as html
|
||||
let text = (a.#getCheckBox(1) ? item.innerHTML : item.innerText);
|
||||
|
||||
// Hide blank anchors
|
||||
if (a.#getCheckBox(14)) {
|
||||
if (String.isNullOrWhitespace(text)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Resolve relative url
|
||||
const href = (a.#getCheckBox(4) ? absoluteUrl.href : item.href);
|
||||
|
||||
// Trim anchor text
|
||||
if (a.#getCheckBox(2)) {
|
||||
text = text.trim();
|
||||
}
|
||||
|
||||
// Search term
|
||||
if (!String.isNullOrWhitespace(a.TextBox1.value)) {
|
||||
if (a.#getComboBox(1) == "anchor") {
|
||||
if (!text.toLowerCase().includes(a.TextBox1.value.toLowerCase())) {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
if (!href.toLowerCase().includes(a.TextBox1.value.toLowerCase())) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result.push({
|
||||
text: text,
|
||||
href: href,
|
||||
title: (a.#getCheckBox(6) ? item.title : ""),
|
||||
target: (a.#getCheckBox(7) ? item.target : ""),
|
||||
rel: (a.#getCheckBox(8) ? item.rel : ""),
|
||||
type: (a.#getCheckBox(9) ? item.type : ""),
|
||||
occurrence: ""
|
||||
});
|
||||
}
|
||||
|
||||
// Show occurrence
|
||||
if (a.#getCheckBox(10)) {
|
||||
// Calc occurrences, store in cache
|
||||
let occurrenceCache = [];
|
||||
for (let i=0; i<result.length; i++) {
|
||||
const occurrence = result.filter(item => JSON.stringify(item) === JSON.stringify(result[i])).length;
|
||||
|
||||
occurrenceCache.push(occurrence);
|
||||
}
|
||||
|
||||
// Update result with occurrence
|
||||
for (let i=0; i<result.length; i++) {
|
||||
result[i].occurrence = occurrenceCache[i];
|
||||
}
|
||||
}
|
||||
|
||||
// Hide duplicates
|
||||
if (a.#getCheckBox(5)) {
|
||||
result = result.distinct();
|
||||
}
|
||||
|
||||
// Sort by anchor text
|
||||
if (a.#getCheckBox(3)) {
|
||||
result = result.orderBy("text");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#generateTHeader() {
|
||||
const a = this;
|
||||
const columns = [
|
||||
{ id: 6, name: "Title" },
|
||||
{ id: 7, name: "Target" },
|
||||
{ id: 8, name: "Rel" },
|
||||
{ id: 9, name: "Type" },
|
||||
{ id: 10, name: "Count" }
|
||||
];
|
||||
|
||||
let html = "";
|
||||
html += "<th>Anchor Text</th>";
|
||||
html += "<th>Address</th>";
|
||||
|
||||
for (let i=0; i<columns.length; i++) {
|
||||
if (a.#getCheckBox(columns[i].id)) {
|
||||
html += "<th>" + columns[i].name + "</th>";
|
||||
}
|
||||
}
|
||||
|
||||
return html;
|
||||
}
|
||||
|
||||
#getCheckBox(num) {
|
||||
const a = this;
|
||||
|
||||
if (a.Container == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const result = a.Container.querySelectorAll("input[name='checkbox" + num + "']");
|
||||
if (result.length <= 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return result[0].checked;
|
||||
}
|
||||
|
||||
#getComboBox(num) {
|
||||
const a = this;
|
||||
|
||||
if (a.Container == null) {
|
||||
return "";
|
||||
}
|
||||
|
||||
const result = a.Container.querySelectorAll("select[name='comboBox" + num + "']");
|
||||
if (result.length <= 0) {
|
||||
return "";
|
||||
}
|
||||
|
||||
return result[0].value;
|
||||
}
|
||||
|
||||
#getRadioGroup(num) {
|
||||
const a = this;
|
||||
|
||||
if (a.Container == null) {
|
||||
return "";
|
||||
}
|
||||
|
||||
const result = a.Container.querySelectorAll("input[name='radioGroup" + num + "']:checked");
|
||||
if (result.length <= 0) {
|
||||
return "";
|
||||
}
|
||||
|
||||
return result[0].value;
|
||||
}
|
||||
|
||||
#renderTable(results) {
|
||||
const a = this;
|
||||
const thead = a.Table1.querySelectorAll("thead")[0];
|
||||
const tbody = a.Table1.querySelectorAll("tbody")[0];
|
||||
|
||||
thead.innerHTML = "";
|
||||
tbody.innerHTML = "";
|
||||
|
||||
a.Table1.style.display = 'table';
|
||||
|
||||
// Write thead
|
||||
thead.innerHTML = "<tr>" + a.#generateTHeader() + "</tr>";
|
||||
|
||||
// Write tbody
|
||||
for (let i=0; i<results.length; i++) {
|
||||
const item = results[i];
|
||||
|
||||
let row = [ item.text, item.href ];
|
||||
|
||||
if (a.#getCheckBox(6)) {
|
||||
row.push(item.title);
|
||||
}
|
||||
|
||||
if (a.#getCheckBox(7)) {
|
||||
row.push(item.target);
|
||||
}
|
||||
|
||||
if (a.#getCheckBox(8)) {
|
||||
row.push(item.rel);
|
||||
}
|
||||
|
||||
if (a.#getCheckBox(9)) {
|
||||
row.push(item.type);
|
||||
}
|
||||
|
||||
if (a.#getCheckBox(10)) {
|
||||
row.push(item.occurrence);
|
||||
}
|
||||
|
||||
tbody.innerHTML += a.GenerateRow(row);
|
||||
}
|
||||
}
|
||||
|
||||
#renderCSV(results) {
|
||||
const a = this;
|
||||
|
||||
a.MemoBox1.value = "";
|
||||
a.MemoBox1.style.display = 'inline-block';
|
||||
|
||||
for (let i=0; i<results.length; i++) {
|
||||
const item = results[i];
|
||||
|
||||
let row = [ item.text, item.href ];
|
||||
|
||||
if (a.#getCheckBox(6)) {
|
||||
row.push(item.title);
|
||||
}
|
||||
|
||||
if (a.#getCheckBox(7)) {
|
||||
row.push(item.target);
|
||||
}
|
||||
|
||||
if (a.#getCheckBox(8)) {
|
||||
row.push(item.rel);
|
||||
}
|
||||
|
||||
if (a.#getCheckBox(9)) {
|
||||
row.push(item.type);
|
||||
}
|
||||
|
||||
if (a.#getCheckBox(10)) {
|
||||
row.push(item.occurrence);
|
||||
}
|
||||
|
||||
a.MemoBox1.value += a.GenerateCSVLine("\t", row);
|
||||
a.MemoBox1.value += "\n";
|
||||
}
|
||||
}
|
||||
|
||||
#renderLinks(results) {
|
||||
const a = this;
|
||||
|
||||
a.MemoBox1.value = "";
|
||||
a.MemoBox1.style.display = 'inline-block';
|
||||
|
||||
for (let i=0; i<results.length; i++) {
|
||||
const item = results[i];
|
||||
|
||||
a.MemoBox1.value += a.GenerateCSVLine("\t", [ item.href ]);
|
||||
a.MemoBox1.value += "\n";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
export default AContentService;
|
@ -1,23 +1,68 @@
|
||||
// import '../references/extensions.dist.js';
|
||||
|
||||
class ContentService {
|
||||
_popupService = null;
|
||||
|
||||
GenerateCheckBox(num, label, checked) {
|
||||
let html = "";
|
||||
html += "<div class=\"form-check form-switch\">";
|
||||
html += "<input class=\"form-check-input\" type=\"checkbox\" role=\"switch\" id=\"checkbox" + num + "\" name=\"checkbox" + num + "\" " + (checked ? "checked" : "") + ">";
|
||||
html += "<label class=\"form-check-label\" for=\"checkbox" + num + "\">" + label + "</label>";
|
||||
html += "</div>";
|
||||
_containerId = null;
|
||||
|
||||
return html;
|
||||
|
||||
constructor(popupService) {
|
||||
const a = this;
|
||||
|
||||
a._popupService = popupService;
|
||||
}
|
||||
|
||||
GenerateCols(...args) {
|
||||
let html = "";
|
||||
|
||||
for (let i=0; i<args.length; i++) {
|
||||
html += "<div class=\"col\">" + args[i] + "</div>";
|
||||
}
|
||||
get Container() {
|
||||
const a = this;
|
||||
|
||||
return document.getElementById(a._containerId);
|
||||
}
|
||||
|
||||
// get Panel1() {
|
||||
// return this.#getElement("div[role='options']", 1);
|
||||
// }
|
||||
|
||||
// get Panel2() {
|
||||
// return this.#getElement("div[role='filters']", 1);
|
||||
// }
|
||||
|
||||
// get Panel3() {
|
||||
// return this.#getElement("div[role='results']", 1);
|
||||
// }
|
||||
|
||||
|
||||
// Clear(clearAll) {
|
||||
// const a = this;
|
||||
// const label1 = a._getLabel(1);
|
||||
|
||||
// label1.innerText = "";
|
||||
|
||||
// if (Boolean.isTrue(clearAll)) {
|
||||
// a._setHtml(a.Panel1, "");
|
||||
// a._setHtml(a.Panel2, "");
|
||||
// }
|
||||
|
||||
// a._setHtml(a.Panel3, "");
|
||||
// }
|
||||
|
||||
// async Search() {
|
||||
// const a = this;
|
||||
|
||||
// a.Clear(false);
|
||||
// }
|
||||
|
||||
|
||||
GenerateCheckBox(num, label, checked) {
|
||||
const randId = Math.randomN(100001, 999999);
|
||||
const id = "checkbox" + randId;
|
||||
const name = "checkbox" + num;
|
||||
|
||||
let html = "";
|
||||
html += "<div class=\"form-check form-switch\">";
|
||||
html += "<input class=\"form-check-input\" type=\"checkbox\" role=\"switch\" id=\"" + id + "\" name=\"" + name + "\" " + (checked ? "checked" : "") + ">";
|
||||
html += "<label class=\"form-check-label\" for=\"" + id + "\">" + label + "</label>";
|
||||
html += "</div>";
|
||||
|
||||
return html;
|
||||
}
|
||||
@ -43,15 +88,17 @@ class ContentService {
|
||||
return result;
|
||||
}
|
||||
|
||||
GenerateRadioBox(groupNo, num, label, value, checked) {
|
||||
let html = "";
|
||||
html += "<div class=\"form-check\">";
|
||||
html += "<input class=\"form-check-input\" type=\"radio\" name=\"radioGroup" + groupNo + "\" id=\"radioBox" + num + "\" value=\"" + value + "\" " + (checked ? "checked" : "") + ">";
|
||||
html += "<label class=\"form-check-label\" for=\"radioBox" + num + "\">" + label + "</label>";
|
||||
html += "</div>";
|
||||
// GenerateRadioBox(groupNo, num, label, value, checked) {
|
||||
// const randId = Math.randomN(100001, 999999);
|
||||
|
||||
return html;
|
||||
}
|
||||
// let html = "";
|
||||
// html += "<div class=\"form-check\">";
|
||||
// html += "<input class=\"form-check-input\" type=\"radio\" name=\"radioGroup" + groupNo + "\" id=\"radioBox" + randId + "\" value=\"" + value + "\" " + (checked ? "checked" : "") + ">";
|
||||
// html += "<label class=\"form-check-label\" for=\"radioBox" + randId + "\">" + label + "</label>";
|
||||
// html += "</div>";
|
||||
|
||||
// return html;
|
||||
// }
|
||||
|
||||
GenerateRow(...args) {
|
||||
const a = this;
|
||||
@ -64,17 +111,113 @@ class ContentService {
|
||||
|
||||
let result = "";
|
||||
for (let i=0; i<args.length; i++) {
|
||||
result = result + a.GenerateRowCell(args[i]);
|
||||
result = result + a._generateTableCell(args[i]);
|
||||
}
|
||||
|
||||
return "<tr>" + result + "</tr>";
|
||||
}
|
||||
|
||||
GenerateRowCell(value) {
|
||||
|
||||
|
||||
_generateCheckBoxPanel(col1, col2) {
|
||||
const a = this;
|
||||
|
||||
let colContent1 = "";
|
||||
let colContent2 = "";
|
||||
|
||||
for (let i=0; i<col1.length; i++) {
|
||||
colContent1 += a.GenerateCheckBox(col1[i].id, col1[i].text, col1[i].checked);
|
||||
}
|
||||
|
||||
for (let i=0; i<col2.length; i++) {
|
||||
colContent2 += a.GenerateCheckBox(col2[i].id, col2[i].text, col2[i].checked);
|
||||
}
|
||||
|
||||
return a.#generateCols(colContent1, colContent2);
|
||||
}
|
||||
|
||||
_generateTextarea() {
|
||||
let html = "";
|
||||
html += "<textarea class=\"form-control font-monospace text-sm px-1 py-1\" rows=\"16\"></textarea>";
|
||||
|
||||
return html;
|
||||
}
|
||||
|
||||
_generateTable() {
|
||||
let html = "";
|
||||
html += "<table class=\"table table-bordered table-hover table-sm table-striped\">";
|
||||
html += "<thead></thead>";
|
||||
html += "<tbody></tbody>";
|
||||
html += "</table>";
|
||||
|
||||
return html;
|
||||
}
|
||||
|
||||
_generateTableCell(value) {
|
||||
return "<td class=\"\"><input type=\"text\" class=\"display\" readonly=\"readonly\" value=\"" + value + "\" /></td>";
|
||||
}
|
||||
|
||||
SetHtml(element, htmlContent) {
|
||||
_generateTableHeader(fixedColumns, conditionalColumns) {
|
||||
const a = this;
|
||||
|
||||
let html = "";
|
||||
for (let i=0; i<fixedColumns.length; i++) {
|
||||
html += "<th>" + fixedColumns[i] + "</th>";
|
||||
}
|
||||
|
||||
for (let i=0; i<conditionalColumns.length; i++) {
|
||||
if (!a._getCheckBox(conditionalColumns[i].id)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
html += "<th>" + conditionalColumns[i].name + "</th>";
|
||||
}
|
||||
|
||||
return html;
|
||||
}
|
||||
|
||||
|
||||
_getButton(num) {
|
||||
return this.#getElement("button", num);
|
||||
}
|
||||
|
||||
_getCheckBox(id) {
|
||||
const a = this;
|
||||
const name = "checkbox" + id;
|
||||
|
||||
const el = this.#getElement("input[type='checkbox'][name='" + name + "']", 1);
|
||||
if (el == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return el.checked;
|
||||
}
|
||||
|
||||
_getComboBox(num) {
|
||||
const a = this;
|
||||
|
||||
const el = a.#getElement("select", num);
|
||||
if (el == null) {
|
||||
return "";
|
||||
}
|
||||
|
||||
return el.value;
|
||||
}
|
||||
|
||||
_getLabel(num) {
|
||||
return this.#getElement("[role='label']", num);
|
||||
}
|
||||
|
||||
_getPanel(name, num) {
|
||||
return this.#getElement("div[role='" + name + "']", num);
|
||||
}
|
||||
|
||||
_getTextBox(num) {
|
||||
return this.#getElement("input[type='text']", num);
|
||||
}
|
||||
|
||||
|
||||
_setHtml(element, htmlContent) {
|
||||
if (element == null) {
|
||||
return;
|
||||
}
|
||||
@ -82,6 +225,36 @@ class ContentService {
|
||||
element.innerHTML = htmlContent;
|
||||
}
|
||||
|
||||
|
||||
#generateCols(...args) {
|
||||
let html = "";
|
||||
|
||||
for (let i=0; i<args.length; i++) {
|
||||
html += "<div class=\"col\">" + args[i] + "</div>";
|
||||
}
|
||||
|
||||
return html;
|
||||
}
|
||||
|
||||
#getElement(nodeName, num) {
|
||||
const a = this;
|
||||
|
||||
if (a.Container == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const nodes = a.Container.querySelectorAll(nodeName);
|
||||
if (nodes.length <= 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (nodes.length > num) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return nodes[(num - 1)];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
233
src/src/popup/img-content-service.js
Normal file
233
src/src/popup/img-content-service.js
Normal file
@ -0,0 +1,233 @@
|
||||
import TabContentService from './tab-content-service.js';
|
||||
|
||||
|
||||
class ImgContentService extends TabContentService {
|
||||
|
||||
constructor(popupService) {
|
||||
super(popupService);
|
||||
|
||||
const a = this;
|
||||
|
||||
a._containerId = "nav-images";
|
||||
a._optionsCol1 = [
|
||||
{ id: 203, text: "Sort By Source URL", checked: true },
|
||||
{ id: 204, text: "Resolve Relative URL", checked: false }
|
||||
];
|
||||
a._optionsCol2 = [
|
||||
{ id: 202, text: "Trim Alternate Text", checked: true }
|
||||
];
|
||||
a._filtersCol1 = [
|
||||
{ id: 212, text: "Hide External Links", checked: false },
|
||||
{ id: 205, text: "Hide Duplicates", checked: true },
|
||||
{ id: 214, text: "Hide Blank Alternate Text", checked: false },
|
||||
{ id: 215, text: "Hide Blank Source URL", checked: true }
|
||||
];
|
||||
a._filtersCol2 = [
|
||||
{ id: 206, text: "Show Alternative Text", checked: true },
|
||||
{ id: 207, text: "Show Source Set", checked: false },
|
||||
{ id: 208, text: "Show Image Map", checked: false },
|
||||
{ id: 210, text: "Show Count", checked: false }
|
||||
];
|
||||
|
||||
}
|
||||
|
||||
async _retrieveResult() {
|
||||
return await this._popupService.GetImages();
|
||||
}
|
||||
|
||||
async _filterResult(items) {
|
||||
const a = this;
|
||||
const currentUrl = await a._popupService.GetLocation();
|
||||
const currentHostname = (new URL(currentUrl)).hostname;
|
||||
|
||||
let result = [];
|
||||
|
||||
for (let i=0; i<items.length; i++) {
|
||||
const item = items[i];
|
||||
|
||||
// Hide source
|
||||
if (a._getCheckBox(215)) {
|
||||
if (String.isNullOrWhitespace(item.src)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
const absoluteUrl = new URL(item.src, currentUrl);
|
||||
|
||||
// Hide external links
|
||||
if (a._getCheckBox(212)) {
|
||||
if (currentHostname != absoluteUrl.hostname) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Hide blank alternative text
|
||||
if (a._getCheckBox(214)) {
|
||||
if (String.isNullOrWhitespace(item.alt)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Resolve source
|
||||
const src = (a._getCheckBox(204) ? absoluteUrl.href : item.src);
|
||||
const alt = (a._getCheckBox(202) ? item.alt.trim() : item.alt);
|
||||
|
||||
// Search term
|
||||
if (!String.isNullOrWhitespace(a._textBox1.value)) {
|
||||
if (a._getComboBox(1) == "src") {
|
||||
if (!src.toLowerCase().includes(a._textBox1.value.toLowerCase())) {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
if (!alt.toLowerCase().includes(a._textBox1.value.toLowerCase())) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result.push({
|
||||
src: src,
|
||||
alt: (a._getCheckBox(206) ? alt : ""),
|
||||
srcset: (a._getCheckBox(207) ? item.srcset : ""),
|
||||
usemap: (a._getCheckBox(208) ? item.usemap : ""),
|
||||
occurrence: ""
|
||||
});
|
||||
}
|
||||
|
||||
// Show occurrence
|
||||
if (a._getCheckBox(210)) {
|
||||
// Calc occurrences, store in cache
|
||||
let occurrenceCache = [];
|
||||
for (let i=0; i<result.length; i++) {
|
||||
const occurrence = result.filter(item => JSON.stringify(item) === JSON.stringify(result[i])).length;
|
||||
|
||||
occurrenceCache.push(occurrence);
|
||||
}
|
||||
|
||||
// Update result with occurrence
|
||||
for (let i=0; i<result.length; i++) {
|
||||
result[i].occurrence = occurrenceCache[i];
|
||||
}
|
||||
}
|
||||
|
||||
// Hide duplicates
|
||||
if (a._getCheckBox(205)) {
|
||||
result = result.distinct();
|
||||
}
|
||||
|
||||
// Sort by source
|
||||
if (a._getCheckBox(203)) {
|
||||
result = result.orderBy("src");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
_renderTable(results) {
|
||||
const a = this;
|
||||
const table = a._generateTable();
|
||||
|
||||
a._setHtml(a._panel3, table);
|
||||
|
||||
const thead = a._panel3.querySelectorAll("thead")[0];
|
||||
const tbody = a._panel3.querySelectorAll("tbody")[0];
|
||||
|
||||
// Write thead
|
||||
thead.innerHTML = "<tr>" + a.#generateTableHeader() + "</tr>";
|
||||
|
||||
// Write tbody
|
||||
for (let i=0; i<results.length; i++) {
|
||||
const item = results[i];
|
||||
|
||||
let row = [ item.src ];
|
||||
|
||||
if (a._getCheckBox(206)) {
|
||||
row.push(item.alt);
|
||||
}
|
||||
|
||||
if (a._getCheckBox(207)) {
|
||||
row.push(item.srcset);
|
||||
}
|
||||
|
||||
if (a._getCheckBox(208)) {
|
||||
row.push(item.usemap);
|
||||
}
|
||||
|
||||
if (a._getCheckBox(210)) {
|
||||
row.push(item.occurrence);
|
||||
}
|
||||
|
||||
tbody.innerHTML += a.GenerateRow(row);
|
||||
}
|
||||
}
|
||||
|
||||
_renderCSV(results) {
|
||||
const a = this;
|
||||
const textarea = a._generateTextarea();
|
||||
|
||||
a._setHtml(a._panel3, textarea);
|
||||
|
||||
const tbody = a._panel3.querySelectorAll("textarea")[0];
|
||||
|
||||
for (let i=0; i<results.length; i++) {
|
||||
const item = results[i];
|
||||
|
||||
let row = [ item.src ];
|
||||
|
||||
if (a._getCheckBox(206)) {
|
||||
row.push(item.alt);
|
||||
}
|
||||
|
||||
if (a._getCheckBox(207)) {
|
||||
row.push(item.srcset);
|
||||
}
|
||||
|
||||
if (a._getCheckBox(208)) {
|
||||
row.push(item.usemap);
|
||||
}
|
||||
|
||||
if (a._getCheckBox(210)) {
|
||||
row.push(item.occurrence);
|
||||
}
|
||||
|
||||
tbody.value += a.GenerateCSVLine("\t", row);
|
||||
tbody.value += "\n";
|
||||
}
|
||||
}
|
||||
|
||||
_renderLinks(results) {
|
||||
const a = this;
|
||||
const textarea = a._generateTextarea();
|
||||
|
||||
a._setHtml(a._panel3, textarea);
|
||||
|
||||
const tbody = a._panel3.querySelectorAll("textarea")[0];
|
||||
|
||||
for (let i=0; i<results.length; i++) {
|
||||
const item = results[i];
|
||||
|
||||
tbody.value += a.GenerateCSVLine("\t", [ item.src ]);
|
||||
tbody.value += "\n";
|
||||
}
|
||||
}
|
||||
|
||||
#generateTableHeader() {
|
||||
const a = this;
|
||||
|
||||
const columns1 = [
|
||||
"Source"
|
||||
];
|
||||
const columns2 = [
|
||||
{ id: 206, name: "Alternative Text" },
|
||||
{ id: 207, name: "Source Set" },
|
||||
{ id: 208, name: "Image Map" },
|
||||
{ id: 210, name: "Count" }
|
||||
];
|
||||
|
||||
return a._generateTableHeader(columns1, columns2);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
export default ImgContentService;
|
@ -1,444 +0,0 @@
|
||||
import '../../../literyz-js/extensions.dist.js';
|
||||
|
||||
import ContentService from './content-service.js';
|
||||
|
||||
|
||||
class ImgContentService extends ContentService {
|
||||
#containerPanel = null;
|
||||
#popupService = null;
|
||||
|
||||
|
||||
constructor(popupService) {
|
||||
super();
|
||||
|
||||
this.#popupService = popupService;
|
||||
}
|
||||
|
||||
InitialiseComponents() {
|
||||
const a = this;
|
||||
|
||||
a.Clear();
|
||||
|
||||
a.#initialiseComponents_Options();
|
||||
a.#initialiseComponents_Filters();
|
||||
|
||||
a.Button1.addEventListener('click', async function (e) {
|
||||
a.Button2.disabled = true;
|
||||
|
||||
a.TextBox1.value = "";
|
||||
|
||||
await a.Search();
|
||||
|
||||
a.Button2.disabled = false;
|
||||
});
|
||||
|
||||
a.Button2.addEventListener('click', async function (e) {
|
||||
a.Button2.disabled = true;
|
||||
|
||||
await a.Search();
|
||||
|
||||
a.Button2.disabled = false;
|
||||
});
|
||||
}
|
||||
|
||||
#initialiseComponents_Options() {
|
||||
const a = this;
|
||||
|
||||
let col1 = "";
|
||||
col1 += a.GenerateCheckBox(203, "Sort By Source URL", true);
|
||||
col1 += a.GenerateCheckBox(204, "Resolve Relative URL", false);
|
||||
|
||||
let col2 = "";
|
||||
col2 += a.GenerateCheckBox(202, "Trim Alternate Text", true);
|
||||
|
||||
let html = a.GenerateCols(col1, col2);
|
||||
|
||||
a.SetHtml(a.Panel1, html);
|
||||
}
|
||||
|
||||
#initialiseComponents_Filters() {
|
||||
const a = this;
|
||||
|
||||
let col1 = "";
|
||||
col1 += a.GenerateCheckBox(212, "Hide External Links", false);
|
||||
col1 += a.GenerateCheckBox(205, "Hide Duplicates", true);
|
||||
col1 += a.GenerateCheckBox(214, "Hide Blank Alternate Text", false);
|
||||
col1 += a.GenerateCheckBox(215, "Hide Blank Source URL", true);
|
||||
|
||||
let col2 = "";
|
||||
col2 += a.GenerateCheckBox(206, "Show Alternative Text", true);
|
||||
col2 += a.GenerateCheckBox(207, "Show Source Set", false);
|
||||
col2 += a.GenerateCheckBox(208, "Show Image Map", false);
|
||||
// col2 += a.GenerateCheckBox(209, "Show Width", false);
|
||||
// col2 += a.GenerateCheckBox(210, "Show Height", false);
|
||||
col2 += a.GenerateCheckBox(210, "Show Count", false);
|
||||
|
||||
let html = a.GenerateCols(col1, col2);
|
||||
|
||||
a.SetHtml(a.Panel2, html);
|
||||
}
|
||||
|
||||
|
||||
get Button1() {
|
||||
const a = this;
|
||||
|
||||
if (a.Container == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return a.Container.querySelectorAll("button")[0];
|
||||
}
|
||||
|
||||
get Button2() {
|
||||
const a = this;
|
||||
|
||||
if (a.Container == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return a.Container.querySelectorAll("button")[1];
|
||||
}
|
||||
|
||||
get Container() {
|
||||
const a = this;
|
||||
|
||||
if (a.#containerPanel == null) {
|
||||
a.#containerPanel = document.getElementById("nav-images");
|
||||
}
|
||||
|
||||
return a.#containerPanel;
|
||||
}
|
||||
|
||||
get Label1() {
|
||||
const a = this;
|
||||
|
||||
if (a.Container == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return a.Container.querySelectorAll("[role='label']")[0];
|
||||
}
|
||||
|
||||
get MemoBox1() {
|
||||
const a = this;
|
||||
|
||||
if (a.Container == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return a.Container.querySelectorAll("textarea")[0];
|
||||
}
|
||||
|
||||
get Panel1() {
|
||||
const a = this;
|
||||
|
||||
if (a.Container == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return a.Container.querySelectorAll("div[role='options']")[0];
|
||||
}
|
||||
|
||||
get Panel2() {
|
||||
const a = this;
|
||||
|
||||
if (a.Container == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return a.Container.querySelectorAll("div[role='filters']")[0];
|
||||
}
|
||||
|
||||
get Table1() {
|
||||
const a = this;
|
||||
|
||||
if (a.Container == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return a.Container.querySelectorAll("table")[0];
|
||||
}
|
||||
|
||||
get TextBox1() {
|
||||
const a = this;
|
||||
|
||||
if (a.Container == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return a.Container.querySelectorAll("input[role='textbox']")[0];
|
||||
}
|
||||
|
||||
|
||||
Clear() {
|
||||
const a = this;
|
||||
|
||||
a.Table1.style.display = 'none';
|
||||
a.MemoBox1.style.display = 'none';
|
||||
|
||||
a.SetHtml(a.Panel1, "");
|
||||
a.SetHtml(a.Panel2, "");
|
||||
}
|
||||
|
||||
async Search() {
|
||||
const a = this;
|
||||
|
||||
a.Label1.innerText = "";
|
||||
|
||||
a.Table1.style.display = 'none';
|
||||
a.MemoBox1.style.display = 'none';
|
||||
|
||||
const result = await a.#popupService.GetImages();
|
||||
const totalCount = result.length;
|
||||
|
||||
const newResults = await a.#filterResult(result.copy());
|
||||
|
||||
if (newResults.length == totalCount) {
|
||||
a.Label1.innerText = "Showing " + totalCount + " result" + (totalCount == 1 ? "" : "s");
|
||||
} else {
|
||||
a.Label1.innerText = "Showing " + newResults.length + " of " + totalCount + " result" + (totalCount == 1 ? "" : "s");
|
||||
}
|
||||
|
||||
switch (a.#getComboBox(2)) {
|
||||
case "table":
|
||||
a.#renderTable(newResults);
|
||||
break;
|
||||
case "csv":
|
||||
a.#renderCSV(newResults);
|
||||
break;
|
||||
case "links":
|
||||
a.#renderLinks(newResults);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
async #filterResult(items) {
|
||||
const a = this;
|
||||
const currentUrl = await a.#popupService.GetLocation();
|
||||
const currentHostname = (new URL(currentUrl)).hostname;
|
||||
|
||||
let result = [];
|
||||
|
||||
for (let i=0; i<items.length; i++) {
|
||||
const item = items[i];
|
||||
|
||||
// Hide source
|
||||
if (a.#getCheckBox(215)) {
|
||||
if (String.isNullOrWhitespace(item.src)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
const absoluteUrl = new URL(item.src, currentUrl);
|
||||
|
||||
// Hide external links
|
||||
if (a.#getCheckBox(212)) {
|
||||
if (currentHostname != absoluteUrl.hostname) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Hide blank alternative text
|
||||
if (a.#getCheckBox(214)) {
|
||||
if (String.isNullOrWhitespace(item.alt)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Resolve source
|
||||
const src = (a.#getCheckBox(204) ? absoluteUrl.href : item.src);
|
||||
const alt = (a.#getCheckBox(202) ? item.alt.trim() : item.alt);
|
||||
|
||||
// Search term
|
||||
if (!String.isNullOrWhitespace(a.TextBox1.value)) {
|
||||
if (a.#getComboBox(201) == "alt") {
|
||||
if (!alt.toLowerCase().includes(a.TextBox1.value.toLowerCase())) {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
if (!src.toLowerCase().includes(a.TextBox1.value.toLowerCase())) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result.push({
|
||||
src: src,
|
||||
alt: (a.#getCheckBox(206) ? alt : ""),
|
||||
srcset: (a.#getCheckBox(207) ? item.srcset : ""),
|
||||
usemap: (a.#getCheckBox(208) ? item.usemap : ""),
|
||||
occurrence: ""
|
||||
});
|
||||
}
|
||||
|
||||
// Show occurrence
|
||||
if (a.#getCheckBox(210)) {
|
||||
// Calc occurrences, store in cache
|
||||
let occurrenceCache = [];
|
||||
for (let i=0; i<result.length; i++) {
|
||||
const occurrence = result.filter(item => JSON.stringify(item) === JSON.stringify(result[i])).length;
|
||||
|
||||
occurrenceCache.push(occurrence);
|
||||
}
|
||||
|
||||
// Update result with occurrence
|
||||
for (let i=0; i<result.length; i++) {
|
||||
result[i].occurrence = occurrenceCache[i];
|
||||
}
|
||||
}
|
||||
|
||||
// Hide duplicates
|
||||
if (a.#getCheckBox(205)) {
|
||||
result = result.distinct();
|
||||
}
|
||||
|
||||
// Sort by source
|
||||
if (a.#getCheckBox(203)) {
|
||||
result = result.orderBy("src");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#generateTHeader() {
|
||||
const a = this;
|
||||
const columns = [
|
||||
{ id: 206, name: "Alternative Text" },
|
||||
{ id: 207, name: "Source Set" },
|
||||
{ id: 208, name: "Image Map" },
|
||||
{ id: 210, name: "Count" }
|
||||
];
|
||||
|
||||
let html = "";
|
||||
html += "<th>Source</th>";
|
||||
|
||||
for (let i=0; i<columns.length; i++) {
|
||||
if (a.#getCheckBox(columns[i].id)) {
|
||||
html += "<th>" + columns[i].name + "</th>";
|
||||
}
|
||||
}
|
||||
|
||||
return html;
|
||||
}
|
||||
|
||||
#getCheckBox(num) {
|
||||
const a = this;
|
||||
|
||||
if (a.Container == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const result = a.Container.querySelectorAll("input[name='checkbox" + num + "']");
|
||||
if (result.length <= 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return result[0].checked;
|
||||
}
|
||||
|
||||
#getComboBox(num) {
|
||||
const a = this;
|
||||
|
||||
if (a.Container == null) {
|
||||
return "";
|
||||
}
|
||||
|
||||
const result = a.Container.querySelectorAll("select[name='comboBox" + num + "']");
|
||||
if (result.length <= 0) {
|
||||
return "";
|
||||
}
|
||||
|
||||
return result[0].value;
|
||||
}
|
||||
|
||||
#renderTable(results) {
|
||||
const a = this;
|
||||
const thead = a.Table1.querySelectorAll("thead")[0];
|
||||
const tbody = a.Table1.querySelectorAll("tbody")[0];
|
||||
|
||||
thead.innerHTML = "";
|
||||
tbody.innerHTML = "";
|
||||
|
||||
a.Table1.style.display = 'table';
|
||||
|
||||
// Write thead
|
||||
thead.innerHTML = "<tr>" + a.#generateTHeader() + "</tr>";
|
||||
|
||||
// Write tbody
|
||||
for (let i=0; i<results.length; i++) {
|
||||
const item = results[i];
|
||||
|
||||
let row = [ item.src ];
|
||||
|
||||
if (a.#getCheckBox(206)) {
|
||||
row.push(item.alt);
|
||||
}
|
||||
|
||||
if (a.#getCheckBox(207)) {
|
||||
row.push(item.srcset);
|
||||
}
|
||||
|
||||
if (a.#getCheckBox(208)) {
|
||||
row.push(item.usemap);
|
||||
}
|
||||
|
||||
if (a.#getCheckBox(210)) {
|
||||
row.push(item.occurrence);
|
||||
}
|
||||
|
||||
tbody.innerHTML += a.GenerateRow(row);
|
||||
}
|
||||
}
|
||||
|
||||
#renderCSV(results) {
|
||||
const a = this;
|
||||
|
||||
a.MemoBox1.value = "";
|
||||
a.MemoBox1.style.display = 'inline-block';
|
||||
|
||||
for (let i=0; i<results.length; i++) {
|
||||
const item = results[i];
|
||||
|
||||
let row = [ item.src ];
|
||||
|
||||
if (a.#getCheckBox(206)) {
|
||||
row.push(item.alt);
|
||||
}
|
||||
|
||||
if (a.#getCheckBox(207)) {
|
||||
row.push(item.srcset);
|
||||
}
|
||||
|
||||
if (a.#getCheckBox(208)) {
|
||||
row.push(item.usemap);
|
||||
}
|
||||
|
||||
if (a.#getCheckBox(210)) {
|
||||
row.push(item.occurrence);
|
||||
}
|
||||
|
||||
a.MemoBox1.value += a.GenerateCSVLine("\t", row);
|
||||
a.MemoBox1.value += "\n";
|
||||
}
|
||||
}
|
||||
|
||||
#renderLinks(results) {
|
||||
const a = this;
|
||||
|
||||
a.MemoBox1.value = "";
|
||||
a.MemoBox1.style.display = 'inline-block';
|
||||
|
||||
for (let i=0; i<results.length; i++) {
|
||||
const item = results[i];
|
||||
|
||||
a.MemoBox1.value += a.GenerateCSVLine("\t", [ item.src ]);
|
||||
a.MemoBox1.value += "\n";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
export default ImgContentService;
|
188
src/src/popup/meta-content-service.js
Normal file
188
src/src/popup/meta-content-service.js
Normal file
@ -0,0 +1,188 @@
|
||||
import TabContentService from './tab-content-service.js';
|
||||
|
||||
|
||||
class MetaContentService extends TabContentService {
|
||||
|
||||
constructor(popupService) {
|
||||
super(popupService);
|
||||
|
||||
const a = this;
|
||||
|
||||
a._containerId = "nav-metas";
|
||||
a._optionsCol1 = [
|
||||
{ id: 303, text: "Sort By Name", checked: true }
|
||||
];
|
||||
a._optionsCol2 = [
|
||||
{ id: 302, text: "Trim Content", checked: true }
|
||||
];
|
||||
a._filtersCol1 = [
|
||||
{ id: 305, text: "Hide Duplicates", checked: true },
|
||||
{ id: 314, text: "Hide Blank Name", checked: false },
|
||||
{ id: 315, text: "Hide Blank Content", checked: true }
|
||||
];
|
||||
a._filtersCol2 = [
|
||||
{ id: 310, text: "Show Count", checked: false }
|
||||
];
|
||||
|
||||
}
|
||||
|
||||
async _retrieveResult() {
|
||||
return await this._popupService.GetMetas();
|
||||
}
|
||||
|
||||
async _filterResult(items) {
|
||||
const a = this;
|
||||
const currentUrl = await a._popupService.GetLocation();
|
||||
|
||||
let result = [];
|
||||
|
||||
for (let i=0; i<items.length; i++) {
|
||||
const item = items[i];
|
||||
|
||||
const content = (a._getCheckBox(302) ? item.content.trim() : item.content);
|
||||
|
||||
// Hide source
|
||||
if (a._getCheckBox(315)) {
|
||||
if (String.isNullOrWhitespace(content)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Hide blank type
|
||||
if (a._getCheckBox(314)) {
|
||||
if (String.isNullOrWhitespace(item.name)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Search term
|
||||
if (!String.isNullOrWhitespace(a._textBox1.value)) {
|
||||
if (a._getComboBox(1) == "name") {
|
||||
if (!item.name.toLowerCase().includes(a._textBox1.value.toLowerCase())) {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
if (!content.toLowerCase().includes(a._textBox1.value.toLowerCase())) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result.push({
|
||||
name: item.name,
|
||||
content: content,
|
||||
occurrence: ""
|
||||
});
|
||||
}
|
||||
|
||||
// Show occurrence
|
||||
if (a._getCheckBox(310)) {
|
||||
// Calc occurrences, store in cache
|
||||
let occurrenceCache = [];
|
||||
for (let i=0; i<result.length; i++) {
|
||||
const occurrence = result.filter(item => JSON.stringify(item) === JSON.stringify(result[i])).length;
|
||||
|
||||
occurrenceCache.push(occurrence);
|
||||
}
|
||||
|
||||
// Update result with occurrence
|
||||
for (let i=0; i<result.length; i++) {
|
||||
result[i].occurrence = occurrenceCache[i];
|
||||
}
|
||||
}
|
||||
|
||||
// Hide duplicates
|
||||
if (a._getCheckBox(305)) {
|
||||
result = result.distinct();
|
||||
}
|
||||
|
||||
// Sort by name
|
||||
if (a._getCheckBox(303)) {
|
||||
result = result.orderBy("name");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
_renderTable(results) {
|
||||
const a = this;
|
||||
const table = a._generateTable();
|
||||
|
||||
a._setHtml(a._panel3, table);
|
||||
|
||||
const thead = a._panel3.querySelectorAll("thead")[0];
|
||||
const tbody = a._panel3.querySelectorAll("tbody")[0];
|
||||
|
||||
// Write thead
|
||||
thead.innerHTML = "<tr>" + a.#generateTableHeader() + "</tr>";
|
||||
|
||||
// Write tbody
|
||||
for (let i=0; i<results.length; i++) {
|
||||
const item = results[i];
|
||||
|
||||
let row = [ item.name, item.content ];
|
||||
|
||||
if (a._getCheckBox(310)) {
|
||||
row.push(item.occurrence);
|
||||
}
|
||||
|
||||
tbody.innerHTML += a.GenerateRow(row);
|
||||
}
|
||||
}
|
||||
|
||||
_renderCSV(results) {
|
||||
const a = this;
|
||||
const textarea = a._generateTextarea();
|
||||
|
||||
a._setHtml(a._panel3, textarea);
|
||||
|
||||
const tbody = a._panel3.querySelectorAll("textarea")[0];
|
||||
|
||||
for (let i=0; i<results.length; i++) {
|
||||
const item = results[i];
|
||||
|
||||
let row = [ item.name, item.content ];
|
||||
|
||||
if (a._getCheckBox(310)) {
|
||||
row.push(item.occurrence);
|
||||
}
|
||||
|
||||
tbody.value += a.GenerateCSVLine("\t", row);
|
||||
tbody.value += "\n";
|
||||
}
|
||||
}
|
||||
|
||||
_renderLinks(results) {
|
||||
const a = this;
|
||||
const textarea = a._generateTextarea();
|
||||
|
||||
a._setHtml(a._panel3, textarea);
|
||||
|
||||
const tbody = a._panel3.querySelectorAll("textarea")[0];
|
||||
|
||||
for (let i=0; i<results.length; i++) {
|
||||
const item = results[i];
|
||||
|
||||
tbody.value += a.GenerateCSVLine("\t", [ item.content ]);
|
||||
tbody.value += "\n";
|
||||
}
|
||||
}
|
||||
|
||||
#generateTableHeader() {
|
||||
const a = this;
|
||||
|
||||
const columns1 = [
|
||||
"Name",
|
||||
"Content"
|
||||
];
|
||||
const columns2 = [
|
||||
{ id: 310, name: "Count" }
|
||||
];
|
||||
|
||||
return a._generateTableHeader(columns1, columns2);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
export default MetaContentService;
|
@ -17,7 +17,6 @@ class PopupService {
|
||||
resolve(payload.copy());
|
||||
});
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
async GetImages() {
|
||||
@ -28,7 +27,16 @@ class PopupService {
|
||||
resolve(payload.copy());
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async GetScripts() {
|
||||
const a = this;
|
||||
|
||||
return new Promise(function(resolve) {
|
||||
a.SendMessage("GetScriptNodes", async function(payload) {
|
||||
resolve(payload.copy());
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async GetLocation() {
|
||||
@ -41,6 +49,16 @@ class PopupService {
|
||||
});
|
||||
}
|
||||
|
||||
async GetMetas() {
|
||||
const a = this;
|
||||
|
||||
return new Promise(function(resolve) {
|
||||
a.SendMessage("GetMetaNodes", async function(payload) {
|
||||
resolve(payload.copy());
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
211
src/src/popup/script-content-service.js
Normal file
211
src/src/popup/script-content-service.js
Normal file
@ -0,0 +1,211 @@
|
||||
import TabContentService from './tab-content-service.js';
|
||||
|
||||
|
||||
class ScriptContentService extends TabContentService {
|
||||
|
||||
constructor(popupService) {
|
||||
super(popupService);
|
||||
|
||||
const a = this;
|
||||
|
||||
a._containerId = "nav-scripts";
|
||||
a._optionsCol1 = [
|
||||
{ id: 303, text: "Sort By Source URL", checked: true },
|
||||
{ id: 304, text: "Resolve Relative URL", checked: false }
|
||||
];
|
||||
a._optionsCol2 = [
|
||||
{ id: 302, text: "Trim Alternate Type", checked: true }
|
||||
];
|
||||
a._filtersCol1 = [
|
||||
{ id: 312, text: "Hide External Links", checked: false },
|
||||
{ id: 305, text: "Hide Duplicates", checked: true },
|
||||
{ id: 314, text: "Hide Blank Type", checked: false },
|
||||
{ id: 315, text: "Hide Blank Source URL", checked: true }
|
||||
];
|
||||
a._filtersCol2 = [
|
||||
{ id: 306, text: "Show Type", checked: true },
|
||||
{ id: 310, text: "Show Count", checked: false }
|
||||
];
|
||||
|
||||
}
|
||||
|
||||
async _retrieveResult() {
|
||||
return await this._popupService.GetScripts();
|
||||
}
|
||||
|
||||
async _filterResult(items) {
|
||||
const a = this;
|
||||
const currentUrl = await a._popupService.GetLocation();
|
||||
const currentHostname = (new URL(currentUrl)).hostname;
|
||||
|
||||
let result = [];
|
||||
|
||||
for (let i=0; i<items.length; i++) {
|
||||
const item = items[i];
|
||||
|
||||
// Hide source
|
||||
if (a._getCheckBox(315)) {
|
||||
if (String.isNullOrWhitespace(item.src)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
const absoluteUrl = new URL(item.src, currentUrl);
|
||||
|
||||
// Hide external links
|
||||
if (a._getCheckBox(312)) {
|
||||
if (currentHostname != absoluteUrl.hostname) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Hide blank type
|
||||
if (a._getCheckBox(314)) {
|
||||
if (String.isNullOrWhitespace(item.type)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Resolve source
|
||||
const src = (a._getCheckBox(304) ? absoluteUrl.href : item.src);
|
||||
const type = (a._getCheckBox(302) ? item.type.trim() : item.type);
|
||||
|
||||
// Search term
|
||||
if (!String.isNullOrWhitespace(a._textBox1.value)) {
|
||||
if (a._getComboBox(1) == "src") {
|
||||
if (!src.toLowerCase().includes(a._textBox1.value.toLowerCase())) {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
if (!type.toLowerCase().includes(a._textBox1.value.toLowerCase())) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result.push({
|
||||
src: src,
|
||||
type: (a._getCheckBox(306) ? type : ""),
|
||||
occurrence: ""
|
||||
});
|
||||
}
|
||||
|
||||
// Show occurrence
|
||||
if (a._getCheckBox(310)) {
|
||||
// Calc occurrences, store in cache
|
||||
let occurrenceCache = [];
|
||||
for (let i=0; i<result.length; i++) {
|
||||
const occurrence = result.filter(item => JSON.stringify(item) === JSON.stringify(result[i])).length;
|
||||
|
||||
occurrenceCache.push(occurrence);
|
||||
}
|
||||
|
||||
// Update result with occurrence
|
||||
for (let i=0; i<result.length; i++) {
|
||||
result[i].occurrence = occurrenceCache[i];
|
||||
}
|
||||
}
|
||||
|
||||
// Hide duplicates
|
||||
if (a._getCheckBox(305)) {
|
||||
result = result.distinct();
|
||||
}
|
||||
|
||||
// Sort by source
|
||||
if (a._getCheckBox(303)) {
|
||||
result = result.orderBy("src");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
_renderTable(results) {
|
||||
const a = this;
|
||||
const table = a._generateTable();
|
||||
|
||||
a._setHtml(a._panel3, table);
|
||||
|
||||
const thead = a._panel3.querySelectorAll("thead")[0];
|
||||
const tbody = a._panel3.querySelectorAll("tbody")[0];
|
||||
|
||||
// Write thead
|
||||
thead.innerHTML = "<tr>" + a.#generateTableHeader() + "</tr>";
|
||||
|
||||
// Write tbody
|
||||
for (let i=0; i<results.length; i++) {
|
||||
const item = results[i];
|
||||
|
||||
let row = [ item.src ];
|
||||
|
||||
if (a._getCheckBox(306)) {
|
||||
row.push(item.type);
|
||||
}
|
||||
|
||||
if (a._getCheckBox(310)) {
|
||||
row.push(item.occurrence);
|
||||
}
|
||||
|
||||
tbody.innerHTML += a.GenerateRow(row);
|
||||
}
|
||||
}
|
||||
|
||||
_renderCSV(results) {
|
||||
const a = this;
|
||||
const textarea = a._generateTextarea();
|
||||
|
||||
a._setHtml(a._panel3, textarea);
|
||||
|
||||
const tbody = a._panel3.querySelectorAll("textarea")[0];
|
||||
|
||||
for (let i=0; i<results.length; i++) {
|
||||
const item = results[i];
|
||||
|
||||
let row = [ item.src ];
|
||||
|
||||
if (a._getCheckBox(306)) {
|
||||
row.push(item.type);
|
||||
}
|
||||
|
||||
if (a._getCheckBox(310)) {
|
||||
row.push(item.occurrence);
|
||||
}
|
||||
|
||||
tbody.value += a.GenerateCSVLine("\t", row);
|
||||
tbody.value += "\n";
|
||||
}
|
||||
}
|
||||
|
||||
_renderLinks(results) {
|
||||
const a = this;
|
||||
const textarea = a._generateTextarea();
|
||||
|
||||
a._setHtml(a._panel3, textarea);
|
||||
|
||||
const tbody = a._panel3.querySelectorAll("textarea")[0];
|
||||
|
||||
for (let i=0; i<results.length; i++) {
|
||||
const item = results[i];
|
||||
|
||||
tbody.value += a.GenerateCSVLine("\t", [ item.src ]);
|
||||
tbody.value += "\n";
|
||||
}
|
||||
}
|
||||
|
||||
#generateTableHeader() {
|
||||
const a = this;
|
||||
|
||||
const columns1 = [
|
||||
"Source"
|
||||
];
|
||||
const columns2 = [
|
||||
{ id: 306, name: "Type" },
|
||||
{ id: 310, name: "Count" }
|
||||
];
|
||||
|
||||
return a._generateTableHeader(columns1, columns2);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
export default ScriptContentService;
|
129
src/src/popup/tab-content-service.js
Normal file
129
src/src/popup/tab-content-service.js
Normal file
@ -0,0 +1,129 @@
|
||||
import ContentService from './content-service.js';
|
||||
|
||||
|
||||
class TabContentService extends ContentService {
|
||||
_button1 = null;
|
||||
_button2 = null;
|
||||
_label1 = null;
|
||||
_panel1 = null;
|
||||
_panel2 = null;
|
||||
_panel3 = null;
|
||||
_textBox1 = null;
|
||||
|
||||
_optionsCol1 = [];
|
||||
_optionsCol2 = [];
|
||||
_filtersCol1 = [];
|
||||
_filtersCol2 = [];
|
||||
|
||||
|
||||
constructor(popupService) {
|
||||
super(popupService);
|
||||
}
|
||||
|
||||
InitialiseComponents() {
|
||||
const a = this;
|
||||
|
||||
const buttons = a.Container.querySelectorAll("button");
|
||||
a._button1 = buttons[0];
|
||||
a._button2 = buttons[1];
|
||||
a._label1 = a._getLabel(1);
|
||||
a._panel1 = a._getPanel("options", 1);
|
||||
a._panel2 = a._getPanel("filters", 1);
|
||||
a._panel3 = a._getPanel("results", 1);
|
||||
a._textBox1 = a._getTextBox(1);
|
||||
|
||||
a.Clear(true);
|
||||
|
||||
// Initialise options
|
||||
const htmlContent1 = a._generateCheckBoxPanel(a._optionsCol1, a._optionsCol2);
|
||||
|
||||
a._setHtml(a._panel1, htmlContent1);
|
||||
|
||||
// Initialise filters
|
||||
const htmlContent2 = a._generateCheckBoxPanel(a._filtersCol1, a._filtersCol2);
|
||||
|
||||
a._setHtml(a._panel2, htmlContent2);
|
||||
|
||||
// Events
|
||||
a._button1.addEventListener('click', async function (e) {
|
||||
a._button2.disabled = true;
|
||||
|
||||
a._textBox1.value = "";
|
||||
|
||||
await a.Search();
|
||||
|
||||
a._button2.disabled = false;
|
||||
});
|
||||
|
||||
a._button2.addEventListener('click', async function (e) {
|
||||
a._button2.disabled = true;
|
||||
|
||||
await a.Search();
|
||||
|
||||
a._button2.disabled = false;
|
||||
});
|
||||
}
|
||||
|
||||
Clear(clearAll) {
|
||||
const a = this;
|
||||
|
||||
a._label1.innerText = "";
|
||||
|
||||
if (Boolean.isTrue(clearAll)) {
|
||||
a._setHtml(a._panel1, "");
|
||||
a._setHtml(a._panel2, "");
|
||||
}
|
||||
|
||||
a._setHtml(a._panel3, "");
|
||||
}
|
||||
|
||||
async Search() {
|
||||
const a = this;
|
||||
|
||||
const result = await a._retrieveResult();
|
||||
const totalCount = result.length;
|
||||
|
||||
const newResults = await a._filterResult(result.copy());
|
||||
|
||||
if (newResults.length == totalCount) {
|
||||
a._label1.innerText = "Showing " + totalCount + " result" + (totalCount == 1 ? "" : "s");
|
||||
} else {
|
||||
a._label1.innerText = "Showing " + newResults.length + " of " + totalCount + " result" + (totalCount == 1 ? "" : "s");
|
||||
}
|
||||
|
||||
switch (a._getComboBox(2)) {
|
||||
case "table":
|
||||
a._renderTable(newResults);
|
||||
break;
|
||||
case "csv":
|
||||
a._renderCSV(newResults);
|
||||
break;
|
||||
case "links":
|
||||
a._renderLinks(newResults);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
async _retrieveResult() {
|
||||
return [];
|
||||
}
|
||||
|
||||
async _filterResult(result) {
|
||||
return result;
|
||||
}
|
||||
|
||||
_renderTable(result) {
|
||||
}
|
||||
|
||||
_renderCSV(result) {
|
||||
}
|
||||
|
||||
_renderLinks(result) {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
export default TabContentService;
|
Loading…
Reference in New Issue
Block a user