/*

  DO NOT EDIT www/htdocs/newaction.js

  Instead, edit www/htdocs/newaction.js.in and then either restart
  the services, or run bin/make-xpi.  This will build newaction.js for your 
  particular installation, as well as fill the correct values in other 
  useful files like download.html, update.rdf, etc.

*/


var debug = false ;

function dprint(line) {
    if (!debug) {
	return ;
    }

    try {
	console.log(line) ;
    } catch (ex) {
	// WJD OUT for now ... annoying.
	// alert("DPRINT: " + line) ;

	var o = document.getElementById('clickable_output') ;
	if (o) {
	    o.innerHTML = o.innerHTML + line + "<BR>\n" ;
	    o.scrollTop = o.scrollHeight ; // Scroll to bottom.
	}
    }
}

var current_version  = "0.8" ;
var outside_hostname = "http://cl.ickable.com" ;
var ssl_hostname     = "https://cl.ickable.com" ;

var pattern = /^https/i ;
if (pattern.test(document.location)) {
    outside_hostname = ssl_hostname ;
}

dprint("newaction.js: outside_hostname: " + outside_hostname) ;

try {
    console.log("Clickable version " + current_version + " from " + outside_hostname + " on " + document.location) ;
} catch (disregard) {}

	
/*
  The Popup object encapsulates the DOM elements necessary to display 
  our widget, and the functions necessary to format and send requests 
  to remote locations.

  Actually, for a while, the functions necessary to format and send 
  requests were in clickhandlers.js, because the buttons themselves were  
  being brought in via an iframe, and same-origin policy keept us from 
  accessing this script from the iframe when this script's containing 
  page is not from the same server as the iframe (which is most of the 
  time).  clickhandlers.js was included by table.html.
*/


function Popup() {
    current_text: "Popup default";
    dom_object: null ;
    input_object: null ;
    grippy_object: null ;
    visit_object: null ;

    this.initialize() ;
}


Popup.prototype = {

    
    initialize: function() {
	dprint("Popup.initialize called.") ;

	//
	// The main container of the entire thing.
	//

	var mydiv = document.createElement('div') ;
	mydiv.style.display          = "none" ;
	mydiv.style.width            = '334px';
	mydiv.style.height           = '179px';
	mydiv.style.backgroundImage  = 
	      "url('" + outside_hostname + "/images/full_frame.png')" ;
	mydiv.style.backgroundRepeat = 'no-repeat' ;
	mydiv.style.position         = 'absolute' ;
	mydiv.style.zIndex           = 100 ;

	
	//
	// This will keep the mouseup event from bubbling to the document
	// object, which would incorrectly move the popup relative to the 
	// mouse's position on the screen.
	// 

	mydiv.onmouseup = function(e) {
	    dprint("mydiv.onmouseup e: " + e + " target: " + e.target + " typeof target: " + typeof(e.target) + "target.constructor: " + e.target.constructor + " target.id: " + e.target.id + " e.currentTarget: " + e.currentTarget + " STOPPROPAGATION!") ;

	    e.stopPropagation() ;
	} ;

	mydiv.onmousedown = function(e) {
	    dprint("mydiv.onmousedown e: " + e + " target: " + e.target + " STOPPROPAGATION!" + " PREVENTDEFAULT!") ;

	    e.stopPropagation() ;

	    // WJD We do NOT prevent the default if the click is on the 
	    // input area, so that it can still be clickable.
	    if (e.target.id == "clickable_input") {
		return ;
	    }

	    // WJD This keeps FF3 from de-selecting underlying text.
	    e.preventDefault() ;
	} ;



	//
	// The container for the buttons.
	//

	var buttondiv = document.createElement('div') ;
	buttondiv.style.display = 'block' ;
	buttondiv.style.width = '280px' ;
	buttondiv.style.height = '84px' ;
	// buttondiv.style.border = 'solid 1px green' ;
	buttondiv.style.position = 'absolute' ;
	buttondiv.style.top = '64px' ;
	buttondiv.style.left = '24px' ;


	/* 

	// 
	// WJD June 18, 2008
	// Firefox 3 is now throwing a security error when I try to 
	// access a property set on an iframe.  As convenient as it was 
	// to have an HTML iframe, it has become such a problem that 
	// I am moving things back here.
	// 

	*/


	buttondiv.innerHTML = '<body style="margin: 0px;"><!--     Be very careful using single quotes in this file.  It is no longer    being snagged via iframe, instead, it is being included IN THE     JAVASCRIPT of newaction.js.in as a single string.  If you want to    use single quotes, escape them with backslash (\').  Not doing so     causes it to end the string.    Confusingly, we do this in the img src properties because we DO     want to add things (outside_hostname) FROM THE JAVASCRIPT in the     middle of the otherwise normal-looking HTML.  Eventually, we should     encase this all in the JavaScript, but it would be a great deal of     tedious work, and we do not even know the final form yet, so.  Enjoy!  --><style type="text/css">.icon {    vertical-align: middle;}span.clickable_button_label {    vertical-align: middle;    font-family: helvetica, sans-serif;    font-size: 12px;    color: #333333;    font-weight: normal;}img.dots {    margin-top: 1px;    margin-bottom: 1px;    /* To override what other sites do. */    margin-left: 0px;    margin-right: 0px;    border: 0px none;/*    border: 2px solid orange; */    padding: 0px;    background: transparent none;    height: 1px;    width: 121px;    /* slashdot, you may now bite me. */    vertical-align: top;}img.clickable_button_icon {    vertical-align: middle;    /* most of this is to override what other sites do. */    display: inline ;    border:  0px none;    margin:  0px;    padding: 0px;    background: transparent none;}a.clickable_button {    font-weight: normal;    background-color: white;    color: #333333;    text-decoration: none;    /* block display so we can set width. */    display: block;    width: 121px;    padding-top: 1px;    padding-bottom: 2px;    padding-left: 1px;    border: 0px;}a.clickable_button:hover {      background-color: #dddddd;}div.new_button_container {      width: 135px;      float: left;      padding: 0px;      margin: 0px;      border: 0px;      text-align: left;}div.new_row_container {      clear: both;      width: 274px;      padding: 0px;      margin: 0px;      border: 0px;}div.new_dots_container {      width: 135px;      float: left;      height: 3px;      padding: 0px;      margin: 0px;      border: 0px;      text-align: left ;}</style><div class="new_row_container"><div class="new_button_container"><a href="javascript:handleClick(\'amazon\');" class="clickable_button"><img src="' + outside_hostname + '/images/icon_amazon.png" width="16" height="18" border="0" class="clickable_button_icon"><span class="clickable_button_label"> Amazon</span></a></div><div class="new_button_container"><a href="javascript:handleClick(\'google\');" class="clickable_button"><img src="' + outside_hostname + '/images/icon_google.png" width="16" height="18" border="0" class="clickable_button_icon"><span class="clickable_button_label"> Google</span></a></div></div><div class="new_row_container"><div class="new_dots_container"><img src="' + outside_hostname + '/images/dots.png" width="121" height="1" class="dots"></div><div class="new_dots_container"><img src="' + outside_hostname + '/images/dots.png" width="121" height="1" class="dots"></div></div><div class="new_row_container"><div class="new_button_container"><a href="javascript:handleClick(\'wikipedia\');" class="clickable_button"><img src="' + outside_hostname + '/images/icon_wikipedia.png" width="16" height="18" border="0" class="clickable_button_icon"><span class="clickable_button_label"> Wikipedia</span></a></div><div class="new_button_container"><a href="javascript:handleClick(\'dictionary\');" class="clickable_button"><img src="' + outside_hostname + '/images/icon_dictionary.png" width="16" height="18" border="0" class="clickable_button_icon"><span class="clickable_button_label"> Dictionary</span></a></div></div><div class="new_row_container"><div class="new_dots_container"><img src="' + outside_hostname + '/images/dots.png" width="121" height="1" class="dots"></div><div class="new_dots_container"><img src="' + outside_hostname + '/images/dots.png" width="121" height="1" class="dots"></div></div><div class="new_row_container"><div class="new_button_container">&nbsp;</div><div class="new_button_container"><a href="javascript:handleClick(\'clipboard\');" class="clickable_button"><img src="' + outside_hostname + '/images/icon_clip.gif" width="16" height="18" border="0" class="clickable_button_icon"><span class="clickable_button_label"> WebClipboard</span></a></div></div><!--<style type="text/css">/* mytd and td.mydots are only used in the table version */.mytd {    padding: 0px;    margin: 0px;    border: 0px;    text-align: left;}td.mydots {    padding: 0px;    margin: 0px;    border: 0px;}</style><table border=0 cellpadding=0 cellspacing=0 style="width: 274px;"><tr><td class="mytd"><a href="javascript:handleClick(\'amazon\');" class="clickable_button"><img src="' + outside_hostname + '/images/icon_amazon.png" width="16" height="18" border="0" class="clickable_button_icon"><span class="clickable_button_label"> Amazon</span></a></td><td class="mytd"><a href="javascript:handleClick(\'google\');" class="clickable_button"><img src="' + outside_hostname + '/images/icon_google.png" width="16" height="18" border="0" class="clickable_button_icon"><span class="clickable_button_label"> Google</span></a></td></tr><tr><td class="mydots"><img src="' + outside_hostname + '/images/dots.png" width="121" height="1" class="dots"></td><td class="mydots"><img src="' + outside_hostname + '/images/dots.png" width="121" height="1" class="dots"></td></tr><tr><td class="mytd"><a href="javascript:handleClick(\'wikipedia\');" class="clickable_button"><img src="' + outside_hostname + '/images/icon_wikipedia.png" width="16" height="18" border="0" class="clickable_button_icon"><span class="clickable_button_label"> Wikipedia</span></a></td><td class="mytd"><a href="javascript:handleClick(\'dictionary\');" class="clickable_button"><img src="' + outside_hostname + '/images/icon_dictionary.png" width="16" height="18" border="0" class="clickable_button_icon"><span class="clickable_button_label"> Dictionary</span></a></td></tr><tr><td class="mydots"><img src="' + outside_hostname + '/images/dots.png" width="121" height="1" class="dots"></td><td class="mydots"><img src="' + outside_hostname + '/images/dots.png" width="121" height="1" class="dots"></td></tr><tr><td class="mytd"></td><td class="mytd"><a href="javascript:handleClick(\'clipboard\');" class="clickable_button"><img src="' + outside_hostname + '/images/icon_clip.gif" width="16" height="18" border="0" class="clickable_button_icon"><span class="clickable_button_label"> WebClipboard</span></a></td></tr></table>  --></body>' ;


	mydiv.appendChild(buttondiv) ;



	//
	// The 'x' button at top right.
	//

	hidediv = document.createElement('div') ;
	hidediv.style.position = 'absolute' ;
	hidediv.style.display  = 'block' ;
	hidediv.style.top      = '19px' ;
	hidediv.style.left     = '290px' ;
	hidediv.style.height   = '22px' ;
	hidediv.style.width    = '21px' ;
	// hidediv.style.border   = 'solid 1px red' ;

	hideimg = document.createElement('img') ;
	hideimg.src = outside_hostname + "/images/close_btn.png" ;
	hideimg.id = "hideimg" ;

	// Override what other pages might do to these values.
	hideimg.style.border   = '0px none' ;
	hideimg.style.padding  = '0px' ;
	hideimg.style.margin   = '0px' ;

	hideimg.onmouseover = function() {
	    var o = document.getElementById('hideimg') ;
	    o.src = outside_hostname + "/images/close_btn_over.png" ;
	} ;
	hideimg.onmouseout = function() {
	    var o = document.getElementById('hideimg') ;
	    o.src = outside_hostname + "/images/close_btn.png" ;
	} ;
	hideimg.onclick = function(e) {
	    dprint("hideimg onclick heard: e: " + e) ;
	    our_popup.setCurrentText('') ;
	    our_popup.hide() ;
	} ;

	//
	// We stop this here in order to keep the document's handler 
	// from moving the popup before onclick ends up hiding it.
	//
	hideimg.onmouseup = function(e) {
	    dprint("hideimg onmouseup heard: e: " + e + " STOPPROPAGATION!") ;
	    e.stopPropagation() ;
	} ;

	hidediv.appendChild(hideimg) ;

	mydiv.appendChild(hidediv) ;

	//
	// The 'input' box at the top.
	//

	myinput = document.createElement('input') ;
	myinput.style.position        = 'absolute' ;
	myinput.style.display         = 'block' ;
	myinput.style.top             = '22px' ;
	myinput.style.left            = '30px' ;
	myinput.style.borderWidth     = '0px' ;
	myinput.style.width           = '240px';
	myinput.style.height          = '21px' ;
	myinput.style.fontFamily      = 'helvetica' ;
	myinput.style.fontSize        = '14px' ;
	myinput.style.padding         = '0px' ;
	myinput.style.margin          = '0px' ;
	myinput.style.border          = '0px' ;
	myinput.style.backgroundColor = 'white' ;
	myinput.style.color           = 'black' ;

	// myinput.style.border = '1px solid red' ;

	myinput.id = "clickable_input" ;

	myinput.popup_handle = this ;
	myinput.onkeyup = function(e) {
	    dprint("myinput.onkeyup keycode: " + e.keyCode + 
		   " value: " + this.value) ;
	    var is_url = this.popup_handle.testForURL(this.value) ;

	    // 13 == return/enter
	    if (e.keyCode == 13 && is_url) {

		// WJD XXX In FF3, using the enter key to open the window 
		// causes the popup-blocker to engage, but not in FF2.
		// stopPropagation and preventDefault seem to have 
		// no effect.

		this.popup_handle.handleClick('visiturl') ;
		e.stopPropagation() ;
		e.preventDefault() ;
	    }
	} ;

	this.input_object = myinput ;

	mydiv.appendChild(myinput) ;


	//
	// The 'visit external link' button, which is only visible 
	// if selected text appears to be link.
	//

	myvisitdiv = document.createElement('div') ;
	myvisitdiv.style.position = 'absolute' ;
	myvisitdiv.style.display = 'none' ;
	myvisitdiv.style.top = '21px' ;
	myvisitdiv.style.left = '250px' ;
	myvisitdiv.style.width = '20px' ;
	myvisitdiv.style.height = '20px' ;
	myvisitdiv.style.backgroundColor = 'white' ;
	// myvisitdiv.style.border = 'solid 1px green' ;

	myvisitdiv.onmouseover = function() {
	    this.style.backgroundColor = '#dddddd' ;
	} ;
	myvisitdiv.onmouseout = function() {
	    this.style.backgroundColor = 'white' ;
	} ;
	myvisitdiv.popup_handle = this ;
	myvisitdiv.onmouseup = function() {
	    dprint("myvisitdiv.onmouseup heard: " + this) ;
	    this.popup_handle.handleClick('visiturl') ;
	} ;

	myvisitimg = document.createElement('img') ;
	myvisitimg.src = outside_hostname + "/images/external.png" ;
	myvisitimg.style.marginTop = '5px' ;
	myvisitimg.style.marginLeft = '5px' ;

	myvisitdiv.appendChild(myvisitimg) ;

	this.visit_object = myvisitdiv ;

	mydiv.appendChild(myvisitdiv) ;



	//
	// Invisible 'grippy' area for dragging the thing around.
	//
	
	mygrippy = document.createElement('div') ;
	mygrippy.style.position = 'absolute' ;
	mygrippy.style.display = 'block' ;
	mygrippy.style.top = '0px' ;
	mygrippy.style.left = '0px' ;
	mygrippy.style.width = '334px' ;
	mygrippy.style.height='17px' ;
	mygrippy.style.cursor = 'move' ;
	// mygrippy.style.border = 'solid 1px red' ;
	this.grippy_object = mygrippy ;
	
	mydiv.appendChild(mygrippy) ;
	
	document.body.appendChild(mydiv) ;
	
	this.dom_object = mydiv ;

    },


    moveTo: function(top, left) {
	this.dom_object.style.top  = top + 'px' ;
	this.dom_object.style.left = left + 'px' ;
    },


    show: function() {
	this.dom_object.style.display = "block" ;
    },

   
    hide: function() {
	this.dom_object.style.display = "none" ;
    },


    showVisitButton: function() {
	this.visit_object.style.display = "block" ;
    },

    
    hideVisitButton: function() {
	this.visit_object.style.display = "none" ;
    },


    testForURL: function(txt) {
	// Perhaps I should not construct RegExp objects every time?
	if (/^\s*http/.test(txt) || /^\s*\S+\.\S+\s*$/.test(txt)) {
	    this.showVisitButton() ;
	    return true ;
	} else {
	    this.hideVisitButton() ;
	    return false ;
	}
    },


    handleClick: function(click_type) {

	switch (click_type) {
	    case 'amazon':
	    dprint("Popup.handleClick sees amazon click type.") ;
	    this.handleAmazon() ;
	    break ;

	    case 'comment':
	    dprint("Popup.handleClick sees comment click type.") ;
	    break ;

	    case 'wikipedia':
	    dprint("Popup.handleClick sees wikipedia click type.") ;
	    this.handleWikipedia() ;
	    break ;

	    case 'google':
	    dprint("Popup.handleClick sees google click type.") ;
	    this.handleGoogle() ;
	    break ;

	    case 'dictionary':
	    dprint("Popup.handleClick sees dictionary click type.") ;
	    this.handleDictionary() ;
	    break ;

	    case 'visiturl':
	    dprint("Popup.handleClick sees visiturl click type.") ;
	    this.handleVisitURL() ;
	    break ;

	    case 'clipboard':
	    dprint("Popup.handleClick sees clipboard click type.") ;
	    this.handleClipboard() ;
	    break ;

	    default: dprint("Popup.handleClick: unknown click_type: " + click_type) ;
	}
	
    },


    /*
      // Would have been sweet.  Security problem, though, when clipping 
      // from anywhere except outside_hostname. :) 
    handleClipboard: function() {
	var html = getSelectedHTML() ;
	dprint("handleClipboard: html: " + html) ;
	var encoded_html  = encodeURIComponent(html) ;
	var encoded_href  = encodeURIComponent(document.location) ;
	var encoded_base  = encodeURIComponent(document.baseURI) ;
	var encoded_title = encodeURIComponent(document.title) ;

	var arguments = "content=" + encoded_html + "&location=" + encoded_href + "&base=" + encoded_base + "&title=" + encoded_title ;

	//	var url = outside_hostname + "/cgi-bin/SaveClip.cgi?content=" + encoded_html + "&location=" + encoded_href + "&base=" + encoded_base + "&title=" + encoded_title ;

	var url = outside_hostname + "/cgi-bin/SaveClip.cgi" ;

	dprint("handleClipboard: arguments: " + arguments) ;

	var request = new XMLHttpRequest() ;
	request.onreadystatechange = function(e) {
	    var state = this.readyState ;
	    dprint("request.onreadystatechange readyState: " + state) ;
	    if (state == 4) {
		dprint("request.onreadystatechange saw done state, status: " + request.status) ;
	    }
	} ;

	request.open('POST', url) ;
	request.setRequestHeader('Content-type',
				 'application/x-www-form-urlencoded') ;

	request.send(arguments) ;
	
	// window.open(url) ;
    },

    */


    handleClipboard: function() {
	var html = getSelectedHTML() ;

	dprint("handleClipboard: html: " + html) ;

	var encoded_html  = encodeURIComponent(html) ;
	var encoded_href  = encodeURIComponent(document.location) ;
	var encoded_base  = encodeURIComponent(document.baseURI) ;
	var encoded_title = encodeURIComponent(document.title) ;

	var url = outside_hostname + "/cgi-bin/SaveClip.cgi?content=" + encoded_html + "&location=" + encoded_href + "&base=" + encoded_base + "&title=" + encoded_title ;
	
	dprint("handleClipboard: url: " + url) ;

	// If possible, I want them to open in the same tab.
	window.open(url, "clickable") ;
    },


    handleVisitURL: function() {
	var text = this.input_object.value ;
	if (!text.length) {
	    return ;
	}

	if (!/http/.test(text)) {
	    text = "http://" + text ;
	}
	dprint("handleVisitURL: visiting: " + text) ;
	window.open(text) ;
    },


    handleDictionary: function() {
	var text = this.input_object.value ;
	if (!text.length) {
	    return ;
	}
	var encoded = encodeURI(text) ;
	var url = outside_hostname + "/cgi-bin/Redirect.cgi?destination=" + "http://www.dictionary.com/search?q=" + encoded ;
	dprint("handleDictionary: url: " + url) ;
	window.open(url) ;
    },


    handleWikipedia: function() {
	var text = this.input_object.value ;
	if (!text.length) {
	    return ;
	}
	var encoded = encodeURI(text) ;

	// Snagged this from:
	// http://www.askdavetaylor.com/add_wikipedia_search_box_to_my_web_site_or_blog.html

	var url = outside_hostname + "/cgi-bin/Redirect.cgi?destination=" + "http://www.wikipedia.org/search-redirect.php?language=en&search=" + encoded;
	dprint("handleWikipedia: url: " + url) ;
	window.open(url) ;
    },


    handleGoogle: function() {
	var text = this.input_object.value ;
	if (!text.length) {
	    return ;
	}
	var encoded = encodeURI(text) ;
	var url = outside_hostname + "/cgi-bin/Redirect.cgi?destination=" + "http://www.google.com/search?q=" + encoded ;
	dprint("handleGoogle: url: " + url) ;
	window.open(url) ;
    },
	

    handleAmazon: function() {
	var text = this.input_object.value ;
	if (!text.length) {
	    return ;
	}
	var encoded = encodeURI(text) ;
	var url = outside_hostname + "/cgi-bin/Redirect.cgi?destination=" + "http://www.amazon.com/gp/associates/link-types/searchbox.html?mode=blended&keyword="  + encoded ;
	dprint("handleAmazon: url: " + url) ;
	window.open(url) ;

    },

    
    setCurrentText: function(txt) {
	this.current_text = txt ;
	this.input_object.value = txt ;

	this.testForURL(txt) ;

    },

};


var our_popup = new Popup() ;


// JavaScript: The Definitive Guide, 5th ed., p 341
function getSelectedText() {
    if (window.getSelection) {
        return window.getSelection().toString() ;
    } else if (document.getSelection) {
        return document.getSelection() ;
    } else if (document.selection) {
        return document.selection.createRange().text ;
    }
}


//
// Working with info from:
// http://www.quirksmode.org/dom/range_intro.html
//

function getSelectedHTML() {

    var selecto = window.getSelection() ;
    dprint("getSelectedHTML: window.getSelection(): " + typeof(selecto)) ;
    if (selecto.getRangeAt) {
	var rangeo = selecto.getRangeAt(0) ;
	dprint("getSelectedHTML: rangeo: " + rangeo + " rangeo.innerHTML: " + rangeo.innerHTML + " rangeo.htmlText: " + rangeo.htmlText) ;
	var frag = rangeo.cloneContents() ;

	var html = getHTMLFromElement(frag) ;
	return html ;
    }

    return "" ;
	
}


function getHTMLFromElement(elem) {
    var html = "" ;

    for (var i = 0; i < elem.childNodes.length; i++) {
	var my_node = elem.childNodes[i] ;

	dprint("my_node.nodeType: " + my_node.nodeType) ;

	if (my_node.nodeType == Node.TEXT_NODE) {

	    var value = my_node.nodeValue ;

	    dprint("TEXT BEFORE: \"" + value + "\"") ;

	    // 
	    // Browsers render any number of spaces in text as a single 
	    // space.  So compress extra space down.  We put a \n at 
	    // the end to break up the HTML.  Previously, we were putting 
	    // a carriage return after each html end tag, but that was 
	    // being rendered as a space even when one was not intended.
	    // Here we KNOW a space is intended, and it makes the HTML
	    // more readable, too.
	    // 
	    value = value.replace(/^\s+/gi, ' ') ;
	    value = value.replace(/\s+$/gi, "\n") ;

	    dprint("TEXT AFTER: \"" + value + "\"") ;

	    html += value ;

	} else if (my_node.nodeType == Node.ELEMENT_NODE) {

	    var my_tag = my_node.tagName.toLowerCase() ;

	    dprint("Element tagName: " + my_tag) ;

	    html += "<" + my_tag ;

	    for (var j = 0; j < my_node.attributes.length; j++) {
		var attr = my_node.attributes[j] ;
		dprint("ATTR: " + attr.name + " = " + attr.value) ;

		html += " " + attr.name + "=\"" + attr.value + "\"" ;
		
	    }

	    html += ">" ;

	    html += getHTMLFromElement(my_node) ;

	    // We stopped adding \n after each html tag, it is rendered
	    // as a space.
	    html += "</" + my_tag + ">" ;

	    dprint("HTML AFTER: \"" + html + "\"") ;

	}
    }
    return html ;
}


function handleClick(click_type) {
    our_popup.handleClick(click_type) ;
}


//
// For Firefox, determine if a click is in the scrollbar,
// which is still passed through to the document.
//
function clickedOnScrollbar(e) {
    my_event = e ? e : window.event ;
    if (/MSIE/.test(navigator.userAgent)) {
	// This is apparently only an issue in Firefox.
	return false ;
    } else {

	dprint("pageX: " + my_event.pageX + 
	       " clientWidth: " + document.body.clientWidth + 
	       " pageY: " + my_event.pageY + 
	       " clientHeight: " + document.body.clientHeight) ;

	if (my_event.pageX > document.body.clientWidth) {
	    return true ;
	}
	if (my_event.pageY > document.body.clientHeight) {
	    // WJD XXX Out until we account for scroll position as well!
	    // return true ;
	}
    }

    return false ;
}



function getMouseLocation(e) {
    /*
      // http://javascript.internet.com/page-details/mouse-coordinates.html
      // when we need IE support.
      function getMouseXY(e) {
      if (IE) { // grab the x-y pos.s if browser is IE
      tempX = event.clientX + document.body.scrollLeft;
      tempY = event.clientY + document.body.scrollTop;
      }
      else {  // grab the x-y pos.s if browser is NS
      tempX = e.pageX;
      tempY = e.pageY;
      }  
    */
    return {left:e.pageX, top:e.pageY} ;
}


function somethingOnMouseUp(e) {
    var selected_text = getSelectedText() ;

    dprint("somethingOnMouseUp: this: " + this + " target: " + e.target + " e.currentTarget: " + e.currentTarget + " selected_text: " + selected_text + " e.target.constructor: " + e.target.constructor) ;
    // + " typeof constructor: " + typeof e.target.constructor + " toString(): " + e.target.constructor.toString()) ;

    if (selected_text.length) {
	
	if (e.target.constructor && 
	    e.target.constructor.toString().match("HTMLAnchorElement") != null) {
	    // WJD June 30, 2008
	    // Do not move the object if the original target is a link,
	    // since they probably clicked there to leave the page.
	    // WJD July 1, 2008
	    dprint("somethingOnMouseUp: e.target.constructor matched HTMLAnchorElement: " + e.target.constructor) ;
	    return ;
	}

	if (clickedOnScrollbar(e)) {
	    dprint("somethingOnMouseUp: clickedOnScrollbar returned true.") ;
	    return ;
	}

	// Move the popup close to the mouse's current location.

	loc = getMouseLocation(e) ;

	// dprint("somethingOnMouseUp: top: " + loc.top + 
	// " left: " + loc.left) ;

	// Do not jump to mouse location if we just finished
	// dragging it.
	if (justDragged) {
	    justDragged = false ;
	} else {
	    our_popup.moveTo(loc.top + 1, loc.left) ;
	}

	our_popup.show() ;
	our_popup.setCurrentText(selected_text) ;
	
    } else {
	dprint("somethingOnMouseUp: calling our_popup.hide") ;
	our_popup.hide() ;
	our_popup.setCurrentText('') ;
    }
    return false ;
}


function somethingOnSelect(e) {
    dprint("somethingOnSelect: " + e) ;
}


function somethingOnKeyUp(e) {
    var my_event = e ? e : window.event ;

    // 27 == Esc
    if (my_event.keyCode == 27) {
	// dprint("somethingOnKeyUp: keyCode == 27") ;
	our_popup.hide() ;
    }

}




/*
  Make the object dragable.

  Much cleaner ideas for this (especially IE compatibility) at:
  http://www.webreference.com/programming/javascript/mk/column2/
  http://elouai.com/javascript-drag-and-drop.php
*/

var dragObject = null ;
var mouseOffset = null ;
var justDragged = false ;

function calculateMouseOffset(e, o) {

    //    dprint("calculateMouseOffset: " + e.pageY + ", " + parseInt(o.style.top)) ;

    var loc = getMouseLocation(e) ;

    var offsetTop = loc.top - parseInt(o.style.top) ;
    var offsetLeft = loc.left - parseInt(o.style.left) ;
    return {top:offsetTop, left:offsetLeft} ;
}

our_popup.grippy_object.onmousedown = function(e) {
    // dprint("our_popup.grippy_object.onmousedown heard: " + e) ; 
    dragObject = our_popup.dom_object ;
    mouseOffset = calculateMouseOffset(e, dragObject) ;
} ;

our_popup.grippy_object.onmouseup = function() {
    // dprint("our_popup.grippy_object.onmouseup heard.") ;
    dragObject = null ;
} ;

function somethingOnMouseMove(e) {
    
    if (!dragObject) {
	return ;
    }

    // dprint("somethingOnMouseMove: offsetTop: " + mouseOffset.top + " offsetLeft: " + mouseOffset.left) ;

    var loc = getMouseLocation(e) ;

    our_popup.moveTo(loc.top - mouseOffset.top, loc.left - mouseOffset.left) ;

    justDragged = true ;

}




if (document.addEventListener) {

    dprint("Using DOM Level 2 addEventListener.") ;

    document.addEventListener("mouseup",
			      somethingOnMouseUp,
			      false) ;
    
    document.addEventListener("keyup",
			      somethingOnKeyUp,
			      false) ;

    document.addEventListener("mousemove",
			      somethingOnMouseMove,
			      false) ;
    
} else {

    dprint("Using DOM Level 0 event properties.") ;

    // Level 0 Version
    document.onmouseup = somethingOnMouseUp ;
    document.onkeyup = somethingOnKeyUp ;
    document.onmousemove = somethingOnMouseMove ;

}



