// vim: et:ts=4

// printfire is no longer supported in firebug.
// see much cooler logging functions here:
// http://joehewitt.com/software/firebug/tests/test.html

var dbcbs = [ ];

document.write('<iframe id="rpc" name="rpc" src="about:blank"></iframe>');

function mb(){}

function appendFrag(node, frag) {
    if (typeof node != 'object') node = document.getElementById(node);
    try {
        node.appendChild(frag);
    } catch (e) {
        node.innerHTML += frag.outerHTML;
    }
}

function replaceFrag(cont, elem, frag) {
    if (typeof cont != 'object') cont = document.getElementById(cont);
    if (typeof elem != 'object') elem = document.getElementById(elem);
    try {
        cont.replaceChild(frag, elem);
    } catch (e) {
        elem.outerHTML = frag.outerHTML;
    }
}

function addClass(node, cls) {
    if (typeof node != 'object') node = document.getElementById(node);
    var cl = node.className.split(/ +/);
    for (var c in cl) {
        if (cl[c] == cls) return;
    }
    cl.push(cls);
    node.className = cl.join(' ');
}

function removeClass(node, cls) {
    var cl = node.className.split(/ +/);
    var ncl = new Array();
    for (var c in cl) {
        if (cl[c] == cls) continue;
        ncl.push(cl[c]);
    }
    node.className = ncl.join(' ');
}

function update_selected(elem) {
    var id = elem.id.substr(3); // the prefix is "cb-"
    var row = document.getElementById('row-' + id);
    if (elem.checked) {
        addClass(row, 'selected');
    } else {
        removeClass(row, 'selected');
    }
}

function checkbox_changed(e) {
    if (!e) var e = window.event;
    update_selected(e.target);
}

function rand(max) {
    return Math.floor(Math.random() * max);
}

function rands(k) {
    var i;
    s = '';
    for (i = 0; i < k; i++) {
        n = rand(61);
        if (n < 10)      n += 48;
        else if (n < 36) n += 55; /* or 65 - 10 */
        else             n += 61; /* or 97 - 36 */
        s += String.fromCharCode(n);
    }
    return s;
}

function dbcb(k, data, frag) {
    if (!k) {
        alert('Internal RPC error: missing parameter k');
        return;
    }
    var cb = dbcbs[k];
    dbcbs[k] = null;
    rpcdoc().location.replace('about:blank');
    if (frag) frag.id = '_R' + rands(5);
    cb(data, frag);
}

function substi(s, a, b) {
    var i = 0;
    for (;;) {
        i = s.indexOf(a, i);
        if (i < 0) break;
        s = s.substr(0, i) + b + s.substr(i += a.length);
    }
    return s;
}

function enc(s) {
    var tab = [['%', '%25'], ['&', '%26'], ['#', '%23'], ['+', '%2B'], ['\u000A', '%0A'], ['\u000D', '%0D']];
    s = ''+s;
    for (var i = 0; i < tab.length; i++) s = substi(s, tab[i][0], tab[i][1]);
    return s;
}

function rpc(cb, f) {
    
    if (global_uid == 0) {
        window.location = masterURL + 'register?url=' + window.location.toString().substring(masterURL.length);
        return;
    }
    
    var k = rands(5);
    var url = 'rpc?k=' + k + '&f=' + f;
    for (var i = 2; i < rpc.arguments.length; i++) {
        url += '&' + (i - 2) + '=' + enc(rpc.arguments[i]);
    }
    dbcbs[k] = cb; // put the callback in here so we can find it later

    rpcdoc().location.replace(masterURL + url);
}

function rpcframe() {
    return document.getElementById('rpc');
}

function rpcdoc() {
    if (rpcframe().contentDocument) {
        return rpcframe().contentDocument; 
    } else if (rpcframe().contentWindow) {
        return rpcframe().contentWindow.document;
    } else if (rpcframe().document) {
        return rpcframe().document;
    } else if (rpcframe().window) {
        return rpcframe().window.document;
    }
    throw 'could not get rpc doc';
}

function setText(id, text) {
    var elem = document.getElementById(id);
    while (elem.childNodes.length > 0) {
        elem.removeChild(elem.firstChild);
    }
    elem.appendChild(document.createTextNode(text));
}

function setStyle(id, style) {
    document.getElementById(id).setAttribute('style', style);
}

/**
* Sets the element's display style to block
* @param id The id of the element to display
*/
function showElement(id, st) {
    var elem = document.getElementById(id);
    if (!st) st = 'block';
    if (elem) {
        elem.style.display = st;
        elem.style.visibility = 'visible';
    }
}

/**
* Sets the element's display style to none
* @param id The id of the element to hide
*/
function hideElement(id) {
    var elem = document.getElementById(id);
    if (elem) elem.style.display = 'none';
}

function invsElement(id) {
	document.getElementById(id).style.visibility = 'hidden';
}

function removeElement(id) {
    var elem = document.getElementById(id);
    if (elem) elem.parentNode.removeChild(elem);
}

function installHandler(tag, prefix, event, handler) {
    var nl = document.getElementsByTagName(tag);
    for (var i = 0; i < nl.length; i++) {
        var el = nl.item(i);
        if (el.id.indexOf(prefix) != 0) continue;
        el['on' + event] = handler;
    }
}

// By Simon Wilson
function addLoadEvent(func) {
    if (typeof window.onload != 'function') {
        window.onload = func;
    } else {
        var oldonload = window.onload;
        window.onload = function() {
            oldonload();
            func();
        }
    }
}

//Miscellaneous stuff that I use lots of places

function clearChildren(target){
	// Only do this if the target actually has children.
	if(target.hasChildNodes()) {
		var children = Array();
		for(var i=0;target.childNodes[i];i++){
			children[i] = target.childNodes[i];
		}
		for(var i=0;children[i];i++){
			target.removeChild(children[i]);
		}
	}
}

function pseudoButton (name, href, onclick){
	var physical = document.createElement('a');
	var text = document.createTextNode("("+name+")");
	physical.appendChild(text);
	physical.href = href;
	physical.onclick = onclick;
	return physical;
}

function normalButton (value, onclick){
	var button = document.createElement('input');
	button.type = "button";
    button.value = value;
	button.onclick = onclick;
	return button;
}
function submitButton(title, onclick) {
    var submit = document.createElement('input');
    submit.type = "submit";
    submit.name = title;
    submit.id = title;
    submit.value = title;
    submit.onclick = onclick;
    return submit;
}

/* eventually this should be modified to pop a more sensible error into the #errors element*/
function popError(string) {
    alert(string);
}

function load_init() {
    if (callInit) init();
    var temp_global_uid = global_uid;
    global_uid = -1;
    global_uid = temp_global_uid;
}
  
/* return true if arg is a valid zip code */
function validZip (arg,digits) {
    if(arg.length!=digits) {
        return false;
    }
    var numerals = new String("0123456789");
    for(i=0; i<digits; i++) {
        if( numerals.indexOf(arg.charAt(i)) < 0 ) {
            return false;
        }
    }
    return true;
}

function isIE() {
    //I know that I shouldn't use a browser detect, but rather an object detect - but there's no 'brower is fucked up' property
    if(navigator.userAgent.indexOf("MSIE") > -1) {
        return true;
    }
    return false;
}

function target(event) {
    if(event.target) return event.target;
    else return event.srcElement;
}


/* for the search tabs */
function searchQ(type) {
    var q = document.getElementById('q2').value;
    var filter = document.getElementById('filters');
    var filterval;
    if(filter) {
        filterval = filter.options[filter.selectedIndex].value;
    } else {
        filterval = 'All';
    }
    if(type == 'people') {
        window.location = masterURL+'search?q='+q+'&filters='+filterval;
    } else {
        window.location = masterURL+type+'/search?q='+q+'&filters='+filterval;
    }
}

function set_filter() {
    var filter = document.getElementById('filters');
    var selval = filter.options[filter.selectedIndex].value;

    var target = document.getElementById('filter_adv');
    target.value = selval;
}

//Array containing all PNG images on the page
var PNGimageArray = new Array();
var isPrinting = false;

//Path to the blank image (1x1 transparent)
var blankSrc = SURL + '/blank.gif';

//Captures print events
if(isIE()) {
    window.attachEvent("onbeforeprint", function () { beforePrint(); } );
    window.attachEvent("onafterprint", function () { afterPrint(); } );
}
//Tests if element is a PNG image, and if so fixes it
function addPngImage(element){
    var search = RegExp("/\.png$/", "i");
    if (search.test(element.src)) {
        fixImage(element);
        element.attachEvent("onpropertychange", function () 
                { propertyChanged(); } );
        PNGimageArray[PNGimageArray.length] = element;
    }
}

//Applies filter and changes source to blank
function fixImage(element) {
    element.runtimeStyle.filter = 
        "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + element.src + "')";
    element.src = blankSrc;
}

//If property "src" is changed fixs image (not 
//if it is changed to blank though)
function propertyChanged() {
    if (isPrinting) return;
    var element = event.srcElement;
    var pName = event.propertyName;
    if (pName != "src") return;
    if (!new RegExp(blankSrc).test(element.src))
        fixImage(element);

}

//Turns image back to original before print (Explorer can't print filters)
function beforePrint() {
    isPrinting = true;
    var element;
    for(var i = 0; i < PNGimageArray.length; i++){
        element = PNGimageArray[i];
        element.src = element.filters[0].src;
        element.runtimeStyle.filter = "";
    }

}

//Fixes image after print
function afterPrint() {
    isPrinting = false;
    var element;
    for(var i = 0; i < PNGimageArray.length; i++){
        element = PNGimageArray[i];
        fixImage(element);

    }
}

function getWindow(node) {
    if (typeof node != 'object') node = document.getElementById(node);
    if (!node) return node;
    if (node.contentWindow) return node.contentWindow;
    return node.window;
}

function cb_reload(url) {
	window.location.href=url;
}


/**
 * Mimics the php swaphl(), except you have to preset hl to 'even'
 * before using the function.
 */
function swapHl(hl) {
    if (hl == 'even') return 'odd';
    return 'even';
}


/************************************************************
 * RPC Buddy Lists stuff.
 */
var findTimeout;

function switchList(listsName, list) {
    if (listLoaded[listsName] != 'loaded' && list == 's') {
	    target = document.getElementById(listsName + '-contacts-list');
		target.style.height = '300px';
		
		var el = document.getElementById(listsName + '-' + list + '-list');
		el.style.display = "block";
		
		return false;
	} else if (listLoaded[listsName] != 'loaded') {
	    // If search list was unhidden, hide it:
        document.getElementById(listsName + '-s-list').style.display = "none";
	    
        // Load list.
		listLoaded[listsName] = 'loaded';
		target = document.getElementById(listsName + '-contacts-list');
		target.style.height = '300px';
		target = document.getElementById(listsName + '-results-status');
		clearChildren(target);
		saving("loading",listsName+"-results-status");
		tempListsName = listsName;
		tempList = list;
		rpc(loadContactListCompleted, "load_contact_lists",listsName,listsToPrint[listsName],info[listsName]);
		return false;
	}
	
    if (!(curList[listsName] == list)) {
    	var el = document.getElementById(listsName + '-' + list + '-list');
    	var curEl = document.getElementById(listsName + '-' + curList[listsName] + '-list');
    	
    	el.style.display = "block";
	    curEl.style.display = "none";
	    curList[listsName] = list;
    } else {
    	document.getElementById(listsName + '-' + list + '-list').style.display = "block";
    }
    
    /*
    // If we click Search All, clear out the search box.
    if (list == 's' || list == 'gs') {
    	var id = document.getElementById(listsName+'_find_id');
    	id.value = "";
    }
    */
}

function loadContactListCompleted(data) {
	var listsName = tempListsName;
	var list = tempList;
	clearInterval(intervalSaving);
	target = document.getElementById(listsName+'-results-status');
	clearChildren(target);
	target = document.getElementById(listsName+'-results-box');
	clearChildren(target);
	target.innerHTML = data;
	switchList(listsName, list);
	loadLists();
	return false;
}

function loadLists() {
	for (var p in listLoaded) {
		if (listLoaded[p] != 'loaded' && listLoaded[p] != 'collapsed' ) {
			switchList(p, listLoaded[p]);
			return;
		}
	}
}


function find_delayed(listsName) {
	if (findTimeout) {
		clearTimeout(findTimeout);
	}
	findTimeout = setTimeout('find(\''+listsName+'\')',400);
}

function find(listsName) {
	var id = document.getElementById(listsName+'_find_id');
	
	if (id.value == "(Enter name)" || id.value == "") return false;
	saving('searching',listsName+'_save_status');
	tempListsName = listsName; // Set this for receive function.
	rpc(receive, 'search_results', id.value, listsName, info[listsName]);
	return false;
}


function receive(data) {
	var listsName = tempListsName;
	
	var findResults = document.getElementById(listsName+'_find_results');
	clearChildren(findResults);
	if (data != '') {
		findResults.innerHTML = data;
		findResults.style.display = 'block';
		if (listsName == 'compose') {
			update_tofield();
	    }
	}
	clearInterval(intervalSaving);
	target = document.getElementById(listsName + '_save_status');
	clearChildren(target);
	
	var id = document.getElementById(listsName+'_find_id');
	target = document.getElementById(listsName + '_find_display');
	if (data.indexOf('No contacts.') != -1 && id.value.indexOf('@') != -1) {
		findResults.style.display = "none";
		
		target.style.display = 'block';
		target.innerHTML = "We can't find <i>"+id.value+"</i> in our database.<br><br><a href=\"invite?email="+id.value+"\">Invite them</a> to Essembly.";
	} else {
		target.style.display = "none";
	}
	return false;
}

function ignore(rid, gid) {
    function f(rid) {
        hideElement('ignore');
        showElement('unignore');
    }
    rpc(f, 'resolve_ignore', rid, gid, '');
}

function ignore_replace(rid, gid, sig) {
    function f(fr) {
        if (fr) {
            var els = copy(document.getElementsByName('r' + rid));
            for (var i = 0; i < els.length; i++) {
                var n = findNext(els[i]);
                if (n && els[i].className == 'first') {
                    n.className = 'first';
                }
                els[i].parentNode.removeChild(els[i]);
            }
            $(sig + 'l').innerHTML += fr;
        }
    }
    rpc(f, 'resolve_ignore', rid, gid, sig);
}

function ignore_noreplace(rid, gid, hid) {
    function f() {
        hideElement('i' + hid);
        showElement('u' + hid, 'inline');
    }
    rpc(f, 'resolve_ignore', rid, gid);
}

function findNext(n) {
    var x = n.nextSibling;
    while (x) {
        if (x.tagName == n.tagName) return x;
        x = x.nextSibling;
    }
    return x;
}

function findFirst(n, tn) {
    while (n) {
        if (n.tagName == tn) return n;
        n = n.nextSibling;
    }
    return n;
}

function findLast(n, tn) {
    while (n) {
        if (n.tagName == tn) return n;
        n = n.previousSibling;
    }
    return n;
}

function copy(l) {
    var v = new Array();
    for (var i = 0; i < l.length; i++) {
        v[i] = l[i];
    }
    return v;
}

function unignore(rid, gid) {
    function f(rid) {
        if (rid) {
            showElement('ignore', 'inline');
            hideElement('unignore');
        }
    }
    rpc(f, 'resolve_unignore', rid, gid);
}

function unignore_noreplace(rid, gid, hid) {
    function f() {
        hideElement('u' + hid);
        showElement('i' + hid, 'inline');
    }
    rpc(f, 'resolve_unignore', rid, gid);
}

String.prototype.splice = function(start, len, rep) {
    return (this.substring(0, start) +
            rep +
            this.substring(start + len, this.length));
}

function _(fmt, dict) {
    var i = 0;
    while ((i = fmt.indexOf('%(', i)) > -1) {
        var e = fmt.indexOf(')', i);
        if (e < 0) break;
        var r = fmt.substring(i, e + 2);
        var k = r.substring(2, r.length - 2);
        var n = dict[k];
        if (n == null) n = r;
        fmt = fmt.splice(i, r.length, n);
        i += n.length;
    }
    return fmt;
}

function makeActive(elem) {
    if (document.getElementById('active') != null) {
        document.getElementById('active').id = '';
    }
    if (elem != null) {
        elem.id = 'active';
    }
}

/*
 * This handy function allows for default text to display in blank fields.
 * The default text is reinserted if the field is blank.
 *
 * @author Chris Chan <cchan05@gmail.com>
 */
function initDefaultTextHandler(id, defaultText) {
  var elem = document.getElementById(id);
  var message = defaultText;
  if (elem.value == "") {
    elem.value = message;
    elem.style.color = "#666";
  }
  elem.onfocus = function () { this.style.color = '#000'; if (this.value == message) this.value = ""; };
  elem.onblur = function () { if (this.value == "") {this.style.color = '#666'; this.value = message; }};
}

/**
 * I don't really know how this fits with Chris' thing and
 * probably needs to be refactored.
 */
function initDefaultTextHandlerForPrintEntityLists(id, defaultText, listsName) {
    var elem = document.getElementById(id);
    var message = defaultText;
    if (elem.value == "") {
        elem.value = message;
        elem.style.color = "#666";
    }
    elem.onfocus = function () {
        this.style.color = '#000';
        if (this.value == message) this.value = "";
        makeActive();
        switchList(listsName, "s");
    };
    elem.onblur = function () {
        if (this.value == "") {
            this.style.color = '#666'; this.value = message;
        }
    };
}


/*
 * Utility functions for determining the number of characters remaining in a text entry box.
 *
 */
function atboi(o) {
    return o.selectionStart == 0;
}   
    
function selspan(o) {
    return o.selectionEnd - o.selectionStart;
}
