/* Show an inline popup, asking the reader to visit a link.
 *
 * The popup contains a div containing the text, above a div
 * containing 3 buttons ("Now", "Later", and "Never"). All 3 buttons
 * will close the popup, but "Now" will also make a real popup of the
 * link page. "Later" will show the inline popup again later, 2 hours
 * per default.
 *
 * This class is instantiated as
 *   <script src="https://www.kalus.dk/js/answering/inline_popup_invite.js" type="text/javascript"></script>
 *   <script type="text/javascript">
 *     var my_popup = new kalus_popup_class("<b>Answer questionnaire?</b>",
 *                                          "http://www.example_com/questionnaire_login");
 *   </script>
 * This instantiation can be done in either <head></head>, or
 * somewhere inside <body></body>. I think there are fewest things
 * that could go wrong if you place it at the bottom of the body, but
 * either should work.
 *
 * The constructor will add itself to window.onload() and
 * window.resize(), and show the popup (if the respondent has not said
 * "no thanks" to the popup in a previous session, saved in a
 * cookie). So don't overwrite window.(onload|onresize). The popup
 * constructor will append its onload|onresize to any extant
 * window.(onload|onresize).
 *
 * When the respondent dismisses the dialogue, then the dialogue
 * should now be shown for a long time ("now" or "never" answers), or
 * a short time ("later" answer). The time before next show is saved
 * as the expiry time of a cookie named "my_popup.id +
 * '_dont_show'". This means that you can easily ignore existing
 * cookies by changing my_popup.id just after initialization.
 *
 * The popup is shown vertically and horizontally centered, with a
 * transparently gray div covering the normal webpage.
 *
 * In addition to the "text" and "link" constructor args, you can
 * configure a number of class instance properties. Usually you will
 * want to at least translate the texts. For example:
 *   my_popup.login_now_txt = "Nu";
 *   my_popup.ask_me_later_txt = "Senere";
 *   my_popup.dont_ask_me_again_txt = "Nej tak";
 *   my_popup.ask_me_again_later_seconds = 30*60; //30 minuttes
 * These properties should be set imediately after the instantiation,
 * ie before the popup has had a chance to be shown as a consequence
 * of window.onload.
 *
 * All elements (div's, input's) have .className = my_popup.id + '_class',
 * so you can easily CSS style them.
 *
 * This file has no dependencies, so you can move it, etc.
 */

var kalus_popup_class = function(text, link) {
    this.text = text; //Set as innerHTML of span, so can contain HTML
    this.link = link;

    //overridable properties. Should be overwritten just after
    //construction, ie before the popup is actually shown.
    this.id = "kalus_popup"; //used as id on div, so should be unique
    this.className = this.id + "_class";
    this.width = 400;  //pixels
    this.height = 200; //pixels
    this.action_div_height = 40; //pixels, how many pixels of this.height is reserved for buttons
    this.dont_ask_me_again_seconds = 60*60*24*365; //one year
    this.ask_me_again_later_seconds = 10*60; //10 minuttes
    this.popup_div_style = {'zIndex':100,
			    'backgroundColor':'#FFFFFF',
			    'border':"1px solid #000000",
			    'padding':'5px'};
    this.action_div_style = {"textAlign":'center'};
    this.action_button_style = {'margin':'6px',
				'cursor':'pointer'};

    var grayout_opacity = 70;
    this.grayout_style = {'zIndex':99,
			  'opacity':grayout_opacity/100,
			  'MozOpacity':grayout_opacity/100,
			  'filter':'alpha(opacity='+grayout_opacity+')',
			  'opaque':grayout_opacity/100,
			  'backgroundColor': '#000000',
			  'display':'block'};

    this.login_now_txt = "Now";
    this.ask_me_later_txt = "Later";
    this.dont_ask_me_again_txt = "Never";
    this.failed_to_open_window = "Failed to open popup window. Perhaps it was blocked by a popup blocker?";


    //Internal vars
    this.popup_div = null;
    this.text_div = null;
    this.positioning = "absolute"; //may be changed by this.popup() on first run
    this.positioning_inited = false;

    //Hacky way to check whether position:fixed works. We create an
    //empty div, and see if it is positioned where we specified. This
    //works, since the browser will fall back to position:static if
    //position:fixed does not work. This function hould only be called after the
    //document is loaded, so that there is a vbody to insert into.
    this.position_fixed_supported = function() {
	var test_div = document.createElement("div");
	test_div.id = "kalus_testing_position_fixed";
	test_div.style.position = "fixed";
	test_div.style.top = "40px";
	test_div.style.left = "41px";
	document.body.appendChild(test_div);
	var supported = false;
	if ((typeof test_div.offsetTop) == "number") {
	    var offsetTop = parseInt(test_div.offsetTop);
	    var offsetLeft = parseInt(test_div.offsetLeft);
	    if (offsetTop === 40 && offsetLeft === 41) {
		supported = true;
	    }
	}
	document.body.removeChild(test_div);
	
	return supported;
    }

    this.attach_event = function(el, eType, fn) {
	if (el.addEventListener) {
	    el.addEventListener(eType, fn, false/*don't use capture*/);
	    return true;
	} else if (el.attachEvent) {
	    return el.attachEvent('on' + eType, fn);
	} else {
	    var onType = 'on' + eType;
	    if (el[onType]) {
		var old_function = el[onType];
		el[onType] = function() {
		    old_function();
		    func();
		};
	    } else {
		el[onType] = fn;
	    }
	} 
    }

    this.init = function() {
	if (!this.should_popup()) {
	    return;
	}

	this.popup();
    }
    var this_class = this;
    this.attach_event(window, "load",  function() {this_class.init();});

    this.resizing = false;
    this.onresize_action = function() {
	if (!this.popup_div) {
	    return;
	}

	if (this.resizing) {
	    //guard against infinite loops
	    return;
	}
	this.resizing = true;

	if (this.popup_div) {
	    this.resize_grayout(this.get_grayout());
	    this.resize_popup(this.popup_div, this.text_div);
	}

	this.resizing = false;
    }
    //Attach this.onresize_action() to body.onresize in popup function
    this.onresize_attached = false;

    //This is only used if we have absolute positioning
    this.onscroll_action = function() {
	if (!this.popup_div) {
	    return;
	}

	var xy = this.get_scroll();
	var x = xy[0];
	var y = xy[1];

	//move popup
	this.resize_popup(this.popup_div, this.text_div, x, y);

	//move grayout
	var dark = this.get_grayout();
	this.resize_grayout(dark, x, y);
    }

    this.dont_show_cookie_name = function() {
	return this.id + "_dont_show";
    }

    

    this.should_popup = function() {
	return !this.get_cookie(this.dont_show_cookie_name());
    };

    this.popup = function() {
	if (this.popup_div) {
	    console.log("popup already open!");
	    return;
	}

	if (!this.positioning_inited && this.position_fixed_supported()) {
	    this.positioning = "fixed";
	}

	if (!this.onresize_attached) {
	    var this_class = this;
	    this.attach_event(window, "resize",  function() {this_class.onresize_action();});
	    this.onresize_attached = true;
	}

	var popup_div = document.createElement("div");
	popup_div.id = this.id;
	popup_div.style.position = this.positioning;
	popup_div.className = this.className;
	this.popup_div = popup_div;
	this.set_style(popup_div, this.popup_div_style);

	var text_div = document.createElement("div");
	text_div.innerHTML = this.text;
	text_div.className = this.className;
	popup_div.appendChild(text_div);
	this.text_div = text_div;

	this.resize_popup(popup_div, text_div);

	var action_div = this.get_action_div();
	popup_div.appendChild(action_div);

	this.add_grayout(true);
	document.body.appendChild(popup_div);

	var login_now_button = document.getElementById(this.id + "_login_now_button");
	login_now_button.focus();

	if (this.positioning == "absolute") {
	    var this_class = this;
	    this.attach_event(window, "scroll", function() {this_class.onscroll_action();});
	}
    };

    this.get_window_width_height = function() {
	if (typeof(window.innerWidth) == "number") {
	    //Sane browsers
	    var w = window.innerWidth ? window.innerWidth : document.body.clientWidth;
	    var h = window.innerHeight ? window.innerHeight : document.body.clientHeight;
	} else {
	    //IE 6-8
	    var IE_version = this.get_IE_version();
	    if (IE_version == 6 && document.compatMode && document.compatMode == "CSS1Compat") {
		var w = document.documentElement.clientWidth;
	    } else {
		var w = document.body.clientWidth;
	    }

	    if (   (IE_version == 6 && document.compatMode == "CSS1Compat")
		|| (IE_version == 7 && document.compatMode == "CSS1Compat")
		|| (typeof(document.documentMode) == "number" && document.documentMode == 8)
		) {
		//ie 6, 7 or 8 in strict mode...
		var h = document.documentElement.clientHeight;
		w += 50; //body margin not included, but overflow works...
	    } else {
		var h = document.body.clientHeight;
	    }
	}

	return [w, h];
    }

    this.resize_popup = function(popup_div, text_div, move_x, move_y) {
	var wh = this.get_window_width_height();
	var window_width = wh[0];
	var window_height = wh[1];

	var my_width = this.width;
        if (my_width > window_width) {
	    var left = 0;
	    my_width = window_width;
	} else {
	    var left = (window_width - my_width) / 2;
        }
	if (move_x) {
	    left += move_x;
	}

	var my_height = this.height;
        if (my_height > window_height) {
	    var top = 0;
	    my_height = window_height;
	} else {
	    var top = (window_height - my_height) / 2;
        }
	if (move_y) {
	    top += move_y;
	}

	popup_div.style.width = my_width + "px";
	//div.style.height = my_height + "px"; //will be set automatically by contained blocks
	popup_div.style.left = left + "px";
	popup_div.style.top = top + "px";

	text_div.style.width = "100%";
	text_div.style.height = (my_height-this.action_div_height) + "px";
	text_div.height = "100%";
    }

    this.set_style = function(obj, style) {
	for (var name in style) {
	    var value = style[name];
	    obj.style[name] = value;
	}
    }

    this.get_action_div = function() {
	var action_div = document.createElement("div");
	action_div.className = this.className;
	this.set_style(action_div, this.action_div_style);
	action_div.style.height = this.action_div_height

	var this_class = this;

	var login_now = document.createElement("input");
	login_now.className = this.className;
	login_now.type = "button";
	login_now.value = this.login_now_txt;
	login_now.id = this.id + "_login_now_button";
	login_now.onclick = function() {this_class.click_login_now(); return false;};
	this.set_style(login_now, this.action_button_style);
	action_div.appendChild(login_now);

	var ask_me_later = document.createElement("input");
	ask_me_later.className = this.className;
	ask_me_later.type = "button";
	ask_me_later.value = this.ask_me_later_txt;
	ask_me_later.onclick = function() {this_class.click_ask_me_later(); return false;};
	this.set_style(ask_me_later, this.action_button_style);
	action_div.appendChild(ask_me_later);

	var dont_ask_me_again = document.createElement("input");
	dont_ask_me_again.className = this.className;
	dont_ask_me_again.type = "button";
	dont_ask_me_again.value = this.dont_ask_me_again_txt;
	dont_ask_me_again.onclick = function() {this_class.click_dont_ask_me_again(); return false;};
	this.set_style(dont_ask_me_again, this.action_button_style);
	action_div.appendChild(dont_ask_me_again);

	return action_div;
    }

    this.click_login_now = function() {
	//popup link
	var my_window = window.open(this.link, "_blank");

	if (my_window) {
	    //close inline popup
	    this.close_inline_popup();
	    this.set_cookie(this.dont_show_cookie_name(), 1, this.dont_ask_me_again_seconds);
	} else {
	    //display error message
	    alert(this.failed_to_open_window);
	}
    }

    this.click_ask_me_later = function() {
	this.set_cookie(this.dont_show_cookie_name(), 1, this.ask_me_again_later_seconds);
	this.close_inline_popup();	
    }

    this.click_dont_ask_me_again = function() {
	this.set_cookie(this.dont_show_cookie_name(), 1, this.dont_ask_me_again_seconds);
	this.close_inline_popup();
    }

    this.close_inline_popup = function() {
	if (this.popup_div) {
	    document.body.removeChild(this.popup_div);
	    this.remove_grayout(false)
	    this.popup_div = null;
	    this.text_div = null;
	}
    }


    this.get_IE_version = function() {
	var ua = navigator.userAgent;
	var MSIEOffset = ua.indexOf("MSIE ");
    
	if (MSIEOffset == -1) {
	    return null;
	} else {
	    return parseFloat(ua.substring(MSIEOffset + 5, ua.indexOf(";", MSIEOffset)));
	}
    }

    this.is_IE = function() {
	return this.get_IE_version() !== null;
    }

    this.get_scroll = function() {
	var x = window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft || 0;
	var y = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0;

	return [x,y];
    }



    //Cookie handling
    this.set_cookie = function(name, value, secs) {
	if (secs) {
	    var date = new Date();
	    date.setTime(date.getTime()+(secs*1000));
	    var expires = "; expires="+date.toGMTString();
	} else {
	    var expires = "";
	}
	document.cookie = name+"="+value+expires;
    };

    this.get_cookie = function(name) {
	var sn = name + "=";
	var ca = document.cookie.split(';');
	for (var i=0; i<ca.length; i++) {
	    var c = ca[i];
	    while (c.charAt(0)==' ') {
		c = c.substring(1, c.length);
	    }
	    if (c.indexOf(sn) == 0) {
		return c.substring(sn.length, c.length);
	    }
	}
	return null;
    };




    //Grayout handling
    //Based on http://www.hunlock.com/blogs/Snippets:_Howto_Grey-Out_The_Screen , public domain
    this.get_grayout = function() {
	var id = this.id + '_grayout';

	var dark = document.getElementById(id);
	if (!dark) {
	    if (!this.positioning_inited && this.position_fixed_supported()) {
		this.positioning = "fixed";
	    }

	    // The dark layer doesn't exist, it's never been created.  So we'll
	    // create it here and apply some basic styles.
	    // If you are getting errors in IE see: http://support.microsoft.com/default.aspx/kb/927917
	    var tnode = document.createElement('div');         // Create the layer.
	    tnode.style.position = this.positioning;           // Always visible regardless of scroll
	    tnode.style.top = '0px';                           // In the top
	    tnode.style.left = '0px';                          // Left corner of the page
	    tnode.style.overflow = 'hidden';                   // Try to avoid making scroll bars            
	    tnode.style.display = 'none';                      // Start out Hidden
	    tnode.id = id;                                     // Name it so we can find it later
	    document.body.appendChild(tnode);                  // Add it to the web page
	    dark = document.getElementById(id);                // Get the object.
	    this.set_style(dark, this.grayout_style);

	    var IE_version = this.get_IE_version();
	    if (IE_version !== null && IE_version < 7) {
		dark.style.display = 'none';
	    }
	}

	//if it was shown, then hidden, then the window resized.
	this.resize_grayout(dark);

	return dark;
    }

    this.add_grayout = function() {
	dark = this.get_grayout();
	this.resize_grayout(dark);
    }

    this.remove_grayout = function() {
	var dark = this.get_grayout();
	dark.style.display = 'none';
    }

    this.resize_grayout = function(dark, move_x, move_y) {
	//If the user makes the window smaller then the dark div may
	//itself define the size if set absolutely as XXpx
	//(This fix works in FF, not in IE 8)
	dark.style.width = '100%';
	dark.style.height = '100%';

	var xy = this.get_window_width_height();
	var x = xy[0];
	var y = xy[1];
	dark.style.width = x;
	dark.style.height = y;

	if (move_x || move_y) {
	    dark.style.left = move_x;
	    dark.style.top = move_y;
	}
    }
}
