// +----------------------------------------------------------------+
// | ahoy 1.1                                                       |
// +----------------------------------------------------------------+
// | Copyright (c) 2002-2003 Brian Donovan                          |
// +----------------------------------------------------------------+
// | This program is free software; you can redistribute it and/or  |
// | modify it under the terms of the GNU General Public License    |
// | as published by the Free Software Foundation; either version 2 |
// | of the License, or (at your option) any later version.         |
// |                                                                |
// | This program is distributed in the hope that it will be useful,|
// | but WITHOUT ANY WARRANTY; without even the implied warranty of |
// | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the  |
// | GNU General Public License for more details.                   |
// |                                                                |
// | You should have received a copy of the GNU General Public      |
// | License along with this program; if not, write to :            |
// | Free Software Foundation, Inc.,                                |
// | 59 Temple Place - Suite 330,                                   |
// | Boston, MA  02111-1307, USA.                                   |
// +----------------------------------------------------------------+
// | Author: Brian Donovan <ahoy-technical@lophty.com>              |
// | Latest version : <http://dev.lophty.com/ahoy/>                 |
// +----------------------------------------------------------------+

//---------------------------------------------------
//------------------- Changes -----------------------
//---------------------------------------------------
//
// Patches
//
// May 6, 2003 => v 1.1
// *  : Mozilla developers (as of Moz v 1.3+ apparently) changed the 
// target property of the event object generated during mousedown, mouseup events 
// so that it no longer points to the text node within which the Mouse event was
// fired, but instead points to the nearest element node above that text node in
// in the DOM hierarchy, so I'm relying more upon Mozilla's nonstandard Selection
// objects (using the anchorNode and focusNode properties).
//---------------------------------------------------

var objSelectedTextRange = null;
var objAhyAnchor = null;
var objAhyAnchorCreatedParentNode = null;

var intThisAhoyVersion = 1.1;

function numberSort(n1,n2) 
{
    if (n1<n2){
        retVal=-1;
    }else if(n1>n2){
        retVal=1;
    }else{
        retVal=0;
    }
    return retVal;
}

function ahy_ScrubQueryString(strScrubbingMode)
{
    if(arguments.length != 1){
        strScrubbingMode = "querystring";
    } else if((strScrubbingMode != "querystring") && (strScrubbingMode != "ahoyparams")){
        return false;
    }
    var strQueryString = location.search;
    var intQueryStringLength = strQueryString.length;
    var intIndexBeginAhoyParamsAtBeginning = strQueryString.indexOf("?ahyAnchor");
    var intIndexBeginAhoyParams = strQueryString.indexOf("&ahyAnchor");
    var arrBeginIndices = [intIndexBeginAhoyParamsAtBeginning, intIndexBeginAhoyParams];
    arrBeginIndices.sort(numberSort);
    if(arrBeginIndices[1] != -1){
        var intIndexAhoySelIndexParam = strQueryString.indexOf("ahySelectionLength", arrBeginIndices[1]);
        if(intIndexAhoySelIndexParam != -1){
            var intIndexAmpersand = strQueryString.indexOf("&", intIndexAhoySelIndexParam);
            var intEndAhoyParams = -1;
            if(intIndexAmpersand != -1){
                intEndAhoyParams = intIndexAmpersand;
            }else{
                intEndAhoyParams = intQueryStringLength;
            }
            var strQueryForReturn = '';
            if(strScrubbingMode == "querystring"){
                if(intIndexBeginAhoyParamsAtBeginning != -1){
                    if(intIndexAmpersand != -1){
                        strQueryForReturn = strQueryString.substring(0, (intIndexBeginAhoyParamsAtBeginning + 1));
                    }else{
                        strQueryForReturn = strQueryString.substring(0, intIndexBeginAhoyParamsAtBeginning);
                    }
                    strQueryStringBeforeAhoy = strQueryString.substring();
                }else{
                    if(intIndexAmpersand != -1){
                        var strQueryStringBeforeAhoyParams = strQueryString.substring(0, intIndexBeginAhoyParams);
                        var strQueryStringAfterAhoyParams = strQueryString.substring(intIndexAmpersand, (intQueryStringLength + 1));
                        strQueryForReturn = strQueryStringBeforeAhoyParams + strQueryStringAfterAhoyParams;
                    }else{
                        strQueryForReturn = strQueryString.substring(0, intIndexBeginAhoyParams);
                    }
                }
            }else{
                var arrEndIndices = [intIndexAmpersand, intQueryStringLength];
                arrEndIndices.sort(numberSort);
                strQueryForReturn = strQueryString.substring(arrBeginIndices[1], arrEndIndices[1]);
            }
            return strQueryForReturn;
        }else{
            return false;
        }
    }else{
        if(strScrubbingMode == "querystring"){
            return strQueryString;
        }else{
            return false;
        }
    }
}


function ahyObjSelectedTextRange(objExistingAnchorParentNode)
{
    ahyObjSelectedTextRange.prototype.nodeExistingAnchorParentNode = objExistingAnchorParentNode;
    ahyObjSelectedTextRange.prototype.ahyMousedownContainer = null;
    ahyObjSelectedTextRange.prototype.ahyMouseupContainer = null;
    ahyObjSelectedTextRange.prototype.ahySelection = null;
    ahyObjSelectedTextRange.prototype.ahySelectionString = null;
    ahyObjSelectedTextRange.prototype.ahySelectionLength = null;
    ahyObjSelectedTextRange.prototype.ahySelectionStartOffset = null;
    ahyObjSelectedTextRange.prototype.ahyParentNodeForAnchor = null;
    ahyObjSelectedTextRange.prototype.ahyChildNodeOfParentNodeForAnchorToSeek = null;
    ahyObjSelectedTextRange.prototype.ahyParentNodeTagName = null;
    ahyObjSelectedTextRange.prototype.ahySelectionParentNodeElementID = null;
    ahyObjSelectedTextRange.prototype.ahyParentNodeIndex = null;
    ahyObjSelectedTextRange.prototype.ahySelectionThisNodeIndex = null;
    ahyObjSelectedTextRange.prototype.ahyQueryStringFragment = null;
    ahyObjSelectedTextRange.prototype.ahy_EndSelect = ahy_EndSelect;
    ahyObjSelectedTextRange.prototype.ahy_ScrubQueryString = ahy_ScrubQueryString;

    function ahy_EndSelect(event)
    {
        if (event.altKey){
            //---------------------------------------------------
            // In Mozilla, getSelection returns a Selection object whose
            // properties are undocumented. See http://www.pbwizard.com/Articles/Moz_Range_Object_Article.htm
            // for more information.
            //---------------------------------------------------
            //=====================================
            // proprietary Moz dom stuff
            //=====================================
            this.ahySelection = window.getSelection();

            this.ahyMousedownContainer = this.ahySelection.anchorNode;
            this.ahyMouseupContainer = this.ahySelection.focusNode;

            this.ahySelectionString = this.ahySelection.toString();
            this.ahySelectionLength = this.ahySelectionString.length;
            var intSelectionAnchorOffset = this.ahySelection.anchorOffset;
            var intSelectionFocusOffset = this.ahySelection.focusOffset;
            //=====================================
            if(this.ahySelectionLength == 0){
                alert("Zero Characters Selected");
                return false;
            }
            strMouseupContainerNodeValue = this.ahyMouseupContainer.nodeValue;
            if(this.ahyMouseupContainer.nodeType == 3){
                if (this.ahyMouseupContainer.parentNode.nodeType == 1){
                    var objPreExistingAnchorSpan = document.getElementById("ahoypreanchorspan");
                    var objExistingAnchorSpan = document.getElementById("ahoyanchorid");
                    var objPostExistingAnchorSpan = document.getElementById("ahoypostanchorspan");
                    if(((this.ahyMouseupContainer.parentNode == objPreExistingAnchorSpan)||
                        (this.ahyMouseupContainer.parentNode == objExistingAnchorSpan)||
                        (this.ahyMouseupContainer.parentNode == objPostExistingAnchorSpan)
                        )&&((this.ahyMousedownContainer.parentNode == objPreExistingAnchorSpan)||
                        (this.ahyMousedownContainer.parentNode == objExistingAnchorSpan)||
                        (this.ahyMousedownContainer.parentNode == objPostExistingAnchorSpan)
                        )){
                        this.ahyParentNodeForAnchor = this.ahyMouseupContainer.parentNode.parentNode;
                        var strPreExistingAnchorSpanTextNodeVal = '';
                        var strExistingAnchorSpanTextNodeVal = '';
                        var strPostExistingAnchorSpanTextNodeVal = '';
                        var intMouseDownTextNodeParentFlag = 0;
                        var intMouseUpTextNodeParentFlag = 0;
                        if(objPreExistingAnchorSpan != null){
                            strPreExistingAnchorSpanTextNodeVal = objPreExistingAnchorSpan.childNodes[0].nodeValue;
                            if(this.ahyMousedownContainer == objPreExistingAnchorSpan.childNodes[0]){
                                intMouseDownTextNodeParentFlag = 1;
                            }
                            if(this.ahyMouseupContainer  == objPreExistingAnchorSpan.childNodes[0]){
                                intMouseUpTextNodeParentFlag = 1;
                            }
                        }
                        if(objExistingAnchorSpan != null){
                            strExistingAnchorSpanTextNodeVal = objExistingAnchorSpan.childNodes[0].nodeValue;
                            if(this.ahyMousedownContainer == objExistingAnchorSpan.childNodes[0]){
                                intMouseDownTextNodeParentFlag = 2;
                            }
                            if(this.ahyMouseupContainer  == objExistingAnchorSpan.childNodes[0]){
                                intMouseUpTextNodeParentFlag = 2;
                            }
                        }
                        if(objPostExistingAnchorSpan != null){
                            strPostExistingAnchorSpanTextNodeVal = objPostExistingAnchorSpan.childNodes[0].nodeValue;
                            if(this.ahyMousedownContainer == objPostExistingAnchorSpan.childNodes[0]){
                                intMouseDownTextNodeParentFlag = 3;
                            }
                            if(this.ahyMouseupContainer  == objPostExistingAnchorSpan.childNodes[0]){
                                intMouseUpTextNodeParentFlag = 3;
                            }
                        }
                        if(intMouseDownTextNodeParentFlag == intMouseUpTextNodeParentFlag){
                            var arrSelectionOffsets = [intSelectionAnchorOffset, intSelectionFocusOffset]
                            arrSelectionOffsets.sort(numberSort);
                            this.ahySelectionStartOffset = arrSelectionOffsets[0];
                        }
                        if((intMouseDownTextNodeParentFlag == 1)&&(intMouseUpTextNodeParentFlag == 1)){
                            intNumCharBeginSelectionInNodeValue = strMouseupContainerNodeValue.indexOf(this.ahySelectionString);
                            if(intNumCharBeginSelectionInNodeValue > this.ahySelectionStartOffset){
                                this.ahySelectionStartOffset = intNumCharBeginSelectionInNodeValue;
                            }
                        }
                        if((intMouseDownTextNodeParentFlag == 2)&&(intMouseUpTextNodeParentFlag == 2)){
                            intNumCharBeginSelectionInNodeValue = strMouseupContainerNodeValue.indexOf(this.ahySelectionString);
                            if(intNumCharBeginSelectionInNodeValue > this.ahySelectionStartOffset){
                                this.ahySelectionStartOffset = intNumCharBeginSelectionInNodeValue;
                            }
                            this.ahySelectionStartOffset = this.ahySelectionStartOffset + strPreExistingAnchorSpanTextNodeVal.length;
                        }
                        if((intMouseDownTextNodeParentFlag == 3)&&(intMouseUpTextNodeParentFlag == 3)){
                            intNumCharBeginSelectionInNodeValue = strMouseupContainerNodeValue.indexOf(this.ahySelectionString);
                            if(intNumCharBeginSelectionInNodeValue > this.ahySelectionStartOffset){
                                this.ahySelectionStartOffset = intNumCharBeginSelectionInNodeValue;
                            }
                            this.ahySelectionStartOffset = this.ahySelectionStartOffset + strPreExistingAnchorSpanTextNodeVal.length + strExistingAnchorSpanTextNodeVal.length;
                        }
                        if((intMouseDownTextNodeParentFlag == 1) && ((intMouseUpTextNodeParentFlag == 2) || (intMouseUpTextNodeParentFlag == 3))){
                            this.ahySelectionStartOffset = intSelectionAnchorOffset;
                        }
                        if((intMouseDownTextNodeParentFlag == 2) && (intMouseUpTextNodeParentFlag == 3)){
                            this.ahySelectionStartOffset =  strPreExistingAnchorSpanTextNodeVal.length + intSelectionAnchorOffset;
                        }
                        if((intMouseDownTextNodeParentFlag == 2) && (intMouseUpTextNodeParentFlag == 1)){
                            this.ahySelectionStartOffset =  intSelectionFocusOffset;
                        }
                        if((intMouseDownTextNodeParentFlag == 3) && (intMouseUpTextNodeParentFlag == 2)){
                            this.ahySelectionStartOffset =  strPreExistingAnchorSpanTextNodeVal.length + intSelectionFocusOffset;
                        }
                        if((intMouseDownTextNodeParentFlag == 3) && (intMouseUpTextNodeParentFlag == 1)){
                            this.ahySelectionStartOffset =  intSelectionFocusOffset;
                        }
                        if(objPreExistingAnchorSpan != null){
                            this.ahyChildNodeOfParentNodeForAnchorToSeek = objPreExistingAnchorSpan;
                        }else{
                            this.ahyChildNodeOfParentNodeForAnchorToSeek = objExistingAnchorSpan;
                        }
                    }else if((this.ahyMousedownContainer == this.ahyMouseupContainer)&&
                                    (
                                        ((objExistingAnchorParentNode == this.ahyMouseupContainer.parentNode)) &&
                                        ((objExistingAnchorParentNode == this.ahyMousedownContainer.parentNode))
                                    )
                                ){
                        var intNumAhoyNodes = 0;
                        var intIndexMouseEventsNode=0;
                        for(var i=0; i<this.ahyMouseupContainer.parentNode.childNodes.length; i++){
                            if((this.ahyMouseupContainer.parentNode.childNodes[i] == objPreExistingAnchorSpan)||
                                (this.ahyMouseupContainer.parentNode.childNodes[i] == objExistingAnchorSpan)||
                                (this.ahyMouseupContainer.parentNode.childNodes[i] == objPostExistingAnchorSpan)){
                                intNumAhoyNodes++;
                             }else if(this.ahyMousedownContainer == this.ahyMouseupContainer.parentNode.childNodes[i]){
                                if(intNumAhoyNodes > 0){
                                    intIndexMouseEventsNode = i - (intNumAhoyNodes - 1);
                                }else{
                                    intIndexMouseEventsNode = i;
                                }
                                break;
                            }
                        }
                        var arrSelectionOffsets = [intSelectionAnchorOffset, intSelectionFocusOffset]
                        arrSelectionOffsets.sort(numberSort);
                        this.ahySelectionStartOffset = arrSelectionOffsets[0];
                        this.ahyParentNodeForAnchor = this.ahyMouseupContainer.parentNode;
                        this.ahyChildNodeOfParentNodeForAnchorToSeek = this.ahyMouseupContainer;
                    }else if(this.ahyMousedownContainer == this.ahyMouseupContainer){
                        this.ahyParentNodeForAnchor = this.ahyMouseupContainer.parentNode;
                        var arrSelectionOffsets = [intSelectionAnchorOffset, intSelectionFocusOffset]
                        arrSelectionOffsets.sort(numberSort);
                        this.ahySelectionStartOffset = arrSelectionOffsets[0];
                        intNumCharBeginSelectionInNodeValue = strMouseupContainerNodeValue.indexOf(this.ahySelectionString);
                        if(intNumCharBeginSelectionInNodeValue > this.ahySelectionStartOffset){
                            this.ahySelectionStartOffset = intNumCharBeginSelectionInNodeValue;
                        }
                        this.ahyChildNodeOfParentNodeForAnchorToSeek = this.ahyMouseupContainer;
                    }else{
                        alert("start and end in different nodes ! ");
                        return false;
                    }
                    if(this.ahyParentNodeForAnchor.hasAttribute("ID")){
                        this.ahySelectionParentNodeElementID = this.ahyParentNodeForAnchor.getAttribute("ID");
                    }else{
                        this.ahyParentNodeTagName = this.ahyParentNodeForAnchor.nodeName;
                        var arrDocumentGetElementsByTagName = document.getElementsByTagName(this.ahyParentNodeTagName);
                        for(var i=0; i< arrDocumentGetElementsByTagName.length; i++){
                            if(arrDocumentGetElementsByTagName[i] == this.ahyParentNodeForAnchor){
                                this.ahyParentNodeIndex = i;
                                break;
                            }
                        }
                    }
                    for(var i=0; i < this.ahyParentNodeForAnchor.childNodes.length; i++){
                        if(this.ahyParentNodeForAnchor.childNodes[i] == this.ahyChildNodeOfParentNodeForAnchorToSeek){
                            if(intIndexMouseEventsNode > 0){
                                this.ahySelectionThisNodeIndex = intIndexMouseEventsNode;
                            } else{
                                this.ahySelectionThisNodeIndex = i;
                            }
                            break;
                        }
                    }
                    if( this.ahySelectionParentNodeElementID == null){
                        this.ahyQueryStringFragment = "ahyAnchor="+intThisAhoyVersion+"&ahyParentNodeTagName="+this.ahyParentNodeTagName+"&ahyParentNodeIndex="+this.ahyParentNodeIndex+"&ahyChildIndex="+this.ahySelectionThisNodeIndex+"&ahySelectionStart="+this.ahySelectionStartOffset+"&ahySelectionLength="+this.ahySelectionLength;
                    } else{
                        this.ahyQueryStringFragment = "ahyAnchor="+intThisAhoyVersion+"&ahyParentNodeID="+this.ahySelectionParentNodeElementID+"&ahyChildIndex="+this.ahySelectionThisNodeIndex+"&ahySelectionStart="+this.ahySelectionStartOffset+"&ahySelectionLength="+this.ahySelectionLength;
                    }
                    var strNewHref = location.protocol+"//"+location.host+location.pathname;
                    if(location.search == ''){
                        location.href = strNewHref + "?"+this.ahyQueryStringFragment+"#ahoyanchor";
                    }else{
                        var strScrubbedQueryString = ahy_ScrubQueryString();
                        if(strScrubbedQueryString != ''){
                            strNewHref  += strScrubbedQueryString + "&" + this.ahyQueryStringFragment+"#ahoyanchor";
                        }else{
                            strNewHref  += "?" + this.ahyQueryStringFragment+"#ahoyanchor";
                        }
                        location.href = strNewHref;
                    }
                }else{
                    alert("Parent node is not an element node \n nodeType : " + this.ahyMouseupContainer.parentNode.nodeType  + "\n nodeName : " + this.ahyMouseupContainer.parentNode.nodeName);
                    return false;
                }
            }else{
                alert("Not a text node ! ");
                return false;
            }
        }
    }

}

function ahyObjAnchor()
{
    ahyObjAnchor.prototype.ahyQueryStringParamsString = null;
    ahyObjAnchor.prototype.ahyAnchorPropertiesArr = null;
    ahyObjAnchor.prototype.ahySelectionParentNode = null;
    ahyObjAnchor.prototype.ahySelectionChildNode = null;
    ahyObjAnchor.prototype.ahyRangeObj = null;
    ahyObjAnchor.prototype.ahyRangeContentsBeforeAnchor = null;
    ahyObjAnchor.prototype.ahyDocumentFragmentToInsert = null;
    ahyObjAnchor.prototype.ahyInsertedAnchorNode = null;
    ahyObjAnchor.prototype.ahy_FetchAhyQueryParamsString = ahy_ScrubQueryString;
    ahyObjAnchor.prototype.ahy_ParseAhyQueryParamsString = ahy_ParseAhyQueryParamsString;
    ahyObjAnchor.prototype.ahy_ParseOneAhyParam = ahy_ParseOneAhyParam;
    ahyObjAnchor.prototype.ahy_CreateAnchor = ahy_CreateAnchor;

    function ahy_ParseOneAhyParam(strAhyParamName)
    {
        var intIndexAhyParamValuePairStart = this.ahyQueryStringParamsString.indexOf(strAhyParamName);
        if(intIndexAhyParamValuePairStart!= -1){
            var intIndexAhyParamValuePairStop = this.ahyQueryStringParamsString.indexOf("&",intIndexAhyParamValuePairStart);
            if(intIndexAhyParamValuePairStop == -1){
                intIndexAhyParamValuePairStop = this.ahyQueryStringParamsString.length;
            }
            var strAhyParamValuePair = this.ahyQueryStringParamsString.substring(intIndexAhyParamValuePairStart, intIndexAhyParamValuePairStop);
            var arrAhyParamValuePair = strAhyParamValuePair.split("=");
            var intLengthArrAhyParamVauePair = arrAhyParamValuePair.length;
            if(intLengthArrAhyParamVauePair == 2){
                return arrAhyParamValuePair[1];
            } else{
                return -1;
            }
        }else{
            return -1;
        }
    }

    function ahy_ParseAhyQueryParamsString()
    {
        this.ahyAnchorPropertiesArr = new Array();
        if(this.ahyQueryStringParamsString.indexOf("ahyParentNodeID") != -1){
            this.ahyAnchorPropertiesArr["parentnodeid"] = this.ahy_ParseOneAhyParam("ahyParentNodeID");
            this.ahyAnchorPropertiesArr["parentnodetagname"] = null;
            this.ahyAnchorPropertiesArr["parentnodeindex"] = null;
            if(this.ahyAnchorPropertiesArr["parentnodeid"] == -1){
                return false;
            }
        }else if((this.ahyQueryStringParamsString.indexOf("ahyParentNodeTagName") != -1)&&(this.ahyQueryStringParamsString.indexOf("ahyParentNodeIndex") != -1)){
            this.ahyAnchorPropertiesArr["parentnodeid"] = null;
            this.ahyAnchorPropertiesArr["parentnodetagname"] = this.ahy_ParseOneAhyParam("ahyParentNodeTagName");
            this.ahyAnchorPropertiesArr["parentnodeindex"] = parseInt(this.ahy_ParseOneAhyParam("ahyParentNodeIndex"));
            if((this.ahyAnchorPropertiesArr["parentnodetagname"] == -1) || (this.ahyAnchorPropertiesArr["parentnodeindex"] == -1)){
                return false;
            }
        }else{
            return false;
        }
        this.ahyAnchorPropertiesArr["childnodeindex"] = parseInt(this.ahy_ParseOneAhyParam("ahyChildIndex"));
        this.ahyAnchorPropertiesArr["selectionstart"] = parseInt(this.ahy_ParseOneAhyParam("ahySelectionStart"));
        this.ahyAnchorPropertiesArr["selectionlength"] = parseInt(this.ahy_ParseOneAhyParam("ahySelectionLength"));
        if((this.ahyAnchorPropertiesArr["childnodeindex"] == -1) || 
            (this.ahyAnchorPropertiesArr["selectionstart"] == -1) ||
            (this.ahyAnchorPropertiesArr["selectionlength"] == -1)){
            return false;
        }else{
            return true;
        }
    }

    function ahy_CreateAnchor()
    {
        if(this.ahyAnchorPropertiesArr["parentnodeid"] != null){
            this.ahySelectionParentNode = document.getElementById(this.ahyAnchorPropertiesArr["parentnodeid"]);
        }else if((this.ahyAnchorPropertiesArr["parentnodetagname"] != null)&&(this.ahyAnchorPropertiesArr["parentnodeindex"] != null)){
            var arrElementsWithSameTagNameAsParentNode = document.getElementsByTagName(this.ahyAnchorPropertiesArr["parentnodetagname"]);
            this.ahySelectionParentNode = arrElementsWithSameTagNameAsParentNode[this.ahyAnchorPropertiesArr["parentnodeindex"]];
        }else{
            alert("One or more Ahoy parameters necessary to resolve the location of the selection are missing.  Exiting.");
            return false;
        }
        this.ahySelectionChildNode = this.ahySelectionParentNode.childNodes[this.ahyAnchorPropertiesArr["childnodeindex"]];
        var objPreSelectionRange = document.createRange();
        objPreSelectionRange.setStart(this.ahySelectionChildNode, 0);
        objPreSelectionRange.setEnd(this.ahySelectionChildNode, this.ahyAnchorPropertiesArr["selectionstart"]);
        var objPreSelectionRangeContentsString = objPreSelectionRange.toString();
        this.ahyRangeObj = document.createRange();
        this.ahyRangeObj.setStart(this.ahySelectionChildNode, this.ahyAnchorPropertiesArr["selectionstart"]);
        var intIndexSelectionEnd = this.ahyAnchorPropertiesArr["selectionstart"] + this.ahyAnchorPropertiesArr["selectionlength"];
        this.ahyRangeObj.setEnd(this.ahySelectionChildNode, intIndexSelectionEnd);
        var strRangeSelectionForAnchor = this.ahyRangeObj.toString();
        var objPostSelectionRange = document.createRange();
        objPostSelectionRange.setStart(this.ahySelectionChildNode, intIndexSelectionEnd);
        objPostSelectionRange.setEnd(this.ahySelectionChildNode, this.ahySelectionChildNode.nodeValue.length);
        var objPostSelectionRangeContentsString = objPreSelectionRange.toString();
        this.ahyDocumentFragmentToInsert  = document.createDocumentFragment();
        var strPreSelectionText = objPreSelectionRange.toString();
        var strPostSelectionText = objPostSelectionRange.toString();
        var nodeAnchorElement = document.createElement("A");
        var nodeAnchorElementContents = document.createTextNode(strRangeSelectionForAnchor);
        nodeAnchorElement.setAttribute("name", "ahoyanchor" );
        nodeAnchorElement.setAttribute("id", "ahoyanchorid" );
        nodeAnchorElement.appendChild(nodeAnchorElementContents);
        if(strPreSelectionText.length > 0){
            var nodePreAnchorSpanElement = document.createElement("SPAN");
            var nodePreSelectionTextNode = document.createTextNode(strPreSelectionText);
            nodePreAnchorSpanElement.setAttribute("id", "ahoypreanchorspan" );
            nodePreAnchorSpanElement.appendChild(nodePreSelectionTextNode);
            this.ahyDocumentFragmentToInsert .appendChild(nodePreAnchorSpanElement);
        }
        this.ahyDocumentFragmentToInsert .appendChild(nodeAnchorElement);
        if(strPostSelectionText.length > 0){
            var nodePostAnchorSpanElement = document.createElement("SPAN");
            var nodePostSelectionTextNode = document.createTextNode(strPostSelectionText);
            nodePostAnchorSpanElement.setAttribute("id", "ahoypostanchorspan" );
            nodePostAnchorSpanElement.appendChild(nodePostSelectionTextNode);
            this.ahyDocumentFragmentToInsert .appendChild(nodePostAnchorSpanElement);
        }
        this.ahySelectionParentNode.replaceChild(this.ahyDocumentFragmentToInsert, this.ahySelectionParentNode.childNodes[this.ahyAnchorPropertiesArr["childnodeindex"]]);
        this.ahyInsertedAnchorNode = document.getElementById("ahoyanchorid");
        this.ahyInsertedAnchorNode.style.backgroundColor="rgb(220,220,220)";
        return true;
    }

}

function ahy_DoOnLoad()
{
    if(window.getSelection && document.implementation.hasFeature){
        var blnRangeImplemented = document.implementation.hasFeature("Range", "2.0");
        if(blnRangeImplemented){
            if(location.search.indexOf("ahyAnchor") != -1){
                objAhyAnchor = new ahyObjAnchor();
                var blnORstrExtractAhoyParamsSubstring = objAhyAnchor.ahy_FetchAhyQueryParamsString("ahoyparams");
                if(blnORstrExtractAhoyParamsSubstring){
                    objAhyAnchor.ahyQueryStringParamsString = blnORstrExtractAhoyParamsSubstring;
                }else{
                    alert("Problems were encountered while obtaining the set of Ahoy parameters from the query string.  Cannot create anchor.");
                    return false;
                }
                var blnparseAhoyParams = objAhyAnchor.ahy_ParseAhyQueryParamsString();
                if(blnparseAhoyParams){
                    var blnAhyAnchorCreated = objAhyAnchor.ahy_CreateAnchor();
                    if(blnAhyAnchorCreated){
                        objAhyAnchorCreatedParentNode = objAhyAnchor.ahySelectionParentNode;
                    }
                    setTimeout("location.href = '#ahoyanchor'", 100);
                }else{
                    alert("Problems were encountered while parsing the Ahoy parameters in query string.  Cannot create anchor.");
                    return false;
                }
            }
            objSelectedTextRange = new ahyObjSelectedTextRange(objAhyAnchorCreatedParentNode);
            document.addEventListener("mouseup", objSelectedTextRange.ahy_EndSelect, false);
        }
    }
}

if(window.addEventListener){
    window.addEventListener("load", ahy_DoOnLoad, false);
}else{
    if(location.search.indexOf("ahyAnchor") != -1){
        alert("You've attempted to access an AHOY bookmark within this page, but your browser doesn't support the addEventListener method of the W3C DOM Level 2 Events API for the window object.  You're being redirected to the url of the page sans the AHOY query string parameters ...");
        var strLocationSansQueryString = location.protocol+"//"+location.host+location.pathname;
        var strScrubbedQueryString = ahy_ScrubQueryString();
        if(strScrubbedQueryString != ''){
            location.replace(strLocationSansQueryString+strScrubbedQueryString);
        }else{
            location.replace(strLocationSansQueryString);
        }
    }
}
