/**
 * Originally written by Travis Wilson for http://facetmap.com
 * Comments etc. mailed to trav at ciahq dotcom are welcome.
 * Freely redistributable if this notice remains intact.
 *
 * You must include dom-drag.js before including this file.
 * dom-drag is published by www.youngpup.net . Thanks, Aaron.
 *
 * Outstanding issues:
 * - tested so far on IE 6 and Firefox 1
 * - no reliable way to include another js file from here?
 * - insufficient error checks
 * - well, still somewhat half-assed and badly structured
 */

var MinMaxSlider = new Object();

MinMaxSlider.onloadQueue = null;
MinMaxSlider.registerByName = function(sliderFormName, countRequestFormName, commFrameId) {
    var onloadQueue = this.onloadQueue;
    if (onloadQueue == null) {
        onloadQueue = new Array();
        if (window.onload) {
            onloadQueue.push(window.onload);
        }
        window.onload = function(e) {
            for (var i=0; i<onloadQueue.length; i++) {
                onloadQueue[i](e);
            }
        }
    }
    onloadQueue.push(function() {
        initSpectrumForm(
            document.forms[sliderFormName],
            document.forms[countRequestFormName],
            document.getElementById(commFrameId)
        );
    });
}

/**
 * 
 * minInit and maxInit must be used instead of the input's "value" attribute,
 * since many browsers cache form input values.
 */
function initSpectrumForm(
    sForm, // form element
    commForm, // input form for server calls (null to disable)
    commFrame // output frame for backup reception of server call output (null to disable)
) {
    minInput = sForm.elements[sForm.getAttribute("minInputName")];
    minSlider = document.getElementById(sForm.getAttribute("minSliderId"));
    origMinValue = Number(sForm.getAttribute("minInit"));
    maxInput = sForm.elements[sForm.getAttribute("maxInputName")];
    maxSlider = document.getElementById(sForm.getAttribute("maxSliderId"));
    origMaxValue = Number(sForm.getAttribute("maxInit"));
    sliderPixelWidth = Number(sForm.getAttribute("sliderPixelWidth"));
    titleTemplate = sForm.getAttribute("titleTemplate");

    sForm.origMin = origMinValue;
    sForm.origMax = origMaxValue;
    sForm.elements.min.value = origMinValue;
    sForm.elements.max.value = origMaxValue;
    sForm.unitsPerPx = (sForm.origMax - sForm.origMin) / sliderPixelWidth;
    sForm.titleTemplate = titleTemplate;
    sForm.minInput = minInput;
    sForm.maxInput = maxInput;

    minSlider.style.left = "0px";
    minSlider.spectrum = sForm;
    minSlider.inputElement = sForm.elements.min;
    Drag.init(minSlider, null, 0, sliderPixelWidth, 0, 0);
    minSlider.onDrag = function(x, y) {
        changeSliderValue(this);
        if (getSliderPos(this) > getSliderPos(this.spectrum.maxSlider)) {
            this.spectrum.maxSlider.style.left = this.style.left;
            changeSliderValue(this.spectrum.maxSlider);
        }
    }
    sForm.minSlider = minSlider;

    maxSlider.style.left = sliderPixelWidth + "px";
    maxSlider.spectrum = sForm;
    maxSlider.inputElement = sForm.elements.max;
    Drag.init(maxSlider, null, 0, sliderPixelWidth, 13, 13);
    maxSlider.onDrag = function(x, y) {
        changeSliderValue(this);
        if (getSliderPos(this) < getSliderPos(this.spectrum.minSlider)) {
            this.spectrum.minSlider.style.left = this.style.left;
            changeSliderValue(this.spectrum.minSlider);
        }
    }
    sForm.maxSlider = maxSlider;

    // set up in-page server calls, if hooks are present
    if (commFrame != null && commForm != null) {

        commForm.target = commFrame.name;
        commForm.s.value = sForm.s.value;
        commForm.facetid.value = sForm.facetid.value;
        sForm.commForm = commForm;
        sForm.commFrame = commFrame;

        minSlider.onDragEnd = function(x, y) {
            sendCountRequest(this.spectrum);
        }
        maxSlider.onDragEnd = function(x, y) {
            sendCountRequest(this.spectrum);
        }

        commForm.formId.value = sForm.id;
    }
}

function sendCountRequest(spectrumForm) {
    spectrumForm.commForm.min.value = spectrumForm.min.value;
    spectrumForm.commForm.max.value = spectrumForm.max.value;

    var req = null;
    try {
        req = new ActiveXObject("Msxml2.XMLHTTP");
    } catch (exc) {
        try {
            req = new ActiveXObject("Microsoft.XMLHTTP");
        } catch (exc2) {
            req = null;
        }
    }
    if (req == null && typeof XMLHttpRequest != "undefined") {
        req = new XMLHttpRequest();
    }
    if (req != null) {
        var url = "/demo/countResults.jsp?";
        url += "&formId=" + escape(spectrumForm.commForm.formId.value);
        url += "&s=" + escape(spectrumForm.commForm.s.value);
        url += "&facetid=" + escape(spectrumForm.commForm.facetid.value);
        url += "&min=" + escape(spectrumForm.commForm.min.value);
        url += "&max=" + escape(spectrumForm.commForm.max.value);
        url += "&map=" + escape(spectrumForm.commForm.map.value);
        req.onreadystatechange = function() {
            if (req.readyState == 4) {
                var startIndex = req.responseText.indexOf(":") + 1;
                var endIndex = req.responseText.indexOf(";");
                var result = req.responseText.substring(startIndex, endIndex);
                displayResultCount(spectrumForm, result);
            }
        }
        req.open("GET", url);
        req.send(null);
    } else {
        // use iframe hack
        spectrumForm.commForm.submit();
    }
}

function receive(formId, result) {
    form = document.getElementById(formId);
    if (form != null) {
        displayResultCount(form, result);
    }

    // hack the history to remove this transaction; doesn't work on IE
    // window.history.back();
}

function sliderRangeTitle(sForm) {
    return sForm.titleTemplate.replace("%0", sForm.minInput.value).replace("%1", sForm.maxInput.value);
}

function getSliderPos(slider) {
    return parseInt(slider.style.left);
}

function getSliderValue(slider) {
    var exactValue =
        parseInt(slider.style.left)
         * slider.spectrum.unitsPerPx
         + slider.spectrum.origMin;
    return Math.round(exactValue);
}

function changeSliderValue(slider) {
    slider.inputElement.value = getSliderValue(slider);
    slider.spectrum.submit.value = "Select " + sliderRangeTitle(slider.spectrum);
}

function displayResultCount(spectrum, result) {
    spectrum.submit.value = "Select " + sliderRangeTitle(spectrum) + " (" + result + ")";
}

