/**
 * copyright: (c) 2011, kalbeck.media. All rights reserved.
 * version: 1.0
 */
huxley = {};
huxley.DEFAULT_TITLE = ' :: kaidoo.cms v2.0';
huxley.DEBUG = true;
huxley.clipboard = null;

/******************************************************************************
 ********** application configuration
 ******************************************************************************/

huxley.app_base_url = "http://www.kalbeck.com";
huxley.appcfg = {
    language_codes: ['en','de','es'],
    hostname: "www.kalbeck.com",
    hostname_en: "www.kalbeck.com",
    hostname_de: "www.kalbeck.com",
    hostname_es: "www.kalbeck.com",
    url_base: huxley.app_base_url,
    api_base: huxley.app_base_url + "/api.php/",
    help_getter: huxley.app_base_url+ "/xhr_kb/gettopic",
    thumbnail_getter: huxley.app_base_url + "/xhr_assets/getthumb",
    asset_getter: huxley.app_base_url + "/api.php/getasset",
    estate_printer: huxley.app_base_url + "/estates/expose",
    css_img_base: "/css/img/",
    image_base: huxley.app_base_url + "/img/",
    profiler: huxley.app_base_url + "/profile.php"
};

huxley.ID_MSG_INLINE_EDIT_HINT = 1001;

huxley.l10n = {};
huxley.l10n.languages = [
    {
        code: 'en'
        ,is_default: true
        ,strings: [
            { id: huxley.ID_MSG_INLINE_EDIT_HINT, value: 'Supports inline editing.' }
        ]
    }
];

huxley.l10n.getDefaultLanguage = function() {
    for (var i=0,l=this.languages.length;i<l;i++) {
        if (this.languages[i].is_default) {
            return this.languages[i];
        }
    }
    return null;
};

huxley.l10n.getLanguage = function(lc) {
    for (var i=0,l=this.languages.length;i<l;i++) {
        if (this.languages[i].code == lc) {
            return this.languages[i];
        }
    }
    return null;
};

huxley.l10n.getString = function(id,lc) {
    var lang = lc ? this.getLanguage(lc) : this.getDefaultLanguage();
    if (lang) {
        for (var i=0,l=lang.strings.length;i<l;i++) {
            if (lang.strings[i].id == id) {
                return lang.strings[i].value;
            }
        }
        return '[BAD ID: ' + id + ']';
    }
    else {
        return '[BAD LANGUAGE: ' + lc + ']';
    }
};
/******************************************************************************
 ********** URL tools
 ******************************************************************************/

huxley.urlparts = {
    hash: document.location.hash,
    host: document.location.host,
    hostname: document.location.hostname,
    href: document.location.href,
    pathname: document.location.pathname,
    port: document.location.port,
    protocol: document.location.protocol,
    search: document.location.search
};

/******************************************************************************
 ********** dom tools
 ******************************************************************************/

huxley.destroyElement = function(e) {
	if (e) {
		var p = e.parentNode;
		if (p) {
			p.removeChild(e);
		}
	}
};

huxley.showElement = function(elId) { YAHOO.util.Dom.setStyle(elId,'visibility','visible'); }
huxley.hideElement = function(elId) { YAHOO.util.Dom.setStyle(elId,'visibility','hidden'); }

huxley.destroyElementById = function(elId) {
	var el = document.getElementById(elId);
	destroyElement(el);
};

huxley.styleElement = function(el,valArray) {
	var i = 0;
	var al = valArray.length;
	while (i<al) {
		el.style[valArray[i]] = valArray[i+1];
		i+=2;
	}
};

huxley.parseObject = function(sIn) {
    var ss = sIn.split(",");
    var res = new Object();
    var name, value, se, dp;
    for (var i=0, ssc = ss.length;i<ssc;i++) {
        se = ss[i];
        dp = se.indexOf("=");
        name = se.substring(0,dp);
        value = se.substring(dp+1);
        res[name] = value;
    }
    return res;
};

huxley.tryJSONParse = function(txt) {
    var res;
    try {
        res = YAHOO.lang.JSON.parse(txt);
    }
    catch (e) {
        alert("Bad json:\n" + txt + "\nexception: " + e);
        return null;
    }
    return res;
}

huxley.print_var = function(arr,level) {
	var dumped_text = "";
	if(!level) { 
        level = 0;
    }
	//The padding given at the beginning of the line.
	var level_padding = "";
	for(var j=0;j<level+1;j++) { 
        level_padding += "    ";
    }
	if(typeof(arr) == 'object') { //Array/Hashes/Objects
		for(var item in arr) {
			var value = arr[item];

			if(typeof(value) == 'object') { //If it is an array,
				dumped_text += level_padding + "'" + item + "' ...\n";
				dumped_text += dump(value,level+1);
			} else {
				dumped_text += level_padding + "'" + item + "' => \"" + value + "\"\n";
			}
		}
	} else { //Stings/Chars/Numbers etc.
		dumped_text = "===>"+arr+"<===("+typeof(arr)+")";
	}
	return dumped_text;
}

/**
 * This one comes from the php.js project.
 * For credits and reference see: http://phpjs.org/functions/strcmp
 */
huxley.strcmp = function(s1, s2) {
    return ((s1 == s2) ? 0 : ((s1 > s2) ? 1 : -1));
}

huxley.objectArrayInsertAfter = function(aTarget, sTestProperty, oRecord, aProperties) {
    var testval = oRecord[sTestProperty];
    var valtype = typeof(testval);
    if (valtype != 'string' && valtype != 'boolean' && valtype != 'number') {
        alert('[ERROR] huxley.objectArrayInsertAfter: Test value ' +  testval + ' may not be of type ' + valtype);
        return false;
    }
    var match;
    for (var i=0,l=aTarget.length;i<l;i++) {
        match = false;
        switch (valtype) {
        case 'string':
            if (huxley.strcmp(testval,aTarget[sTestProperty]) >= 0) {
                match = true;
            }
            break;
        case 'boolean':
        case 'number':
            if (testval > aTarget[i][sTestProperty]) {
                match = true;
            }
        default:
            alert('[ERROR] huxley.objectArrayInsertAfter: Unknown value type "' + valtype + '". Aborting operation.');
            return false;
        }
        if (match) {
            aTarget.splice(i,0,{});
            if (aProperties) {
                for (var pi=0,pl=aProperties.length;pi<pl;pi++) {
                    aTarget[i][aProperties[pi]] = oRecord[aProperties[pi]];
                }                
            }
            else {
                aTarget[i] = oRecord;
            }
            return true;
        }
    }
    // add to end, if not found
};

huxley.objectArraySet = function(aTarget, sTestProperty, oRecord, aProperties) {
    for (var i=0,l=aTarget.length;i<l;i++) {
        if (aTarget[i][sTestProperty] == oRecord[sTestProperty]) {
            if (aProperties) {
                for (var pi=0,pl=aProperties.length;pi<pl;pi++) {
                    aTarget[i][aProperties[pi]] = oRecord[aProperties[pi]];
                }
            }
            else {
                aTarget[i] = oRecord;
            }
            return true;
        }
    }
    return false;
};

huxley.getViewportWidth = function() {
  var res = 0;
  if( typeof( window.innerWidth ) == 'number' ) {
    //Non-IE
    res = window.innerWidth;
  } else if( document.documentElement && ( document.documentElement.clientWidth || document.documentElement.clientHeight ) ) {
    //IE 6+ in 'standards compliant mode'
    res = document.documentElement.clientWidth;
  } else if( document.body && ( document.body.clientWidth || document.body.clientHeight ) ) {
    //IE 4 compatible
    res = document.body.clientWidth;
  }
  return res;
}

huxley.getViewportHeight = function() {
  var res = 0;
  if( typeof( window.innerWidth ) == 'number' ) {
    //Non-IE
    res = window.innerHeight;
  } else if( document.documentElement && ( document.documentElement.clientWidth || document.documentElement.clientHeight ) ) {
    //IE 6+ in 'standards compliant mode'
    res = document.documentElement.clientHeight;
  } else if( document.body && ( document.body.clientWidth || document.body.clientHeight ) ) {
    //IE 4 compatible
    res = document.body.clientHeight;
  }
  return res;
}

huxley.getViewport = function() {
  var res = {width: 0, height: 0};
  
  if( typeof( window.innerWidth ) == 'number' ) {
    //Non-IE
    res.width = window.innerWidth;
    res.height = window.innerHeight;
  } else if( document.documentElement && ( document.documentElement.clientWidth || document.documentElement.clientHeight ) ) {
    //IE 6+ in 'standards compliant mode'
    res.width = document.documentElement.clientWidth;
    res.height = document.documentElement.clientHeight;
  } else if( document.body && ( document.body.clientWidth || document.body.clientHeight ) ) {
    //IE 4 compatible
    res.width = document.body.clientWidth;
    res.height = document.body.clientHeight;
  }
  return res;
}

huxley.loadScripts = function(sContent) {
    var stag = '<script type="text/javascript">';
    var etag = '</script>';
    var stl = stag.length;
    var etl = etag.length;
    var sidx = 0;
    var eidx = 0;
    var code;
    var midx = sContent.indexOf(stag,sidx);
    while (midx != -1) {
        eidx = sContent.indexOf(etag,midx+stl);
        if (eidx == -1) {
            alert('Incomplete <script> tag in response. Aborting.');
            return false;
        }
        code = sContent.substring(midx+stl,eidx);
        eval(code);
        sidx = eidx + etl;
        midx = sContent.indexOf(stag,sidx);
    }
    return true;
};

huxley.showHelp = function(section,topic) {
    var req_url = huxley.appcfg.help_getter + "?s=" + section + "&t=" + topic;
    YAHOO.util.Connect.asyncRequest("GET",req_url,{
        failure: function() {
            alert("Help loader should return \"missing topic\" notice.");
        },
        success: function(o) {
            var unit = huxley.ui.mainLayout.getUnitByPosition('right');
            unit.body.innerHTML = o.responseText;
            unit.expand();
        }
    });
}

huxley.strStartsWith = function(str, pre) {
    return str.indexOf(pre) == 0;
}

huxley.strEndsWith = function(str, suff) {
    return str.lastIndexOf(suff) == str.length() - suff.length()
}

huxley.formatStringArray = function(a) {
    var res = "[";
    var first = true;
    for (var i=0,l=a.length;i<l;i++) {
        if (first) {first = false;} else {res += ",";}
        res += a[i];
    }
    return res + "]";
}

huxley.getFeedbackValuei = function(fb, name) {
    if (fb.values) {
        for (var i=0,l=fb.values.length;i<l;i++) {
            if (fb.values[i].name == name) {
                var ret = parseInt(fb.values[i].value);
                return isNaN(ret) ? 0 : ret;
            }
        }
        return 0;
    }
    else {
        return 0;
    }
}

huxley.getFeedbackValue = function(fb, name) {
    if (fb.values) {
        for (var i=0,l=fb.values.length;i<l;i++) {
            if (fb.values[i].name == name) {
                return fb.values[i].value;
            }
        }
        return null;
    }
    else {
        return null;
    }
}

huxley.formatFeedbackFatalsHTML = function(fb) {
    var i, l, res = "";
    if (fb.fatals) {
        for (i=0,l=fb.fatals.length;i<l;i++) {
            res += "[FATAL] " + fb.fatals[i] + "<br/>";
        }
    }
    return res;
}

huxley.formatFeedbackErrorsHTML = function(fb) {
    var i, l, res = "";
    if (fb.errors) {
        for (i=0,l=fb.errors.length;i<l;i++) {
            res += "[ERROR] " + fb.errors[i] + "<br/>";
        }
    }
    return res;
}

huxley.formatFeedbackWarningsHTML = function(fb) {
    var i, l, res = "";
    if (fb.warnings) {
        for (i=0,l=fb.warnings.length;i<l;i++) {
            res += "[WARNING] " + fb.warnings[i] + "<br/>";
        }
    }
    return res;
}

huxley.formatFeedbackInfosHTML = function(fb) {
    var i, l, res = "";
    if (fb.infos) {
        for (i=0,l=fb.infos.length;i<l;i++) {
            res += "[INFO] " + fb.infos[i] + "<br/>";
        }
    }
    return res;
}

huxley.formatFeedbackValuesHTML = function(fb) {
    var i, l, res = "";
    if (fb.values) {
        for (i=0,l=fb.values.length;i<l;i++) {
            res += "[VALUE] " + fb.values[i].name + " = " + fb.values[i].value + "<br/>";
        }
    }
}

huxley.formatFeedbackNamedBlockHTML = function(fb, name) {
    switch (name) {
    case "fatals":return this.formatFeedbackFatalsHTML(fb);
    case "errors":return this.formatFeedbackErrorsHTML(fb);
    case "warnings":return this.formatFeedbackWarningsHTML(fb);
    case "infos":return this.formatFeedbackInfosHTML(fb);
    case "values":return this.formatFeedbackValuesHTML(fb);
    default:return "";
    }
}

huxley.formatFeedbackHTML = function(fb, blocks) {
    var i,l, res = "";
    if (YAHOO.lang.isUndefined(blocks)) {
        res += this.formatFeedbackFatals(fb);
        res += this.formatFeedbackErrors(fb);
        res += this.formatFeedbackWarnings(fb);
        res += this.formatFeedbackInfos(fb);
        res += this.formatFeedbackValues(fb);
    }
    else if (YAHOO.lang.isArray(blocks)) {
        for (i=0,l=blocks.length;i<l;i++) {
            res += this.formatFeedbackNamedBlockHTML(fb, blocks[i]);
        }
    }
    else {
        res += this.formatFeedbackNamedBlockHTML(fb, blocks);
    }
    return res;
}
/******************************************************************************
 ********** common dialogs
 ******************************************************************************/

huxley.showMessage = function(msg) {
	if (!huxley._messageBox) {
		huxley._messageBox = new YAHOO.widget.SimpleDialog("ky_message_box", {
			width:"30em", visible:false, fixedcenter: true, constraintoviewport:true, modal: true,
			buttons: [{text: 'Close', handler: huxley.hideMessage}]
		});
		if (!huxley._messageBox.render()) {
			alert("dialog could not be rendered.");
		}
	}
	huxley._messageBox.setBody(msg);
	huxley._messageBox.show();
};

huxley.hideMessage = function() {
	if (huxley._messageBox) {huxley._messageBox.hide();}
};

huxley.showLoader = function() {
	var k = huxley;
	if (!k._loadingScreen) {
		k._loadingScreen = new YAHOO.widget.Panel("ky_loader",{width: "200px", fixedcenter: true, close: false, draggable: false, zindex: 4, modal: true, visible: false});
		k._loadingScreen.setHeader("Loading, please wait...");
		k._loadingScreen.setBody("<img src=\"/img/ajax-loader.gif\" style=\"margin-left: auto; margin-right: auto;\"/>");
		k._loadingScreen.render(document.body);
	}
	k._loadingScreen.show();
};

huxley.hideLoader = function() {
	var k = huxley;
	if (k._loadingScreen) {
		k._loadingScreen.hide();
	}
};

huxley.inArray = function(v, a) {
	for (var i=0, l=a.length;i<l;i++) {
		if (a[i] == v) {
			return true;
		}
	}
	return false;
};

/**
 * copyright: (c) 2010, kalbeck.media. All rights reserved.
 * version: 1.0
 * content:
 *     <code>huxley.ui</code> is the base class for huxley javascript user interface classes and utilities.
 *     It contains tool functions, symbolic constants and supplemental classes to handle common
 *     tasks in huxley UI projects.
 */

(function() {
    var _hux = huxley;
    _hux.ui = new Object();
    var _ui = _hux.ui;
    _ui.moduleCleanups = [];

    // paginator setup (kept here to be common for all editors)
    _ui.PG_TEMPLATE_P1 = '{CurrentPageReport}: {FirstPageLink} {PreviousPageLink} {NextPageLink} {LastPageLink} ';
    _ui.PG_TEMPLATE_P2 = '{RowsPerPageDropdown}'; // {FilterDropDown}';
    _ui.PG_LBL_FIRST_LINK = '|&lt;&lt;';
    _ui.PG_LBL_PREV_LINK = '&lt;&lt;';
    _ui.PG_LBL_NEXT_LINK = '&gt;&gt;';
    _ui.PG_LBL_LAST_LINK = '&gt;&gt;|';

    _ui._target_module_url = "";
    _ui._last_module_url = "";
    _ui._current_module_url = "";
    _ui.nestedLayout = null;
    _ui.mainLayout = null;
    _ui.defaultContentHTML = '<div id="content" style="padding: 10px; background: #fff url(\'http://www.the-construct.at/fm/www/img/gray_gears_03.jpg\') no-repeat left bottom; height: 97%;"></div>';

    _ui.debugValidatorOptions = {response: 'mark', error_action: 'continue', error_class: 'hux_form_error', debug: true};
    _ui.defaultValidatorOptions = {response: 'mark', error_action: 'continue', error_class: 'hux_form_error', debug: false};
    _ui.defaultDatatableConfig = {initialLoad: true,initialRequest: "sort=id&dir=asc&startIndex=0&results=25",dynamicData: true,draggableColumns: true,sortedBy: {key: "id", dir: "yui-dt-asc"}};

    _ui.defaultCurrencyOptions =  {
        prefix: "&euro;&nbsp;", decimalPlaces: 2, decimalSeparator: '.', thousandsSeparator: ","
    };

    _ui.defaultFailureHandler = function(o) {
        var dom = YAHOO.util.Dom;
        var ra = dom.get('resp');
        if (ra) {
            ra.innerHTML = o.status + "<br/>" + o.responseText;
            dom.addClass(ra,"hux_feedback_error");
        }
    };

    _ui.conveyError = function(msg) {
        alert(msg);
    }

    _ui.defaultSuccessHandler = function(o) {
        var dom = YAHOO.util.Dom;
        var ra = dom.get('resp');
        if (ra) {
            if (dom.hasClass(ra,"hux_feedback_error")) {
                dom.removeClass(ra,"hux_feedback_error");
            }
            ra.innerHTML = o.responseText;
        }
    }

    _ui.initDatatable = function(dt) {
        dt.set("paginator",this.createPaginator(),false);
        dt.render();
        dt.subscribe("rowMouseoverEvent",dt.onEventHighlightRow);
        dt.subscribe("rowMouseoutEvent",dt.onEventUnhighlightRow);
        dt.handleDataReturnPayload = function(oRequest, oResponse, oPayload) {
            oPayload.totalRecords = oResponse.meta.totalRecords;
            return oPayload;
        }
    }

    _ui._current_module_url = "";

    _ui.setCurrentModuleURL = function(url) {_ui._current_module_url = url;}
    _ui.getCurrentModuleURL = function() {return _ui._current_module_url;}

    _ui.getFormValuesAsObject = function(form_ref,name_array) {
        var res = {};
        for (var i=0, l=name_array.length;i<l;i++) {
            res[name_array[i]] = form_ref[name_array[i]].value;
        }
        return res;
    }

    _ui.createPaginator = function(item_count) {
        var ui = huxley.ui;
        var paginator = new YAHOO.widget.Paginator({
                rowsPerPage: 10
                ,totalRecords: item_count
                ,template: ui.PG_TEMPLATE_P1 + 'entries per page:&nbsp;' + ui.PG_TEMPLATE_P2
                ,firstPageLinkLabel: ui.PG_LBL_FIRST_LINK
                ,previousPageLinkLabel: ui.PG_LBL_PREV_LINK
                ,nextPageLinkLabel: ui.PG_LBL_NEXT_LINK
                ,lastPageLinkLabel: ui.PG_LBL_LAST_LINK
                ,pageReportTemplate: "Page {currentPage} of {totalPages}"
                ,rowsPerPageOptions : [
                    {text: "5", value: 5}
                    ,{text: "10", value: 10}
                    ,{text: "20", value: 20}
                    ,{text: "show all", value: "all"}
                ]
            });
        return paginator;
    }

    _ui.selectDefaultOption = function(swidget) {
        if (swidget.tagName.toLowerCase() != "select") {
            return false;
        }
        for (var i=0,l=swidget.options.length;i<l;i++) {
            if (swidget.options[i].defaultSelected) {
                swidget.selectedIndex = swidget.options[i].index;
                return true;
            }
        }
        return false;
    }

    _ui.selectOptionByValue = function(swidget, value) {
        if (swidget.tagName.toLowerCase() != "select") {
            return false;
        }
        var i = 0;
        var oct = swidget.options.length;
        var opt;
        while (i<oct) {
            opt = swidget.options[i];
            if (opt.value == value) {
                opt.selected = true;
                return true;
            }
            i++;
        }
        return false;
    }

    _ui.selectOptionByText = function(swidget, text) {
        if (swidget.tagName.toLowerCase() != "select") {
            return false;
        }
        var i = 0;
        var oct = swidget.options.length;
        var opt;
        while (i<oct) {
            opt = swidget.options[i];
            if (opt.text == text) {
                opt.selected = true;
                return true;
            }
            i++;
        }
        return false;
    };
    
    _ui.selectOption = function(swidget, otext) {
        if (swidget.tagName.toLowerCase() != "select") {
            return false;
        }
        var i = 0;
        var oct = swidget.options.length;
        var opt;
        while (i<oct) {
            opt = swidget.options[i];
            if (opt.text == otext) {
                opt.selected = true;
                return true;
            }
            i++;
        }
        return false;
    };

    _ui.getSelectedText = function(swidget) {
        return swidget.tagName.toLowerCase() != "select" ? "" : swidget.options[swidget.selectedIndex].text;
    };
    
    _ui.clearSelect = function(swidget) {
        if (swidget.tagName.toLowerCase() != "select") {
            return false;
        }
        while (swidget.length > 0) {
            swidget.remove(0);
        }
        return true;
    }

    _ui.addSelectOption = function(swidget, value, text, is_default) {
        if (swidget.tagName.toLowerCase() != "select") {
            return false;
        }
        var o = document.createElement('option');
        o.value = value;
        o.text = text;
        o.defaultSelected = is_default || false;
        sw.add(o,null);
        return true;
    }
    
    _ui.setFormInputFormFromRecord = function(form, record, field_names) {
        for (var i=0,l=field_names.length;i<l;i++) {
            form["item[" + field_names[i] + "]"].value = record.getData(field_names[i]);
        }
    }
    
    _ui.resetL10nFieldGroup = function(form, name) {
        var lcs = huxley.appcfg.language_codes;
        var el, nn, fen;
        for (var i=0,l=form.elements.length;i<l;i++) {
            el = form.elements[i];
            nn = el.nodeName;
            if (nn != 'INPUT' && nn != 'TEXTAREA') {
                continue;
            }
            fen = el.name;
            if (!huxley.strStartsWith(fen,name)) {
                continue;
            }
            for (var li=0,ll=lcs.length;li<ll;li++) {
                if (huxley.strEndsWith(fen,'_' + lcs[li])) {
                    switch (el.type.toLowerCase()) {
                    case 'text':
                    case 'hidden':
                        el.value = "";
                        break;
                    }
                }
            }
        }
    }

    _ui.setCheckbox = function(cwidget, value) {
        if (cwidget.type.toLowerCase() != "checkbox") {
            return false;
        }
        cwidget.checked = value ? true : false;
        return true;
    };

    _ui.toggleModule = function(id, btn) {
        var dom = YAHOO.util.Dom;
        var mdl = dom.get(id);
        if (!mdl) {return false;}
        var bd = dom.getElementsByClassName('hux_bd','div',mdl)[0];
        bd.style.display = bd.style.display != 'none' ? 'none' : 'block';
        if (dom.hasClass(btn,'hux_toggle_open')) {
            dom.replaceClass(btn,'hux_toggle_open','hux_toggle_close');
        }
        else if (dom.hasClass(btn,'hux_toggle_close')) {
            dom.replaceClass(btn,'hux_toggle_close','hux_toggle_open');
        }
        return true;
    };

    _ui.addModuleCleanup = function(f) {
        this.moduleCleanups[this.moduleCleanups.length] = f;
    }

    _ui.performModuleCleanup = function() {
        for (var i=0, l=this.moduleCleanups.length;i<l;i++) {
            this.moduleCleanups[i]();
        }
        this.moduleCleanups = [];
    }

    _ui.showXHRSuccess = function(text) {
        this.showXHRStatus(text,{text_display: 3000, delay: 1000, color: '#1aa026'});
    }
    
    _ui.showXHRFailure = function(text) {
        this.showXHRStatus(text,{text_display: 5000, delay: 1000, color: '#ec1a1a'});
    }
    
    _ui.showXHRInfo = function(text) {
        this.showXHRStatus(text,{text_display: 2000, delay: 1000, color: ''});
    }
    
    _ui.showXHRStatus  = function(text, options) {
        var delay = 1000;
        var text_display = 2000;
        var color = '#fdf97f';
        if (options) {
            text_display = options.text_display || 2000;
            delay = options.delay || 1000;
            color = options.color || '#fdf97f';
        }
        var dom = YAHOO.util.Dom;
        // get the status div
        var pnl = dom.get('pnlXHRStatus');
        pnl.innerHTML = text;
        dom.setStyle(pnl,'display','block');
        dom.setStyle(pnl,'backgroundColor',color);
        dom.setStyle(pnl,'opacity',1.0);
        var keep = new YAHOO.util.Anim(pnl,{opacity: {to: 1}}, text_display / 1000);
        keep.onComplete.subscribe(function () {
            var anim = new YAHOO.util.Anim('pnlXHRStatus',{opacity: {to: 0}}, (delay / 1000));
            anim.onComplete.subscribe(function () {
                YAHOO.util.Dom.setStyle('pnlXHRStatus','display','none');
            });
            anim.animate();
        });
        keep.animate();
    }
    
    _ui.loadModule = function(url, target_id) {
        var hux = huxley;
        var tid = target_id ? target_id : 'content';
        hux.ui._target_module_url = url;
        this.performModuleCleanup();
        if (!hux.cbModuleShow) {
            hux.cbModuleShow = {
                success: function(o) {
                    var target = document.getElementById(tid);
                    var response = o.responseText;
                    target.innerHTML = response;
                    hux.loadScripts(response);
                    hux.ui._last_module_url = hux.ui._current_module_url;
                    hux.ui._current_module_url = url;
                    hux.ui._current_module_target_id = tid;
                    hux.ui._current_module_target = target;
                    hux.hideLoader();
                },
                failure: function(o) {
                    var target = document.getElementById(tid);
                    target.innerHTML = "AJAX CONNECTION FAILED!<br/><em>Server said:</em></br>" + o.responseText;
                    hux.hideLoader();
                }
            };
        }
        hux.showLoader();
        YAHOO.util.Connect.asyncRequest("GET",url,hux.cbModuleShow);
    };

    _ui.reloadModule = function() {
        var hux = huxley;
        var tid = hux.ui._current_module_target_id;
        if (!hux.cbModuleReload) {
            hux.cbModuleReload = {
                success: function(o) {
                    var target = document.getElementById(tid);
                    var response = o.responseText;
                    target.innerHTML = response;
                    hux.loadScripts(response);
                    hux.hideLoader();
                },
                failure: function(o) {
                    var target = document.getElementById(tid);
                    target.innerHTML = "AJAX CONNECTION FAILED!<br/><em>Server said:</em></br>" + o.responseText;
                    hux.hideLoader();
                }
            };
        }
        hux.showLoader();
        YAHOO.util.Connect.asyncRequest("GET",url,hux.cbModuleShow);
    }

    _ui.setNavMark = function(url) {
        var rm = url.substr(huxley.appcfg.url_base.length);
        window.location.hash = "#" + rm;
    }
    /**
     * This is compatible to the interface used for YUI data table formatting functions (which is where
     * it's supposed to be used).
     */
    _ui.formatBoolean = function(el, oRecord, oColumn, oData) {
        var bChecked;
        if (YAHOO.lang.isBoolean(oData)) {
            bChecked = oData;
        }
        else if (YAHOO.lang.isString(oData)) {
            bChecked = oData == "1" ? true : false;
        }
        else if (YAHOO.lang.isNumber(oData)) {
            bChecked = oData > 0 ? true : false;
        }
        else {
            alert('Illegal argument passed to huxley boolean formatter: ' + oData);
        }
        
        el.innerHTML = bChecked ? "<span>Yes</span>" : "<span>No</span>";
    };

    _ui.formatButton = function(el, oRecord, oColumn, oData) {
        var sValue = YAHOO.lang.isValue(oData) ? oData : "...";
        el.innerHTML = "<button type=\"button\" class=\"" +  YAHOO.widget.DataTable.CLASS_BUTTON + "\">" + sValue + "</button>";
    }
    
    _ui.formatEstateExposeLink = function(el, oRecord, oColumn, oData) {
//        var sValue = YAHOO.lang.isValue(oData) ? oData : "expose";
        el.innerHTML = "<a target=\"_blank\" href=\"" + huxley.appcfg.estate_printer + "?refnr=" + oRecord.getData("refnr") + "\">expose</a>";
    }
    
//    _ui.formatPortalArticleRadio = function(el, oRecord, oColumn, oData) {
//        var sValue = YAHOO.lang.isValue(oData) ? oData : "...";
//        el.innerHTML = "<input type=\"radio\" class=\"" +  YAHOO.widget.DataTable.CLASS_RADIO + "\">" + sValue + "</button>";
//    }
    
    _ui.formatDimensions = function(el, oRecord, oColumn, oData) {
        el.innerHTML = oRecord.getData("width") + " x " + oRecord.getData("height");
    }

    _ui.formatThumbnail = function(el, oRecord, oColumn, oData) {
        el.innerHTML = huxley.ui.getThumbnailHTML(oData);
    }

    _ui.getThumbnailHTML = function(thumbnail_fn) {
        return "<img src=\"" + huxley.appcfg.thumbnail_getter + "?fn=" + thumbnail_fn + "\" />";
    }

    _ui.formatAsset = function(el, oRecord, oColumn, oData) {
        el.innerHTML = huxley.ui.getAssetHTML(oData);
    }

    _ui.getAssetHTML = function(asset_id) {
        return "<img src=\"" + huxley.appcfg.asset_getter + "?id=" + asset_id + "\" />";
    }
    
    _ui.getInlineEditableLabel = function(text, has_right) {
        var hr = typeof(has_right) != 'undefined' ? has_right : true;
        if (!hr) {
            return text;
        }
        return '<div class="icon_inline_editable" title="' + huxley.l10n.getString(huxley.ID_MSG_INLINE_EDIT_HINT) + '">&nbsp;</div>&nbsp;' + text;
    }
    
    _ui.getImageURI = function(img_name) {
        return huxley.appcfg.image_base + img_name;
    }

    _ui.buildEnumCell = function(elParentRow, sName, oaData, sStyle) {
        var d = document;
        var cell = d.createElement("td");
        var html = "<select name=\"" + sName + "\"";
        if (sStyle != "") {
            html += " style=\"" + sStyle + "\"";
        }
        html += "/>";
        for (var l=oaData.length, i=0;i<l;i++) {
            html += "<option value=\"" + oaData[i].value + "\">" + oaData[i].name + "</option>";
        }
        html += "</select>";
        cell.innerHTML = html;
        if (elParentRow) {
            elParentRow.appendChild(cell);
        }
        return cell;
    };

    _ui.buildIntegerCell = function(elParentRow, sName, sStyle) {
        var d = document;
        var cell = d.createElement("td");
        cell.innerHTML = "<input type=\"text\" name=\"" + sName + "\" style=\"" + sStyle + "\"/>";
        if (elParentRow) {
            elParentRow.appendChild(cell);
        }
        return cell;
    };

    _ui.buildStringCell = function(elParentRow, sName, sStyle) {
        var d = document;
        var cell = d.createElement("td");
        cell.innerHTML = "<input type=\"text\" name=\"" + sName + "\" style=\"" + sStyle + "\"/>";
        if (elParentRow) {
            elParentRow.appendChild(cell);
        }
        return cell;
    };

    _ui.buildBooleanCell = function(elParentRow, sName, sStyle) {
        var d = document;
        var cell = d.createElement("td");
        cell.innerHTML = "<input type=\"checkbox\" name=\"" + sName + "\" style=\"" + sStyle + "\"/>";
        if (elParentRow) {
            elParentRow.appendChild(cell);
        }
        return cell;
    };

    _ui.buildLabelCell = function(elParentRow, sFor, sCaption, sWidth) {
        var d = document;
        var cell = d.createElement("td");
        if (sWidth != "") {
            cell.style.width = sWidth;
        }
        cell.innerHTML = "<label for=\"" + sFor + "\">" + sCaption + ":&nbsp;</label>";
        if (elParentRow) {
            elParentRow.appendChild(cell);
        }
        return cell;
    };

    /**
     * build three divs with classed "hd", "bd", "ft" and inline style for
     * body div. Returns the body div element.
     */
    _ui.buildDialogueCarrier = function(sId, bBuildFooter) {
        var d = document;
        var host = d.createElement("div");
        host.setAttribute("id",sId);

        var hd = d.createElement("div");
        hd.className = "hd";
        hd.appendChild(d.createTextNode("&nbsp;"));
        host.appendChild(hd);

        var bd = d.createElement("div");
        bd.className = "bd";
        bd.style.overflow = "auto";
        host.appendChild(bd);

        if (bBuildFooter) {
            var ft = d.createElement("div");
            ft.className = "ft";
            host.appendChild(ft);
        }
        return bd;
    };

    _ui.buildHiddenInput = function(elParent,sName,sValue) {
        var el = document.createElement("input");
        el.type = "hidden";
        el.name = sName;
        el.value = sValue;
        if (elParent) {
            elParent.appendChild(el);
        }
        return el;
    };

    _ui.buildTableElement = function(elParent, sId, sClass) {
        var el = document.createElement("table");
        if (sId != "") {
            el.id = sId;
        }
        if (sClass != "") {
            el.className = sClass;
        }
        if (elParent) {
            elParent.appendChild(el);
        }
        return el;
    };

    _ui.buildFormElement = function(elParent,sName,sMethod,sAction) {
        var el = document.createElement("form");
        el.name = sName;
        el.method = sMethod;
        el.action = sAction;
        if (elParent) {
            elParent.appendChild(el);
        }
        return el;
    };
})();

/**
 * huxley.ui.validator
 * copyright: (c) 2010, kalbeck.media. All rights reserved.
 * version: 1.0
 * content:
 *     The validator class is a part of the huxley.ui namespace and performs requirement-based
 *     validation of named form fields together with configurable feedback including alerts,
 *     callbacks and automatic generation and scrubbing of error message mark up.
 *     
 *     The validator can be used with YUI's Dialog widget by simply setting 
 *     <code>dialog.validate = function (reqs) { return huxley.ui.validator.validate(this.form,reqs); }</code>
 */
(function() {
    var _k = huxley;
    if (!_k.ui) {
        _k.ui = new Object();
    }
    _k.ui.validator = new Object();
    var _v = _k.ui.validator;
    
    _v.ERROR_CLASS = 'hux_form_error';

    _v._findElement = function(form, name) {
        if (!form) {
            return null;
        }
        var fl = form.length;
        var el;
        for (var i=0;i<fl;i++) {
            el = form.elements[i];
            if (el.name == name) {
                return el;
            }
        }
        return null;
    }

    _v._markFormError = function(form, msg, error_class) {
        var p = form.parentNode;
        var doc = document;
        var lists = p.getElementsByTagName('ul');
        var list = null;
        if (lists.length != null) {
            for (var i=0;i<lists.length;i++) {
                if (lists[i].className == error_class) {
                    list = lists[i];
                    break;
                }
            }
        }
        if (!list) {
          list = doc.createElement('ul');
          list.className = error_class;
        }
        var li = doc.createElement('li');
        list.appendChild(li);
        var txt = doc.createTextNode(msg);
        li.appendChild(txt);
        li.className = error_class;
        p.insertBefore(list,form);
    }

    _v._markErrorElement = function(el, msg, error_class) {
        var p = el.parentNode;
        var doc = document;
        var lists = p.getElementsByTagName('ul');
        var list = null;
        if (lists.length != 0) {
            for (var i=0;i<lists.length;i++) {
                if (lists[i].className == error_class) {
                    list = lists[i];
                    break;
                }
            }
        }
        if (!list) {
          list = doc.createElement('ul');
          list.className = error_class;
        }
        var li = doc.createElement('li');
        list.appendChild(li);
        var txt = doc.createTextNode(msg);
        li.appendChild(txt);
        li.className = error_class;
        p.insertBefore(list,el);
    };

    _v._scrubSiblingElements = function(el) {
        var p = el.parentNode;
        var i=0;
        var sib;
        while (i<p.childNodes.length) {
            sib = p.childNodes[i];
            if (sib != el) {
                p.removeChild(sib);
            }
            i++;
        }
    };

    _v._scrubErrorElement = function(el, error_class) {
        var ec = error_class || this.ERROR_CLASS;
        var p = el.parentNode;
        var i=0;
        var sib;
        while (i<p.childNodes.length) {
            sib = p.childNodes[i];
            if (sib.className == ec && sib != el) {
                p.removeChild(sib);
            }
            else {
                i++;
            }
        }
    }

    _v.scrubErrorElements = function(form, error_class) {
        if (!form) {
            return;
        }
        var ec = error_class || this.ERROR_CLASS;
        var fl = form.length;
        for (var i=0;i<fl;i++) {
            this._scrubErrorElement(form.elements[i],ec);
        }
        this._scrubErrorElement(form, ec);
    };

    _v.isInt = function(v) {
        return !isNaN(v) && parseInt(v) == v;
    };

    _v._boolConstsTrue = ['true', '1', 'yes'];
    _v._boolConstsFalse = ['false', '0', 'no'];

    _v.isBool = function(v) {
        return _k.inArray(v, this._boolConstsTrue) || _k.inArray(v, this._boolConstsFalse);
    };

    _v.isFloat = function(v) {
        alert("BUILDME: huxley.ui.validator.isFloat");
        // return parseFloat(mixed_var * 1) != parseInt(mixed_var * 1);
    };

    _v._validateText = function(field, req, response, debug, error_class) {
        if (!field || !req) {
            return false;
        }
        var value = field.value;
        var valid = true;
        var regex;
        switch (req.requirement) {
        case 'non-null':
            valid = value != '';
            break;
        case 'min-length':
            valid = value.length >= req.param1;
            break;
        case 'max-length':
            valid = value.length <= req.param1;
            break;
        case 'bool':
            valid = this.isBool(value);
            break;
        case 'int':
            valid = value == '' ? true : this.isInt(value);
            break;
        case 'min-int':
            valid = this.isInt(value);
            if (valid) {
                valid = parseInt(value) >= req.param1;
            }
            break;
        case 'max-int':
            valid = this.isInt(value);
            if (valid) {
                valid = parseInt(value) <= req.param1;
            }
            break;
        case 'alpha-num-sub':
            regex = /^[0-9A-Za-z_]+$/;
            valid = regex.test(value);
            break;
        default:
            if (debug) {
                alert("[WARNING] Validator skipping unknown or unsupported requirement \"" + req.requirement + "\" on field \"" + field.name + "\"");
            }
            break;
        }
        if (!valid) {
            switch (response) {
            case 'alert':
                alert(req.message);
                break;
            case 'mark':
                this._markErrorElement(field, req.message, error_class);
                break;
            default:
                break;
            }
        }
        return valid;
    };

    _v._validateSelect = function(field, req, response, debug, error_class) {
        if (!field || !req) {
            return false;
        }
        var opt = field.options[field.selectedIndex];
        var value = opt.value;
        var valid = true;
        var regex;
        switch (req.requirement) {
        case 'non-null':
            valid = this.isInt(value) ? parseInt(value) != 0 : value != '';
            break;
        default:
            if (debug) {
                alert("[WARNING] Validator skipping unknown or unsupported requirement \"" + req.requirement + "\" on field \"" + field.name + "\"");
            }
            break;
        }
        if (!valid) {
            switch (response) {
            case 'alert':
                alert(req.message);
                break;
            case 'mark':
                this._markErrorElement(field, req.message, error_class);
                break;
            default:
                break;
            }
        }
        return valid;
    };
    
    _v.validate = function(form, reqs, opt) {
        // parse options
        var response = 'alert';
        var error_action = 'continue';
        var onerror = null;
        var onbeforevalidate = null;
        var debug = false;
        var error_class = this.ERROR_CLASS;
        var skipfields = new Array();
        if (opt) {
            if (opt.debug) {
                debug = opt.debug;
            }
            if (opt.error_class) {
                error_class = opt.error_class;
            }
            if (opt.response) {
                response = opt.response;
            }
            if (opt.error_action) {
                error_action = opt.error_action;
            }
            if (opt.onerror) {
                onerror = opt.onerror;
            }
            if (opt.onbeforevalidate) {
                onbeforevalidate = opt.onbeforevalidate;
            }
        }
        if (!form) {
            if (debug) {
                alert("[WARNING] Validator called with invalid form reference.");
            }
            return false;
        }
        // pre-validate callback
        if (onbeforevalidate) {
            onbeforevalidate(form);
        }
        // field requirements come first
        var idx, l, req, rtype, field, fieldresult;
        var error_count = 0;
        for (idx in reqs) {
            req = reqs[idx];
            rtype = req.type;
            if (rtype != 'field') {
                continue;
            }
            if (_k.inArray(req.target, skipfields)) {
                continue;
            }
            field = this._findElement(form,req.target);
            if (!field) {
                if (debug) {
                    alert('[WARNING] Validator called for non-existing field "' + req.target + '"');
                }
                continue;
            }
            switch (field.nodeName) {
            case 'INPUT':
                switch (field.type) {
                case 'text':
                case 'password':
                case 'hidden':
                    fieldresult = this._validateText(field,req,response,debug,error_class);
                    break;
                default:
                    if (debug) {
                        alert('[WARNING] Validator skipping non-supported field type "' + field.type + '"');
                    }
                    continue;
                }
                break;
            case 'SELECT':
                fieldresult = this._validateSelect(field,req,response,debug,error_class);
                break;
            default:
                if (debug) {
                    alert('[WARNING] Validator skipping non-supported field node ' +  field.nodeName + '"');
                }
                continue;
            }
            if (!fieldresult) {
                error_count++;
                if (onerror && response == 'callback') {
                    onerror(field,req.type,req.message);
                }
                if (error_action == 'abort') {
                    return false;
                }
                if (error_action == 'abort-field') {
                    skipfields[skipfields.length] = req.target;
                }
            }
        }
        // second loop for form requirements
        for (idx=0,l=reqs.length;idx<l;idx++) {
            req = reqs[idx];
            rtype = req.type;
            if (rtype != 'form') {
                continue;
            }
            switch (req.requirement) {
            case "n-in-m":
                fieldresult = this._validateNinM(form, req,response,debug,error_class);
                break;
            case "equality":
                fieldresult = this._validateEquality(form, req, response, debug, error_class);
                break;
            default:
                if (debug) {
                    alert('[WARNING] Validator skipping non-supported form requirement "' + req.requirement + '"');
                }
                continue;
            }
            if (!fieldresult) {
                error_count++;
                switch (response) {
                case 'alert':
                    alert(req.message);
                    break;
                case 'mark':
                    this._markFormError(form, req.message, error_class);
                    break;
                default:
                    break;
                }
                if (onerror && response == 'callback') {
                    onerror(req);
                }
                if (error_action == 'abort') {
                    return false;
                }
            }
        }
        if (error_count > 0 && debug) {
            alert("Validator encountered " + error_count + " errors.");
        }

        return error_count == 0;
    }
    
    _v._validateEquality = function(form, requirement, response, debug, error_class) {
        var fields = requirement.fields;
        var valid = false;
        var test = "";
        var field = null;
        for (var i=0, l=fields.length;i<l;i++) {
            field = form[fields[i]];
            if (i == 0) {
                test = field.value;
            }
            else {
                valid = test == field.value;
                if (!valid) {
                    break;
                }
            }
        }
        if (!valid && !requirement.message) {
            requirement.message = "At least one of these fields does not match the others: " + huxley.formatStringArray(fields);
        }
        return valid;
    }

    _v._validateNinM = function(form, requirement, response, debug, error_class) {
        var n = requirement.n;
        var fct = 0;
        for (var i=0, l=requirement.fields.length;i<l;i++) {
            var field = form[requirement.fields[i]];
            if (field.value != "") {
                fct++;
            }
        }
        var valid = fct >= n;
        if (!valid && !requirement.message) {
            requirement.message = "Please set at least " + n + " of the fields " + huxley.formatStringArray(requirement.fields);
        }
        return valid;
    }
})();

/*
 * File: huxJumploader.js
 * Copyright: (c) 2010 kalbeck.media
 * Author: Klaus Drobec
 *
 * Event handler functions for Jumploader Java upload applet JS API.
 * These have to be part of the global Javascript object in order to be found
 *
 *
 */
(function() {
    var _hux = huxley;
    if (!_hux.ui) {
        alert("[ERROR] Jumploader support module requires huxley.ui to be included first.");
    }
    var _ui = _hux.ui;
    if (_ui.JL) {
        return;
    }
    _ui.JL = new Object();
    var _jl = _ui.JL;
    
    _jl.cbsUploadDone = [];
    _jl.cbsFileDone = [];
    _jl.cbsFileFailed = [];
    
    _jl.onUploadDone = function(uploader) {
        for (var i=0, l=this.cbsUploadDone.length;i<l;i++) {
           this.cbsUploadDone[i](uploader);
        }
    }

    _jl.onFileDone = function(uploader, file) {
        for (var i=0, l=this.cbsFileDone.length;i<l;i++) {
           this.cbsFileDone[i](uploader, file);
        }
    }
    
    _jl.onFileFailed = function(uploader, file) {
        for (var i=0, l=this.cbsFileFailed.length;i<l;i++) {
           this.cbsFileFailed[i](uploader, file);
        }
    }
    
    _jl.addCallbackUploadDone = function(f) {
        this.cbsUploadDone[this.cbsUploadDone.length] = f;
    }

    _jl.clearCallbacksUploadDone = function() {this.cbsUploadDone = [];}

    _jl.clearCallbacksFileDone = function() {this.cbsFileDone = [];}

    _jl.clearCallbacksFileFailed = function() {this.cbsFileFailed = [];}

    _jl.addCallbackFileDone = function(f) {
        this.cbsFileDone[this.cbsFileDone.length] = f;
    }
    
    _jl.addCallbackFileFailed = function(f) {
        this.cbsFileFailed[this.cbsFileFailed.length] = f;
    }

    _jl.getAttributeValue = function(uploader, name, default_value) {
        var attrSet = uploader.getAttributeSet();
        var attr = attrSet.getAttributeByName(name);
        return attr ? attr.getStringValue() : default_value;
    }

    _jl.clearFinished = function() {
        var uploader = document.jumpLoaderApplet.getUploader();
        // STATUS_READY = 0
        var files = uploader.getAllFiles();
        for (var i=0,l=files.length;i<l;i++) {
            if (files[i].isFinished()) {
                uploader.removeFile(files[i]);
            }
        }
    }

    _jl.clearAll = function() {
        var uploader = document.jumpLoaderApplet.getUploader();
        // STATUS_READY = 0
        var files = uploader.getAllFiles();
        for (var i=0,l=files.length;i<l;i++) {
            uploader.removeFile(files[i]);
        }
    }

})();

function appletInitialized(uploader,file) {
//	alert("Applet initialized.\nTarget module is: " + huxley.ui._target_module_url +  "\nLast module was: " +  huxley.ui._last_module_url);
//    var ul = document.jumpLoaderApplet.getUploader();
//	ul.addFile("D:/Games/BI3_CD1/AVI/API035.AVI");
}

function uploaderStatusChanged(uploader) {
  if (uploader.isReady() && uploader.getFileCountByStatus(3) == 0) {
    // huxley.ui.AssetManager1.dlgAddJava.hide();
    huxley.ui.JL.onUploadDone(uploader);
  }
}

function uploaderFileStatusChanged(uploader, file) {
    if (file.isFailed()) {
        huxley.ui.JL.onFileFailed(uploader,file);
    }
    else if (file.isFinished()) {
        huxley.ui.JL.onFileDone(uploader,file);
    }
}

/**
 * add attribute to uploader
 */
 function createUploaderAttribute(name,value,transmit) {
//     alert('creating uploader attribute name = ' +  name + ", value = " +  value);
     var sval = "" + value;
     var uploader = document.jumpLoaderApplet.getUploader();
     var attrSet = uploader.getAttributeSet();
     var attr = attrSet.getAttributeByName(name);
     if (!attr) {
        attr = attrSet.createStringAttribute(name,sval);
//          attr = attrSet.createAttribute(name,value);
     }
     else {
         attr.setStringValue(sval);
//        attr.setValue(value);
     }
     attr = attrSet.getAttributeByName(name);
//     alert('set attribute: ' + attr.getStringValue());
     attr.setSendToServer(transmit);
 }

 function removeUploaderAttribute(name) {
     var uploader = document.jumpLoaderApplet.getUploader();
     var attrSet = uploader.getAttributeSet();
     var attr = attrSet.getAttributeByName(name);
     if (attr) {
        attrSet.removeAttribute(attr);
     }
 }
 /******************************************************************************
 ********** image preview dialog
 ******************************************************************************/
(function() {
    var _hux = huxley;
    _hux.imagePopup = {};
    var _ip = _hux.imagePopup;
    _ip.dlg = null;
    _ip.setup = {
        width: "40em"
        ,modal: false
        ,labels: {
            close: "Close"
        }
    };
    
    _ip.cleanup = function() {
        if (this.dlg) { delete this.dlg; this.dlg = null; }
    }
    
    _ip.assertDialog = function() {
        if (this.dlg) {
            return true;
        }
        // build the host markup
        var dom = YAHOO.util.Dom;
        var s = this.setup;
        var host = document.createElement('div');
        var hd = document.createElement('div');
        dom.addClass(hd,"hd");
        var bd = document.createElement('div');
        dom.addClass(hd,"bd");
        host.appendChild(hd);
        host.appendChild(bd);
        dom.setStyle(host,'display','none');
        document.body.appendChild(host);
        // build the dialog
        this.dlg = new YAHOO.widget.Dialog(host,{
            width: s.width,fixedcenter: true,visible: false,constraintoviewport: true,hideaftersubmit: true ,postmethod: "manual",modal: s.modal
           ,buttons : [{text: s.labels.close, handler: function () {this.cancel();}, isDefault:true}]
        });
        this.dlg.render();
        return true;
    }
    
    _ip.preExecute = function(setup) {
        if (setup) {
            this.cleanup();
            this.setup = setup;
        }
        this.assertDialog();
    }
    
    _ip.executeForAsset = function(asset_id, setup) {
        this.preExecute(setup);
        this.dlg.setBody(huxley.ui.getAssetHTML(asset_id));
        this.dlg.show();
    }
    
})();    
 /******************************************************************************
 ********** Kaidoo tools
 ******************************************************************************/

(function() {
    var _hux = huxley;
    _hux.kaidoo = {};
    var _k = _hux.kaidoo;
    _k.perform_resize = true;
    
    _k.hasFlash = function(min_major, min_minor, min_release) {
        if (!swfobject) {
            alert("huxley.kaidoo requires swfobject to work.");
            return false;
        }
        var fpv = swfobject.getFlashPlayerVersion();
        if (!fpv) {
            return false;
        }
        var req_major = min_major || 0;
        var req_minor = min_minor || 0;
        var req_release = min_release || 0;
        if (fpv.major < req_major) {
            return false;
        }
        if (fpv.minor < min_minor) {
            return false;
        }
        if (fpv.release < min_release) {
            return false;
        }
        return true;
    }
    
    _k.hasFlashByString = function(version_string) {
        if (!swfobject) {
            alert("huxley.kaidoo requires swfobject to work.");
            return false;
        }
        return swfobject.hasFlashPlayerVersion(version_string);
    }
        
    _k.isHashURL = function() {
        return huxley.urlparts.hash != '' && huxley.urlparts.pathname == '/';
    }
    
    _k.getLanguageCodeFromHostname = function() {
        var hn = document.location.hostname;
        if (hn == huxley.appcfg.hostname_en) {return "en";}
        if (hn == huxley.appcfg.hostname_de) {return "de";}
        if (hn == huxley.appcfg.hostname_es) {return "es";}
        return "en";
    }
    
    _k.redirectToHash = function() {
        // ?? l10ns ==
//        var need_index = ["forsale","forrent","magazine","maps"];
        var lcs = ["en","de","es"];
        var pn = huxley.urlparts.pathname;
        var i,l,hash;
        var pnparts = pn.split('/');
        var cleanparts = [];
        // clean the path parts
        for (i=0,l=pnparts.length;i<l;i++) {
            if (pnparts[i] != '') {
                cleanparts[cleanparts.length] = pnparts[i];
            }
        }
        // empty pathname
        if (cleanparts.length == 0) {
            hash = '#/' + this.getLanguageCodeFromHostname() + '/index';
        }
        else {
            // get language code from urlet or hostname
            var lc = huxley.inArray(cleanparts[0],lcs) ? cleanparts.shift() : this.getLanguageCodeFromHostname();
            // build new #-pathname and handle missing /index cases            
            switch (cleanparts.length) {
            case 0:
                hash = '#/' + lc + '/index';
                break;
            case 1:
                if (cleanparts[0] != 'index') {
                    hash = '#/' + lc + "/" + cleanparts[0] + "/index";
                }
                else {
                    hash = '#/' + lc + "/" + cleanparts[0];
                }
                break;
            default:
                hash = '#/' + lc;
                for (i=0,l=cleanparts.length;i<l;i++) {
                    hash += '/' + cleanparts[i];
                }
                break;
            }   
        }
//        alert("About to forward: \"" + hash + "\"");
        document.location.href = huxley.appcfg.url_base + hash;
    };
    
    _k.redirectToNonHash = function() {
        var hash = document.location.hash;
//        alert('redirecting to non-hash: hash = ' + hash);
        if (hash != '#' && hash != '') {
            document.location.href = huxley.appcfg.url_base + '/' + hash.substr(2);
        }
    };
    
    _k.isIndex = function() {
        var up = huxley.urlparts;
//        alert('kaidoo::isIndex: pathname = ' + up.pathname);
        if (up.pathname == '/'  || up.pathname == '') {
            return true;
        }
        return false;
    };
    
    _k.onWindowResize = function() {
        if (!huxley.kaidoo.perform_resize) {
            return;
        }
        var dom = YAHOO.util.Dom;
        var base_w = 1024, base_h = 616;
        var t_w, t_h;
        var act_vp = huxley.getViewport();
        var act_w = act_vp.width;
        var act_h = act_vp.height;
        var o_w = dom.getAttribute('kaidooDiv','width');
        var o_h = dom.getAttribute('kaidooDiv','height');
        if (act_w < 1420 || act_h < 770) {
            t_w = base_w;
            t_h = base_h;
        }
        else {
            if (act_w >= 2048) { act_w = 2048; } 
            if (act_h >= 1272) { act_h = 1272; }
            var f_w = act_w / base_w;
            t_w = act_w;
            t_h = base_h * f_w;
            if (t_h > (act_h - 40)) {
                t_h = (act_h - 40);
                t_w = base_w * (t_h / base_h);
            }
        }
        dom.setAttribute('kaidooDiv','width',t_w);
        dom.setAttribute('kaidooDiv','height',t_h);
        dom.setStyle('container','margin-left','-' + Math.floor(t_w / 2) + 'px');
        dom.setStyle('container','margin-top','-' + Math.floor(t_h / 2) + 'px');
    };
    
})();

/******************************************************************************
 ********** Profiling tools
 ******************************************************************************/

(function() {
    var _hux = huxley;
    _hux.profiler = {};
    var _p = _hux.profiler;
    _p.xhr_urls = null;
    _p.xhr_delay = 100;
    _p.xhr_runs = 100;
    _p.current_xhr_run = 0;
    _p.xhr_callback = null;
    
    _p.runXHRSeries = function(setup) {
        var p = huxley.profiler;
        p.xhr_urls = setup.urls;
        p.xhr_delay = setup.delay || 100;
        p.xhr_runs = setup.runs || 100;
        p.xhr_callback = setup.callback;
        p.current_xhr_run = 0;
        p.offsetXHRRun();
    }
    
    _p.offsetXHRRun = function() {
        var p = huxley.profiler;
        p.xhr_callback.log('waiting ' + p.xhr_delay + ' ms');
        setTimeout("huxley.profiler.executeXHRRun()",huxley.profiler.xhr_delay);
    }
    
    _p.executeXHRRun = function() {
        var p = huxley.profiler;
        var url = YAHOO.lang.isArray(p.xhr_urls) ? p.xhr_urls[p.current_xhr_run] : _p.xhr_urls;
        p.xhr_callback.log('starting xhr run #' + p.current_xhr_run + ' of ' + p.xhr_runs);
        YAHOO.util.Connect.asyncRequest("GET",url,{
            success: function (o) {
                var p = huxley.profiler;
                p.current_xhr_run++;
//                p.xhr_callback.success(o);
                if (p.current_xhr_run < p.xhr_runs) {
                    p.offsetXHRRun();
                }
                else {
                    p.xhr_callback.complete(o);
                }
            },
            failure: function (o) {
                var p = huxley.profiler;
                p.current_xhr_run++;
                p.xhr_callback.failure(o);
            }
        })
    }
    
})();
