Greasy Fork is available in English.
Automatically expand all collapsed sections, truncated text, and FAQ accordions on Amazon product pages
// ==UserScript==
// @name Amazon Full View
// @namespace http://tampermonkey.net/
// @version 3.0
// @description Automatically expand all collapsed sections, truncated text, and FAQ accordions on Amazon product pages
// @author zhaozyu with kiro
// @homepageURL https://greasyfork.org/en/scripts/580063-amazon-dp-auto-expand-collapsed-sections
// @include https://www.amazon.*/dp/*
// @include https://www.amazon.*/*/dp/*
// @include https://www.amazon.*/gp/product/*
// @grant none
// @run-at document-idle
// ==/UserScript==
(function () {
"use strict";
/**
* Global capture-phase click interceptor.
* 1. Blocks Amazon's delegated popover handler from firing on truncated
* attribute "See more" links in the product overview area.
* 2. Blocks programmatic clicks on "詳細はこちら" navigation links.
*/
document.addEventListener(
"click",
(e) => {
const target = e.target.closest ? e.target.closest("a") : null;
if (!target) return;
// Block any click on links containing skip text (e.g. "詳細はこちら")
const targetText = target.textContent.trim();
if (SKIP_TEXTS.some((t) => targetText.includes(t))) {
// Only block programmatic clicks (isTrusted=false), allow real user clicks
if (!e.isTrusted) {
e.preventDefault();
e.stopPropagation();
e.stopImmediatePropagation();
return;
}
}
// Only intercept links inside product overview truncate areas
const overviewArea = target.closest(
"#productOverview_feature_div, #poExpander, .po-expander, " +
"#productFactsDesktop_Section, .product-facts"
);
if (!overviewArea) return;
// Check if this link is a popover trigger or inside a truncate cell
const isPopoverTrigger =
target.hasAttribute("data-a-popover") ||
target.getAttribute("data-action") === "a-popover";
const cell = target.closest("td");
const hasTruncate = cell && cell.querySelector(
".a-truncate, .a-truncate-full, .a-truncate-cut"
);
if (isPopoverTrigger || hasTruncate) {
const text = target.textContent.trim();
const expandTexts = ["表示を増やす", "See more", "Show more", "Read more"];
if (expandTexts.some((t) => text.includes(t))) {
e.preventDefault();
e.stopPropagation();
e.stopImmediatePropagation();
// Trigger inline expansion instead
expandTruncatedCellsInline();
}
}
},
true // capture phase - fires before Amazon's handlers
);
/**
* Expand truncated attribute cells inline instead of opening a popover/modal.
* Targets the product overview table where fields like "特徴" are cut off
* with a "表示を増やす" link that normally triggers a popup.
*/
function expandTruncatedCellsInline() {
// Target all a-truncate containers in the product overview area
const truncateContainers = document.querySelectorAll(
[
"#productOverview_feature_div .a-truncate",
"#poExpander .a-truncate",
".po-expander .a-truncate",
"#productFactsDesktop_Section .a-truncate",
".product-facts .a-truncate",
'table.a-normal .a-truncate',
'table.prodDetTable .a-truncate',
].join(",")
);
truncateContainers.forEach((container) => {
// Skip if already processed
if (container.dataset.inlineExpanded === "true") return;
const fullTextEl = container.querySelector(".a-truncate-full");
const cutTextEl = container.querySelector(".a-truncate-cut");
if (fullTextEl && cutTextEl) {
// Show the full text element and hide the cut version
fullTextEl.style.display = "inline";
fullTextEl.classList.remove("a-offscreen");
cutTextEl.style.display = "none";
// Remove the max-height / overflow constraints on the container
container.style.maxHeight = "none";
container.style.overflow = "visible";
container.style.webkitLineClamp = "unset";
container.classList.remove("a-truncate");
// Hide the "表示を増やす" / "See more" link
const seeMoreLink = container.querySelector(
".a-truncate-see-more, .a-declarative"
);
if (seeMoreLink) {
seeMoreLink.style.display = "none";
}
// Also remove any popover trigger attributes to prevent modal
const popoverTriggers = container.querySelectorAll(
'[data-action="a-popover"], [data-a-popover]'
);
popoverTriggers.forEach((trigger) => {
trigger.remove();
});
// Remove the "表示を増やす" link entirely from the container
const seeMoreLinks = container.querySelectorAll(
'a[href="javascript:void(0)"], .a-truncate-see-more, .a-declarative'
);
seeMoreLinks.forEach((link) => {
link.remove();
});
container.dataset.inlineExpanded = "true";
}
});
// Also handle the case where the "See more" link is outside the truncate
// container but within the same table cell (td)
const overviewCells = document.querySelectorAll(
[
"#productOverview_feature_div td",
"#poExpander td",
".po-expander td",
"#productFactsDesktop_Section td",
".product-facts td",
].join(",")
);
overviewCells.forEach((cell) => {
if (cell.dataset.inlineExpanded === "true") return;
const truncateEl = cell.querySelector(".a-truncate");
if (!truncateEl) return;
const fullTextEl = truncateEl.querySelector(".a-truncate-full");
const cutTextEl = truncateEl.querySelector(".a-truncate-cut");
if (fullTextEl && cutTextEl) {
fullTextEl.style.display = "inline";
fullTextEl.classList.remove("a-offscreen");
cutTextEl.style.display = "none";
truncateEl.style.maxHeight = "none";
truncateEl.style.overflow = "visible";
truncateEl.classList.remove("a-truncate");
// Remove any "表示を増やす" popover links from the cell entirely
const expandLinks = cell.querySelectorAll(
'a[data-action="a-popover"], a[data-a-popover], .a-truncate-see-more, a[href="javascript:void(0)"]'
);
expandLinks.forEach((link) => {
link.remove();
});
cell.dataset.inlineExpanded = "true";
}
});
}
/**
* Intercept and block popover triggers for truncated product overview cells.
* This prevents the modal from appearing even if the link is clicked.
*/
function blockTruncatePopovers() {
const popoverLinks = document.querySelectorAll(
[
'#productOverview_feature_div a[data-action="a-popover"]',
'#poExpander a[data-action="a-popover"]',
'.po-expander a[data-action="a-popover"]',
'#productFactsDesktop_Section a[data-action="a-popover"]',
'.product-facts a[data-action="a-popover"]',
].join(",")
);
popoverLinks.forEach((link) => {
if (link.dataset.popoverBlocked === "true") return;
// Check if this link is inside or near a truncate container
const cell = link.closest("td") || link.closest("tr");
if (!cell) return;
const hasTruncate = cell.querySelector(
".a-truncate, .a-truncate-full, .a-truncate-cut"
);
if (!hasTruncate) return;
// Block the popover by capturing click and stopping propagation
link.addEventListener(
"click",
(e) => {
e.preventDefault();
e.stopPropagation();
e.stopImmediatePropagation();
// Instead of popover, expand inline
expandTruncatedCellsInline();
},
true
);
link.dataset.popoverBlocked = "true";
});
}
/**
* Text patterns that indicate a link/expander should NOT be auto-expanded.
* These are navigation or info links, not content expanders.
*/
const SKIP_TEXTS = ["詳細はこちら", "Details here", "Click here for details"];
/**
* Check if an element itself contains skip text.
* Only checks the element's own direct text, not parent containers,
* to avoid false positives on nearby expanders.
*/
function shouldSkipElement(el) {
// If already marked as skip, return immediately
if (el.dataset.dpAutoSkip === "true") return true;
// Check the element's own text content
const text = el.textContent.trim();
if (SKIP_TEXTS.some((t) => text.includes(t))) {
el.dataset.dpAutoSkip = "true";
return true;
}
// Check only the immediate expander content (sibling), not the whole page section
const expanderContainer = el.closest(".a-expander-container");
if (expanderContainer) {
// Only check the expander-content div that is a direct child
const contentDiv = expanderContainer.querySelector(
":scope > .a-expander-content"
);
if (contentDiv) {
const contentText = contentDiv.textContent.trim();
if (SKIP_TEXTS.some((t) => contentText.includes(t))) {
el.dataset.dpAutoSkip = "true";
return true;
}
}
}
return false;
}
/**
* Track elements we've already clicked to prevent repeated expansion.
*/
const clickedElements = new WeakSet();
/**
* Pre-scan and mark all elements that should never be auto-expanded.
* This runs before expandAllSections to block "詳細はこちら" etc.
*/
function markSkipElements() {
// Find all expander headers/links that contain skip text
const allExpanders = document.querySelectorAll(
'.a-expander-header, .a-expander-prompt, .a-expander-partial-collapse-header'
);
allExpanders.forEach((el) => {
const text = el.textContent.trim();
if (SKIP_TEXTS.some((t) => text.includes(t))) {
el.dataset.dpAutoSkip = "true";
clickedElements.add(el);
}
});
// Find ALL links that contain skip text (covers non-expander <a> tags)
const allLinks = document.querySelectorAll("a");
allLinks.forEach((link) => {
const text = link.textContent.trim();
if (SKIP_TEXTS.some((t) => text.includes(t))) {
link.dataset.dpAutoSkip = "true";
clickedElements.add(link);
}
});
// Also find links whose expander-content contains skip text
const allContainers = document.querySelectorAll(".a-expander-container");
allContainers.forEach((container) => {
const contentText = container.textContent;
if (SKIP_TEXTS.some((t) => contentText.includes(t))) {
const header = container.querySelector(
".a-expander-header, .a-expander-prompt"
);
if (header) {
header.dataset.dpAutoSkip = "true";
clickedElements.add(header);
}
}
});
}
/**
* Safe click that prevents clicking on skip-marked elements.
* Allows retry if the element is still collapsed (click didn't take effect).
* Only permanently blocks elements marked as dpAutoSkip.
*/
function safeClick(el) {
if (el.dataset.dpAutoSkip === "true") return false;
if (clickedElements.has(el)) {
// If previously clicked, only skip if it's now expanded
const isExpanded =
el.getAttribute("aria-expanded") === "true" ||
el.closest(".a-expander-container")?.classList.contains("a-expander-expanded") ||
el.closest(".a-expander-partial-collapse-container")?.classList.contains("a-expander-inline-expanded");
if (isExpanded) return false;
// Otherwise allow retry
}
clickedElements.add(el);
el.click();
return true;
}
/**
* Force-expand all A+ FAQ module Q&A panels.
* Amazon A+ Premium FAQ uses a custom structure:
* ul.faq-list > li.faq-block > span[data-faq-question][aria-expanded]
* Answer panels are controlled via aria-controls pointing to answer element IDs.
* The accordion behavior only allows one open at a time.
* We force all panels open and disable the exclusive behavior.
*/
function forceExpandAplusAccordions() {
// Target A+ FAQ question triggers
const faqQuestions = document.querySelectorAll(
'span[data-faq-question], [data-faq-question]'
);
faqQuestions.forEach((trigger) => {
const isExpanded = trigger.getAttribute("aria-expanded") === "true";
if (isExpanded) return;
// Get the answer element via aria-controls
const controlsId = trigger.getAttribute("aria-controls");
const answerEl = controlsId ? document.getElementById(controlsId) : null;
// Force expand
trigger.setAttribute("aria-expanded", "true");
if (answerEl) {
answerEl.style.display = "block";
answerEl.style.visibility = "visible";
answerEl.style.height = "auto";
answerEl.style.maxHeight = "none";
answerEl.style.overflow = "visible";
answerEl.style.opacity = "1";
answerEl.removeAttribute("hidden");
answerEl.classList.remove("a-hidden");
}
// Also try to find the answer as a sibling
const parentLi = trigger.closest("li");
if (parentLi) {
const answer = parentLi.querySelector(
".aplus-answer, .faq-answer, [class*='answer']"
);
if (answer) {
answer.style.display = "block";
answer.style.visibility = "visible";
answer.style.height = "auto";
answer.style.maxHeight = "none";
answer.style.overflow = "visible";
answer.style.opacity = "1";
}
}
});
// Also handle via CSS class on the faq-block list items
const faqBlocks = document.querySelectorAll(
"li.faq-block, .faq-block"
);
faqBlocks.forEach((block) => {
block.classList.add("faq-expanded");
// Show all child elements that might be hidden answers
const hiddenChildren = block.querySelectorAll(
'[style*="display: none"], [style*="display:none"], [hidden], .a-hidden'
);
hiddenChildren.forEach((child) => {
child.style.display = "block";
child.removeAttribute("hidden");
child.classList.remove("a-hidden");
});
});
// Disable the exclusive accordion behavior by removing event bindings
// Clone and replace the FAQ list to strip all event listeners
const faqLists = document.querySelectorAll("ul.faq-list");
faqLists.forEach((list) => {
if (list.dataset.accordionDisabled === "true") return;
// Remove click handlers by cloning
const clone = list.cloneNode(true);
// Re-add click handlers that just toggle individual items
clone.querySelectorAll("span[data-faq-question]").forEach((trigger) => {
trigger.addEventListener("click", (e) => {
e.stopPropagation();
const expanded = trigger.getAttribute("aria-expanded") === "true";
const controlsId = trigger.getAttribute("aria-controls");
const answerEl = controlsId
? document.getElementById(controlsId)
: null;
if (expanded) {
trigger.setAttribute("aria-expanded", "false");
if (answerEl) answerEl.style.display = "none";
} else {
trigger.setAttribute("aria-expanded", "true");
if (answerEl) {
answerEl.style.display = "block";
answerEl.style.height = "auto";
}
}
});
});
clone.dataset.accordionDisabled = "true";
list.parentNode.replaceChild(clone, list);
});
}
function expandAllSections() {
let expanded = 0;
// =========================================================
// 0. Pre-scan: mark elements that should never be expanded
// =========================================================
markSkipElements();
// =========================================================
// 0b. Expand truncated cells inline (prevent popover/modal)
// =========================================================
expandTruncatedCellsInline();
blockTruncatePopovers();
// =========================================================
// 1. Product overview attributes table "表示を増やす" / "See more"
// Located in the product overview/facts section (top area)
// =========================================================
const overviewExpanders = document.querySelectorAll(
[
// Product facts "See more" / "表示を増やす"
'#productOverview_feature_div .a-expander-header[aria-expanded="false"]',
'#productOverview_feature_div a-expander-header[aria-expanded="false"]',
'#poExpander .a-expander-header[aria-expanded="false"]',
'.po-expander .a-expander-header[aria-expanded="false"]',
// Product facts desktop section
'#productFactsDesktop_Section .a-expander-header[aria-expanded="false"]',
'.product-facts .a-expander-header[aria-expanded="false"]',
].join(",")
);
overviewExpanders.forEach((el) => {
if (shouldSkipElement(el)) return;
if (safeClick(el)) expanded++;
});
// =========================================================
// 2. "この商品について" / "About this item" - "もっと見る" / "See more"
// The bullet point list that gets truncated
// =========================================================
const featureBulletExpanders = document.querySelectorAll(
[
'#featurebullets_feature_div .a-expander-header[aria-expanded="false"]',
'#feature-bullets .a-expander-header[aria-expanded="false"]',
'#featurebullets_feature_div a[data-action="a-expander-toggle"]',
].join(",")
);
featureBulletExpanders.forEach((el) => {
if (shouldSkipElement(el)) return;
const container = el.closest(".a-expander-partial-collapse-container");
if (
!container ||
container.classList.contains("a-expander-collapsed") ||
container.style.maxHeight
) {
if (safeClick(el)) expanded++;
}
});
// Also handle the partial-collapse style "もっと見る" links
const partialCollapseHeaders = document.querySelectorAll(
".a-expander-partial-collapse-header"
);
partialCollapseHeaders.forEach((header) => {
if (shouldSkipElement(header)) return;
const container = header.closest(
".a-expander-partial-collapse-container"
);
if (container && container.classList.contains("a-expander-collapsed")) {
if (safeClick(header)) expanded++;
}
});
// =========================================================
// 3. Bottom "商品情報" section - 商品詳細, サイズ, 機能と仕様, etc.
// These are the tabbed/accordion panels in the lower part of the page
// =========================================================
const productInfoExpanders = document.querySelectorAll(
[
// Product information section (bottom of page)
'#productDetails_expanderSectionTriggers .a-expander-header[aria-expanded="false"]',
'#prodDetails .a-expander-header[aria-expanded="false"]',
'#detailBullets_feature_div .a-expander-header[aria-expanded="false"]',
// "商品情報" accordion panels
'#productDetails_feature_div .a-expander-header[aria-expanded="false"]',
'#productDetails_db_sections .a-expander-header[aria-expanded="false"]',
'#productDetails_techSpec_sections .a-expander-header[aria-expanded="false"]',
// Newer layout with card-style panels
'.product-details-grid .a-expander-header[aria-expanded="false"]',
'#productDetails_expanderTrigger_702[aria-expanded="false"]',
].join(",")
);
productInfoExpanders.forEach((el) => {
if (shouldSkipElement(el)) return;
if (safeClick(el)) expanded++;
});
// =========================================================
// 4. Generic: any remaining collapsed expanders in product area
// =========================================================
const allCollapsedHeaders = document.querySelectorAll(
'.a-expander-header[aria-expanded="false"]'
);
allCollapsedHeaders.forEach((header) => {
if (!isInProductArea(header)) return;
if (shouldSkipElement(header)) return;
if (safeClick(header)) expanded++;
});
// =========================================================
// 4b. A+ Content Q&A sections (商品の説明 area)
// These are collapsible Q&A panels in the brand story / A+ section.
// Amazon uses an exclusive accordion (only one open at a time).
// We bypass the accordion logic by directly manipulating DOM/styles
// to force all panels open simultaneously.
// =========================================================
const aplusExpanders = document.querySelectorAll(
[
'#aplus_feature_div .a-expander-header[aria-expanded="false"]',
'#aplus .a-expander-header[aria-expanded="false"]',
'#aplusProductDescription .a-expander-header[aria-expanded="false"]',
'#productDescription_feature_div .a-expander-header[aria-expanded="false"]',
'.aplus-module .a-expander-header[aria-expanded="false"]',
'[class*="aplus"] .a-expander-header[aria-expanded="false"]',
].join(",")
);
aplusExpanders.forEach((el) => {
if (shouldSkipElement(el)) return;
if (safeClick(el)) expanded++;
});
// Force-expand A+ accordion panels by directly manipulating DOM
forceExpandAplusAccordions();
// =========================================================
// 5. Handle "表示を増やす" / "See more" text links specifically
// These may be <a> or <span> elements with specific text
// =========================================================
const allLinks = document.querySelectorAll(
"a.a-expander-header, span.a-expander-header, .a-expander-prompt"
);
allLinks.forEach((link) => {
// Skip links inside cells already expanded inline
const parentCell = link.closest("td");
if (parentCell && parentCell.dataset.inlineExpanded === "true") return;
// Skip links that are popover triggers (handled by inline expansion)
if (
link.hasAttribute("data-a-popover") ||
link.getAttribute("data-action") === "a-popover" ||
link.dataset.popoverBlocked === "true"
) return;
const text = link.textContent.trim();
const expandTexts = [
"表示を増やす",
"表示件数を増やす",
"さらに表示する",
"もっと見る",
"続きを見る",
"See more",
"Read more",
"Show more",
"Mehr anzeigen",
"Ver más",
"Voir plus",
"Mostra di più",
"Meer weergeven",
];
// Skip navigation links
if (shouldSkipElement(link)) return;
if (expandTexts.some((t) => text.includes(t))) {
const isAlreadyExpanded =
link.getAttribute("aria-expanded") === "true" ||
link
.closest(".a-expander-container")
?.classList.contains("a-expander-expanded");
if (!isAlreadyExpanded) {
if (safeClick(link)) expanded++;
}
}
});
// =========================================================
// 6. Product attribute table "表示を増やす" (truncated specs)
// The tech-spec / product-info table that truncates rows
// and shows a "表示を増やす ▼" link at the bottom.
// Uses various structures: a-truncate, showMoreLink, etc.
// =========================================================
// 6a. Handle a-truncate based "See more" in product tables
const truncateToggles = document.querySelectorAll(
[
".a-truncate-cut + .a-truncate-see-more",
".a-truncate .a-link-normal",
'#technicalSpecifications_feature_div a[href="javascript:void(0)"]',
'#productDetails_techSpec_section_1 a[href="javascript:void(0)"]',
].join(",")
);
truncateToggles.forEach((toggle) => {
// Skip if already handled by inline expansion
const parentCell = toggle.closest("td");
if (parentCell && parentCell.dataset.inlineExpanded === "true") return;
if (toggle.dataset.popoverBlocked === "true") return;
const container = toggle.closest(".a-truncate");
if (container && container.dataset.inlineExpanded === "true") return;
if (container && container.querySelector(".a-truncate-cut")) {
if (safeClick(toggle)) expanded++;
}
});
// 6b. Handle "See more" / "表示を増やす" links that expand hidden table rows
const tableExpanders = document.querySelectorAll(
[
"#poShowMoreLink",
"#showMoreLink",
".po-show-more a",
'a[data-action="po-show-more"]',
'#productOverview_feature_div a[href="javascript:void(0)"]',
".a-size-small.po-truncate-link a",
].join(",")
);
tableExpanders.forEach((link) => {
// Skip if already handled by inline expansion
const parentCell = link.closest("td");
if (parentCell && parentCell.dataset.inlineExpanded === "true") return;
if (link.dataset.popoverBlocked === "true") return;
if (
link.hasAttribute("data-a-popover") ||
link.getAttribute("data-action") === "a-popover"
) return;
const text = link.textContent.trim();
// Skip navigation links
if (shouldSkipElement(link)) return;
if (
text.includes("表示を増やす") ||
text.includes("表示件数を増やす") ||
text.includes("さらに表示する") ||
text.includes("See more") ||
text.includes("Show more")
) {
if (safeClick(link)) expanded++;
}
});
// 6c. Broad fallback: find any clickable element with expand text
// inside product detail/overview tables that hasn't been handled
const allClickables = document.querySelectorAll(
[
'#productOverview_feature_div a',
'#productOverview_feature_div span[role="button"]',
'#poExpander a',
'.po-expander a',
'#technicalSpecifications_feature_div a',
'#productDetails_techSpec_section_1 a',
'table.a-normal a',
'table.prodDetTable a',
].join(",")
);
allClickables.forEach((el) => {
// Skip if already handled by inline expansion
const parentCell = el.closest("td");
if (parentCell && parentCell.dataset.inlineExpanded === "true") return;
if (el.dataset.popoverBlocked === "true") return;
if (
el.hasAttribute("data-a-popover") ||
el.getAttribute("data-action") === "a-popover"
) return;
const text = el.textContent.trim();
// Skip navigation links
if (shouldSkipElement(el)) return;
if (text.includes("表示を増やす") || text.includes("表示件数を増やす") || text.includes("さらに表示する") || text.includes("See more")) {
if (safeClick(el)) expanded++;
}
});
return expanded;
}
/**
* Check if an element is within the product content area
* (excludes reviews, Q&A, recommendations, etc.)
*/
function isInProductArea(el) {
// Exclude areas we don't want to auto-expand
const excludeSelectors = [
"#reviewsMedley",
"#ask-btf_feature_div",
"#similarities_feature_div",
"#sp_detail",
"#sponsoredProducts",
"#rhf",
"#navFooter",
'[data-feature-name="reviewFeatureGroup"]',
"#smbLogoImg_feature_div",
"#smb_feature_div",
".smb-container",
"#olp_feature_div",
"#moreBuyingChoices_feature_div",
"#extraProductInfoTips_feature_div",
"#productAlert_feature_div",
"#legal_feature_div",
"#globalStoreBadgePopover_feature_div",
'[id*="smbLogo"]',
'[id*="smb_"]',
];
if (excludeSelectors.some((sel) => el.closest(sel))) {
return false;
}
// Include areas we want to expand
const includeSelectors = [
"#centerCol",
"#dp-container",
"#productDetails_feature_div",
"#detailBullets_feature_div",
"#productFactsDesktop_Section",
"#featurebullets_feature_div",
"#feature-bullets",
"#productOverview_feature_div",
"#productDescription_feature_div",
"#aplus_feature_div",
"#prodDetails",
"#productDetails_db_sections",
"#productDetails_techSpec_sections",
".product-details-grid",
'[id*="productDetail"]',
];
return includeSelectors.some((sel) => el.closest(sel));
}
/**
* Run expansion with retries to handle lazy-loaded content.
* Uses increasing delays to catch content that loads later.
*/
function runWithRetries() {
// Multiple attempts at increasing intervals to catch lazy-loaded content
const delays = [500, 1000, 1500, 2000, 3000, 4000, 6000, 9000];
delays.forEach((delay) => {
setTimeout(expandAllSections, delay);
});
}
// Inject CSS to ensure inline-expanded text displays properly
const style = document.createElement("style");
style.textContent = `
/* Force full text visible in product overview truncated cells */
[data-inline-expanded="true"] .a-truncate-full,
.a-truncate-full.dp-auto-expanded {
display: inline !important;
position: static !important;
clip: auto !important;
width: auto !important;
height: auto !important;
overflow: visible !important;
}
[data-inline-expanded="true"] .a-truncate-cut {
display: none !important;
}
[data-inline-expanded="true"] .a-truncate-see-more,
[data-inline-expanded="true"] a[data-action="a-popover"] {
display: none !important;
}
/* Force A+ FAQ accordion panels to stay open */
span[data-faq-question][aria-expanded="true"] ~ .aplus-answer,
span[data-faq-question][aria-expanded="true"] ~ p.aplus-answer,
li.faq-block .aplus-answer,
li.faq-block [id^="faq_a_"] {
display: block !important;
visibility: visible !important;
height: auto !important;
max-height: none !important;
overflow: visible !important;
opacity: 1 !important;
}
`;
document.head.appendChild(style);
// Initial run after page load
runWithRetries();
// Observe DOM changes for dynamically loaded content
const observer = new MutationObserver((mutations) => {
let shouldExpand = false;
for (const mutation of mutations) {
if (mutation.addedNodes.length > 0) {
for (const node of mutation.addedNodes) {
if (node.nodeType === 1 && node.querySelector) {
if (
node.querySelector('[aria-expanded="false"]') ||
node.querySelector(".a-expander-collapsed") ||
node.querySelector(".a-expander-header") ||
node.matches?.('[aria-expanded="false"]')
) {
shouldExpand = true;
break;
}
}
}
}
if (shouldExpand) break;
}
if (shouldExpand) {
setTimeout(expandAllSections, 500);
}
});
observer.observe(document.body, {
childList: true,
subtree: true,
});
})();