// UBBpreserveWidth.user.js
// (c) 2005 by Steve Grantz
//
// UBB forums are used at many web sites such as the popular 2+2 poker forum.
// However there are sometimes format issues that cause posts to spread 
// horizontally, making it tedious to read other posts on the same page.
//
// This script attempts to enforce page width by addressing the two most
// common causes of this horizontal sprawl:
// (1) long anchor text without whitespace, caused by posting a long link
//     and using the URL for the text
// (2) included images that are wider than the page
//
// The first item is readily taken care of by examining anchors and
// replacing the text if the text is longer than 80 characters without
// whitepsace for breaking. The number 80 works well for 1024x768
// resolution.
//
// The second item is more troublesome because it relies on the document
// knowing the size of included images. Sometimes it does not work
// because the script acts before the images are loaded. This should be 
// fixed. For now, users can refresh the page after all images load,
// and often that will resize the images.
//
// The script uses a stored value for the maximum image size, as
// selected by the user the first time the script is run. Use the
// menu option Tools > User script commands > Reset UBB page max image width
// to force the script to prmpt again and change the value.
//
//
// ==UserScript==
// @name           Preserve width of UBB page
// @namespace      http://www.visi.com/~sgrantz
// @description    Enforces page width by replacing long URL text and by resizing large images. Prompts user for max image size on 1st use. To reset, go to Tools > User script commands > Reset UBB page max image width
// @include        http://forumserver.twoplustwo.com/*
// ==/UserScript==

    const urlRegex = /\S{80}\S+/;
    const defMaxImageWidth=600;

    var maxImageWidth=defMaxImageWidth;

    // We store the maximum image size preferred by the user.
    // If this is 0 or not set, we prompt the user again. 
    // The 0 test is to accout for something odd.
    if(!GM_getValue('maxImageWidth') || GM_getValue == 0) {
       promptForMaxImageWidth();
       maxImageWidth = GM_getValue('maxImageWidth');
    } else {
       maxImageWidth = GM_getValue('maxImageWidth');
    }

    // count of changed items, to determine if page should be redrawn
    var changedCount = 0;

    // find all images that are inside posts. Uses quirks of the UBB 
    // post display HTML. once it finds the images, attempts to 
    // learn their size, and if they exceed the maximum allowed 
    // width, changes the attributes to resize the image,
    // preserving the aspect ratio.
    var xpath = "//font[@class='post']//img";
    var candidates = document.evaluate(xpath, document, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);

    var t0 = new Date().getTime();
    var found = 0;
    var aspectRatio = 1;
    for (var cand = null, i = 0; (cand = candidates.snapshotItem(i)); i++) {
        if (cand.width > maxImageWidth) {
           found++;
           aspectRatio = cand.height / cand.width;
           cand.setAttribute("width",maxImageWidth);
           cand.setAttribute("height",Math.round(maxImageWidth * aspectRatio));
           changedCount++;
        }	
    }
    var t1 = new Date().getTime();

    // tags we will scan looking for long anchor text without whitespace
    var allowedParents = [
        "a" 
        ];
    
    xpath = "//text()[(parent::" + allowedParents.join(" or parent::") + ")]";

    candidates = document.evaluate(xpath, document, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);

    t0 = new Date().getTime();
    for (var cand = null, i = 0; (cand = candidates.snapshotItem(i)); i++) {
        if (urlRegex.test(cand.nodeValue)) {
            cand.nodeValue = "(long text replaced)";
            changedCount++;
        }
    }
    t1 = new Date().getTime();
    //alert((t1 - t0) / 1000);

   
    // Add a menu item to Tools > User Script Commands to 
    // change the maximum width for images.
    GM_registerMenuCommand("Reset UBB page max image width", promptForMaxImageWidth);

    // Prompt the user for the preferred maximum image size. 
    // Will only accept whole numbers 
    function promptForMaxImageWidth() {
       var maxImageWidth = prompt("Please select the maximum image width. 600 is suggested for 1024x768 resolution, 800 for higher resolution.",defMaxImageWidth);
       while (!maxImageWidth.match(/^\d+$/) || maxImageWidth < 1) {
           maxImageWidth = prompt("You must select a number.\nPlease select the maximum image width. 600 is suggested for 1024x768 resolution, 800 for higher resolution.",defMaxImageWidth);
       }
       GM_setValue('maxImageWidth',Math.round(maxImageWidth));
    }
