// ==UserScript== // @name Collapsing Paragraphs // @namespace http://chrislord.net/ // @description Collapses paragraphs to a GtkExpander-like structure // @include * // ==/UserScript== ssr_style = "/* The feel-like-a-cellphone stylesheet" + "\n" + " *" + "\n" + " * (c) Netscape Communications Corporation 2002" + "\n" + " * " + "\n" + " * Original Author: Daniel Glazman " + "\n" + "*/" + "\n" + "* {" + "\n" + " /* on a small screen, we need to use a readable font */" + "\n" + " /* Note: We don't do this with gtkhtml2 as font sizes are relative to the" + "\n" + " * default, which will be set to a readable size already." + "\n" + " */" + "\n" + "/* font-size: small ! important;*/" + "\n" + "}" + "\n" + "/* for all elements but the root element and the body, let's */" + "\n" + "/* cancel all annoying document's settings */ " + "\n" + "* {" + "\n" + " /* first cancel all size settings */" + "\n" + " width: auto ! important;" + "\n" + " height: auto ! important;" + "\n" + " /* and make the width adjust to screen layout for the device */" + "\n" + " max-width: 100% ! important;" + "\n" + " /* remove all positioning */" + "\n" + " position: static ! important;" + "\n" + " /* remove all positioning offsets */" + "\n" + " top: auto ! important;" + "\n" + " left: auto ! important;" + "\n" + " /* and cancel floats */" + "\n" + " float: none ! important;" + "\n" + " /* margins and paddings have to be changed */" + "\n" + " padding: 0px ! important;" + "\n" + " margin: 0px ! important;" + "\n" + " /* avoid overflow on pre and table cells */" + "\n" + " white-space: normal ! important;" + "\n" + " /* Remove any background images */" + "\n" + " background-image: none ! important;" + "\n" + "}" + "\n" + //"/* we need to \"flatten\" all tables */" + "\n" + //"table,tbody,thead,tfoot,tr,td,th,col,colgroup {" + "\n" + //" display: block ! important;" + "\n" + //"}" + "\n" + "img[width=\"1\"], img[height=\"1\"],img[width=\"468\"], img[height=\"600\"] {" + "\n" + " /* let's get rid of 1 pixel wide/high images */" + "\n" + " /* and of std formats of ads ; current ads formats are */" + "\n" + " /* too big for small screens */" + "\n" + " display: none ! important;" + "\n" + "}" + "\n" + "li {" + "\n" + " /* better placement of the bullet on a small screen */" + "\n" + " list-style-position: inside ! important;" + "\n" + "}" + "\n" + "a {" + "\n" + " /* we need to make anchors more visible */" + "\n" + " text-decoration: underline !important;" + "\n" + "}"; function getText (element, size) { for (var child = element.firstChild; child; child = child.nextSibling) { if ((child.nodeType == child.TEXT_NODE) && (child.nodeValue.length >= size)) { return child.nodeValue; } else { if ((element.tagName != "A") && (element.nodeType != child.COMMENT_NODE) && (element.tagName != "SCRIPT")) { var text = getText (child, size); if (text) return text; } } } return null; } function flatten (element) { if ((element.tagName == "TABLE") || (element.tagName == "TBODY") || (element.tagName == "THEAD") || (element.tagName == "TFOOT") || (element.tagName == "TR") || (element.tagName == "TD") || (element.tagName == "TH") || (element.tagName == "COL") || (element.tagName == "COLGROUP")) { element.style.display = "block"; // element.setAttribute ("style", "display: block ! important;"); } for (var child = element.firstChild; child; child = child.nextSibling) flatten (child); } function flatten_table (element) { if ((!element) || (element.nodeType != element.ELEMENT_NODE)) return; if (element.tagName == "TABLE") { flatten (element); } flatten_table (element.parentNode); } function collapse (element, min_size, summary_size, ellipses_size) { var text, para, event; if (element.nodeType == element.TEXT_NODE) text = element.nodeValue; else { text = getText (element, min_size); if (!text) return; text = getText (element, summary_size); } if (text.length > ellipses_size) text = text.substr(0, ellipses_size - 3) + "..."; para = document.createElement ("p"); para.appendChild (document.createTextNode (text)); para.style.textDecoration = "underline"; para.style.cursor = "pointer"; element.parentNode.insertBefore (para, element); /* Note, some firefox bugs (or at least, things that go against docs): * - DOM elements have no 'click' function * http://www.mozilla.org/docs/dom/domref/dom_el_ref34.html#1028373 * - Can't set 'onclick' by doing element.onclick = ...; * http://www.mozilla.org/docs/dom/domref/dom_event_ref.html#998197 * - Works in Firefox < 1.5 * - dispatchEvent example is wrong * http://www.mozilla.org/docs/dom/domref/dom_el_ref36.html#1028419 */ para.addEventListener ("click", function (e) { var node = this.nextSibling; var j, new_display, old_display; if (node.hasAttribute ("old-display")) old_display = node.getAttribute ("old-display"); else old_display = "none"; node.setAttribute ("old-display", node.style.display); node.style.display = old_display; }, true); event = document.createEvent ("MouseEvents"); event.initEvent ("click", true, true); para.dispatchEvent (event); } function collapse_image (image) { var para, event; para = document.createElement ("p"); para.appendChild (document.createTextNode ("Hide image")); para.style.textDecoration = "underline"; para.style.cursor = "pointer"; para.style.border = "1px dashed #CCCCCC"; image.parentNode.insertBefore (para, image); para.addEventListener ("click", function (e) { var node = this.nextSibling; var j, new_display, old_display; if (node.hasAttribute ("old-display")) old_display = node.getAttribute ("old-display"); else old_display = "none"; node.setAttribute ("old-display", node.style.display); node.style.display = old_display; if (node.style.display == "none") { this.firstChild.nodeValue = "View image"; } else { this.firstChild.nodeValue = "Hide image"; } }, true); event = document.createEvent ("MouseEvents"); event.initEvent ("click", true, true); para.dispatchEvent (event); } function is_parent (parent, element) { if (!element) { return false; } if (element == parent) { return true; } else return is_parent (parent, element.parentNode); } function should_flatten (element) { if ((!element) || (element.nodeType != element.ELEMENT_NODE)) return false; /* This needs to special-case more elements, or maybe exclude elements * instead... Most pages look alright though */ for (var child = element.firstChild; child; child = child.nextSibling) { if ((child.tagName == "IMG") || (child.tagName == "INPUT") || (should_flatten (child))) return true; } return false; } function getTextParents (array, element, size) { /* Stop at certain tags */ if ((element.nodeType != element.ELEMENT_NODE) || (element.tagName == "A") || (element.tagName == "SCRIPT")) return array; for (var child = element.firstChild; child; child = child.nextSibling) { if (child.nodeType == child.TEXT_NODE) { if ((child.nodeValue.length >= size) && (element.tagName != "BODY")) { array.push (element); break; } } else getTextParents (array, child, size); } return array; } /* Add stylesheet if there's no hand-held stylesheet */ head = document.getElementsByTagName ("head")[0]; if (head) { do_ssr = true; if (document.styleSheets) { for (i = 0; i < document.styleSheets.length; i++) if (document.styleSheets[i].media == "handheld") do_ssr = false; } if (do_ssr) { style = document.createElement ("style"); style.setAttribute ("type", "text/css"); style.appendChild (document.createTextNode (ssr_style)); head.appendChild (style); /* Flatten big tables/tables with images */ tables = document.getElementsByTagName ("table"); for (i = 0; i < tables.length; i++) { if ((should_flatten (tables[i])) || (getText (tables[i], 80))) flatten (tables[i]); } } } /* Collapse images */ /*img_array = document.getElementsByTagName ("img"); for (i = 0; i < img_array.length; i++) { if (img_array[i].parentNode.tagName == "A") collapse_image (img_array[i].parentNode); else collapse_image (img_array[i]); }*/ /* Flatten tables with long paragraphs in them */ /*collapse_array = getTextParents (new Array (), document.body, 80); for (i = 0; i < collapse_array.length; i++) { collapse (collapse_array[i], 80, 10, 40); }*/