add linked element context (#196)
This commit is contained in:
@@ -425,8 +425,11 @@ function getElementContext(element) {
|
|||||||
return fullContext;
|
return fullContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getElementContent(element) {
|
function getElementContent(element, skipped_element = null) {
|
||||||
// DFS to get all the text content from all the nodes under the element
|
// DFS to get all the text content from all the nodes under the element
|
||||||
|
if (skipped_element && element === skipped_element) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
let textContent = element.textContent;
|
let textContent = element.textContent;
|
||||||
let nodeContent = "";
|
let nodeContent = "";
|
||||||
@@ -441,7 +444,7 @@ function getElementContent(element) {
|
|||||||
nodeTextContentList.push(childText);
|
nodeTextContentList.push(childText);
|
||||||
} else if (child.nodeType === Node.ELEMENT_NODE) {
|
} else if (child.nodeType === Node.ELEMENT_NODE) {
|
||||||
// childText = child.textContent.trim();
|
// childText = child.textContent.trim();
|
||||||
childText = getElementContent(child);
|
childText = getElementContent(child, skipped_element);
|
||||||
} else {
|
} else {
|
||||||
console.log("Unhandled node type: ", child.nodeType);
|
console.log("Unhandled node type: ", child.nodeType);
|
||||||
}
|
}
|
||||||
@@ -632,6 +635,89 @@ function buildTreeFromBody() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const getContextByParent = (element) => {
|
||||||
|
// for most elements, we're going 10 layers up to see if we can find "label" as a parent
|
||||||
|
// if found, most likely the context under label is relevant to this element
|
||||||
|
let targetParentElements = new Set(["label", "fieldset"]);
|
||||||
|
|
||||||
|
// look up for 10 levels to find the most contextual parent element
|
||||||
|
let targetContextualParent = null;
|
||||||
|
let currentEle = document.querySelector(`[unique_id="${element.id}"]`);
|
||||||
|
let parentEle = currentEle;
|
||||||
|
for (var i = 0; i < 10; i++) {
|
||||||
|
parentEle = parentEle.parentElement;
|
||||||
|
if (parentEle) {
|
||||||
|
if (targetParentElements.has(parentEle.tagName.toLowerCase())) {
|
||||||
|
targetContextualParent = parentEle;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!targetContextualParent) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
let context = "";
|
||||||
|
var lowerCaseTagName = targetContextualParent.tagName.toLowerCase();
|
||||||
|
if (lowerCaseTagName === "label") {
|
||||||
|
context = getElementContext(targetContextualParent);
|
||||||
|
} else if (lowerCaseTagName === "fieldset") {
|
||||||
|
// fieldset is usually within a form or another element that contains the whole context
|
||||||
|
targetContextualParent = targetContextualParent.parentElement;
|
||||||
|
if (targetContextualParent) {
|
||||||
|
context = getElementContext(targetContextualParent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return context;
|
||||||
|
};
|
||||||
|
|
||||||
|
const getContextByLinked = (element) => {
|
||||||
|
let currentEle = document.querySelector(`[unique_id="${element.id}"]`);
|
||||||
|
// check labels pointed to this element
|
||||||
|
// 1. element id -> labels pointed to this id
|
||||||
|
// 2. by attr "aria-labelledby" -> only one label with this id
|
||||||
|
let linkedElements = new Array();
|
||||||
|
const elementId = currentEle.getAttribute("id");
|
||||||
|
if (elementId) {
|
||||||
|
linkedElements = [
|
||||||
|
...document.querySelectorAll(`label[for="${elementId}"]`),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
const labelled = currentEle.getAttribute("aria-labelledby");
|
||||||
|
if (labelled) {
|
||||||
|
const label = document.getElementById(labelled);
|
||||||
|
if (label) {
|
||||||
|
linkedElements.push(label);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const described = currentEle.getAttribute("aria-describedby");
|
||||||
|
if (described) {
|
||||||
|
const describe = document.getElementById(described);
|
||||||
|
if (describe) {
|
||||||
|
linkedElements.push(describe);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const fullContext = new Array();
|
||||||
|
for (let i = 0; i < linkedElements.length; i++) {
|
||||||
|
const linked = linkedElements[i];
|
||||||
|
// if the element is a child of the label, we should stop to get context before the element
|
||||||
|
const content = getElementContent(linked, currentEle);
|
||||||
|
if (content) {
|
||||||
|
fullContext.push(content);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const context = fullContext.join(";");
|
||||||
|
const charLimit = 1000;
|
||||||
|
if (context.length > charLimit) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
return context;
|
||||||
|
};
|
||||||
|
|
||||||
// TODO: Handle iframes
|
// TODO: Handle iframes
|
||||||
// setup before parsing the dom
|
// setup before parsing the dom
|
||||||
checkSelect2();
|
checkSelect2();
|
||||||
@@ -653,39 +739,10 @@ function buildTreeFromBody() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// for most elements, we're going 10 layers up to see if we can find "label" as a parent
|
const context = getContextByLinked(element) + getContextByParent(element);
|
||||||
// if found, most likely the context under label is relevant to this element
|
// const context = getContextByParent(element)
|
||||||
let targetParentElements = new Set(["label", "fieldset"]);
|
if (context && context.length <= 1000) {
|
||||||
|
element.context = context;
|
||||||
// look up for 10 levels to find the most contextual parent element
|
|
||||||
let targetContextualParent = null;
|
|
||||||
let currentEle = document.querySelector(`[unique_id="${element.id}"]`);
|
|
||||||
let parentEle = currentEle;
|
|
||||||
for (var i = 0; i < 10; i++) {
|
|
||||||
parentEle = parentEle.parentElement;
|
|
||||||
if (parentEle) {
|
|
||||||
if (targetParentElements.has(parentEle.tagName.toLowerCase())) {
|
|
||||||
targetContextualParent = parentEle;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (targetContextualParent) {
|
|
||||||
let context = "";
|
|
||||||
var lowerCaseTagName = targetContextualParent.tagName.toLowerCase();
|
|
||||||
if (lowerCaseTagName === "label") {
|
|
||||||
context = getElementContext(targetContextualParent);
|
|
||||||
} else if (lowerCaseTagName === "fieldset") {
|
|
||||||
// fieldset is usually within a form or another element that contains the whole context
|
|
||||||
targetContextualParent = targetContextualParent.parentElement;
|
|
||||||
if (targetContextualParent) {
|
|
||||||
context = getElementContext(targetContextualParent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (context.length > 0) {
|
|
||||||
element.context = context;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user