# Copyright 2002-2008 Josh Clark and Global Moxie, LLC. This code cannot be 
# redistributed without permission from globalmoxie.com.  For more
# information, consult your Big Medium license.
#
# $Id: DefaultTmpl.pm 3123 2008-06-17 14:23:33Z josh $

package BigMed::DefaultTmpl;
## BASIC DEFAULT HTML FOR WHEN MOXIEDATA LOCATION UNKNOWN

my ( $COMMON_HEAD, $COMMON_FOOTER, $COMMON_FIELDSET, $COMMON_FIELD );
my %TEMPLATE_MAP = (
    'shell_message.tmpl' => \&shell_message,
    'screen_start_generic.tmpl' => \&screen_start_generic,
    'screen_web_crash.tmpl' => \&screen_web_crash,
    'wi_prompt_input.tmpl' => \&wi_form_input,
    'wi_prompt_textarea.tmpl' => \&wi_form_textarea,
    'wi_prompt_radio_toggle.tmpl' => \&wi_form_radio_toggle,
    'wi_prompt_select.tmpl' => \&wi_form_select,
    'wi_ajax_status_ok.tmpl' => \&wi_ajax_status_ok,
    'wi_ajax_status_err.tmpl' => \&wi_ajax_status_err,
);

sub template {
    return $TEMPLATE_MAP{$_[0]} ? $TEMPLATE_MAP{$_[0]}->() : "<!-- UNKNOWN TEMPLATE $_[0] -->";
}


$COMMON_HEAD = <<'END_HEAD';
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<!-- START BigMed::DefaultTmpl, COMMON_HEAD -->
<head>
    <meta http-equiv="content-type" content="text/html; charset=utf-8" />
    <meta http-equiv="Pragma" content="no-cache" />
    <style type="text/css">
    /* <![CDATA[ */
        body {
            background-color: #fff;
        }
        
        * {
            padding:0;
            margin:0;
        }
        h2, h3, h4, p, ul, fieldset {
            margin:1em 0;
        }
        li { margin-left:5%; }
        fieldset { padding: .5em; }
        label, h4.bm_labelHead { margin: 0 2% 0 0 }
        option { padding-right: 1em; min-width:1.5em; } 
        table { margin:0 auto; }
    
        /*  FONT SETUP
        -------------------------------------------------------- */
        
        body, input, textarea, select {
            font-family: "Lucida Grande", Helvetica, Arial, sans-serif;
            color: #000;
        }
        
        a:link,
        a:visited {
            color: #000066;
        }        
        a:hover {
            color: #CC0000;
        }
        
        code, #bm_ErrorBox {
            font-family: monaco, "courier new", "courier", monospace;
        }        
        
        body,
        code,
        label,
        h4.bm_labelHead,
        input,
        textarea {
            font-size: x-small;
            voice-family: "\"}\""; voice-family: inherit;
            font-size: small;
        }
        html>body,
        html>body code,
        html>body label,
        html>body h4.bm_labelHead,
        html>body input,
        html>body textarea { font-size: small }
        
        #bm_CPfooter,
        div.fieldDescription,
        #bm_ErrorBox,
        a.bm_FieldSetHelpLink,
        .bm_FieldSetPost,
        .bm_ajaxStat {    
            font-size: xx-small;
            voice-family: "\"}\""; voice-family: inherit;
            font-size: x-small;
        }
        html>body #bm_CPfooter,
        html>body div.fieldDescription,
        html>body #bm_ErrorBox,
        html>body a.bm_FieldSetHelpLink,
        html>body .bm_FieldSetPost,
        html>body .bm_ajaxStat { font-size: x-small }
                
        .bmcpSubhead {
            font-size: small;
            voice-family: "\"}\""; voice-family: inherit;
            font-size: medium;
        }
        html>body .bmcpSubhead { font-size: medium }
        
        /* HEADINGS
        -------------------------------------------------------- */
        
        .bmcpSubhead { 
            font-style: normal;
            font-weight: bold;
            color: #003333;
        }
        
        ul#bmcp_SetupStatus {
            list-style-type: none;
            margin: 0 auto 0 0;
            width:19em;
            height:3.5em;
            float:right;
        }
        ul#bmcp_SetupStatus li {
            margin-left: .5em;
            text-align:center;
            display:block;
            float:left;
            width: 2em;
            border:1px solid #699;
            background-color: #deefef;
            font-size: 10px;
            height: 2em;
            color: #999;
            padding: .5em;
        }
        ul#bmcp_SetupStatus li.SetupStatusActive {
            background-color: #699;
            color: #fff;
        }
        ul#bmcp_SetupStatus li h3 {
            margin: 0;
            font-size: 14px;
        }

       /* 
        -----------------------------------------------------
        CONTENT BOX LAYOUT/DISPLAY */
        
        #CPbox {
            margin:1em 10% .5em 10%;
            border: 1px solid #699;
            background-color: #deefef;
        }
        
        #BasicBox {
            width:500px;
            margin:1em auto .5em auto;
            border: 1px solid #699;
            background-color: #deefef;
        }
        
        #bmhtmlWrap {
            padding: 5px;
        }
        
        div.fieldBox {
            padding: 5px;
            clear: both;
            margin-top: 5px;
        }
        
        #bm_CPfooter {
            text-align: center;
            margin-bottom: 20px;
        }
        
        /* -----------------------------------------------------
        MESSAGE BOXES
        -------------------------------------------------------- */
        
        .bm_alertBox,
        .bm_messageBox,
        .fieldStatus,
        .bmcp_error,
        .bm_FieldSetHelpBox,
        .bm_FieldSetPre,
        .bm_FieldSetPost {
            background-color:#deefef;
            background-position: top right;
            background-repeat:no-repeat;
            padding: 5px;
            margin-bottom: 1em;
            border: 1px solid #999;
            clear:both;
        }
        
        .bm_FieldSetHelpBox {
            background-color: #ffc;
        }
        
        .bm_FieldSetPre,
        .bm_FieldSetPost {
            border: 1px solid #699;
        }
        .bm_FieldSetPost {
            color: #666;
        }
        
        .fieldStatus,
        .bmcp_error {
            margin-bottom: 5px;
            background-color: #900;
            border-left-color: #600;
            border-bottom-color: #600;
            color: #fff;
        }
        .bmcp_error {
            border-color: #600;
        }
        
        /* for ajax updates and reports */
        div.bm_ajaxStat {
            color: #666;
            padding-top:.3em;
        }
        .bm_ajaxOK {
            color: #090;
        }
        .bm_ajaxNotOK {
            color: #c00;
        }
                
        /* for error/bug report messages on crash page only */
        div#bm_ErrorBox { 
            border: 1px solid #fff;
            background: #333;
            color: #0c0;
            padding: 5px;
            margin: 5px 0;
        }
        
        div#bm_AlertBox {
            position: absolute;
            top: 0px;
            z-index: 101;
            border-width: 5px;
            border-style: solid;
            width:450px;
            margin-left:50%;
            left:-225px;
        }
        
        /* PULLDOWN, BUTTON, FORM FORMATS
        ----------------------------------------------------- */
        
        fieldset {
            border: 1px solid #cddede;
            overflow: auto;
        }
        
        legend {
            border: 1px solid #9cc;
            padding: 4px;
            color: #477;
            font-weight:bold;
            background-color: #bdd;
        }
        
        div.bm_FieldEntry {
            clear:both;
            margin-bottom: 1em;
        }
        
        a.bm_FieldSetHelpLink {
            font-weight: normal;
            border-bottom: 1px solid #ccc;
            border-right: 1px solid #ccc;
            padding: .3em;
            padding-right: 0;
            background-color: #fff;
            width:25%;
            display:block;
            margin-bottom: .5em;
        }
        a.bm_FieldSetHelpLink:hover {
            background-color: #ffc;
        }

        label, div.fieldDescription, h4.bm_labelHead {
            font-weight: bold;
            color: #666;
            display:block;
            float:left;
            clear:left;
            text-align:right;
            width:25%;
        }
        
        div.fieldDescription {
            margin-right: 2%;
            padding-top: 4px;
            margin-bottom: 1em;
            font-weight: normal;
        }
        
        label.labelHighlight {
            color: #000;
        }
        
        input, textarea {
            font-style: normal;
            width: 68%;
            border: 1px solid #999;
            background-color: #dee;
            padding: 3px;
            color: #000;
        }
        
        textarea {
            line-height:130%;
        }
        
        select {
            font-style: normal;
            border: 1px solid #999;
            background-color: #fff;
            color: #000;
        }
        
        input.inFocus,
        textarea.inFocus,
        select.inFocus {
            background-color: #ffc;
            border-color: #033;
        }

        /* radio tab/toggle styles */
        div.bm_tab_set {
            overflow:auto;
            width:68%; /* ie will not observe overflow without the width set */
            border-bottom:1px solid #999;
        }
        
        label.bm_radio_tab {
            clear:right; /* clear:none more accurate, but older safaris need help */
            width:115px;
            float:left;
            text-align: left;
            border:1px solid #999;
            border-bottom: none;
            margin-right:2px;
            padding:3px;
        }
        
        label.bm_radio_tab_select {
            background-color: #bdd;
            color: #000;
            border-color: #000;
        }
        label.bm_radio_tab input,
        .bmcpChecklist input {
            width:auto;
            float:none;
            border: none;
            background-color: transparent;
            padding: 0;
        }

        /*
        -----------------------------------------------------
        BUTTONS AND BUTTON LINKS
        */
        
        input.bm_Submit,
        .bm_ButtonLink,
        .bm_ButtonLink:visited {
            display:block;
            text-align: center;
            border: 1px outset #033;
            clear:both;
            color: #033;
            padding: 4px;
            font-weight: bold;
            background-color: #fff;
            text-decoration:none;
            cursor:pointer;
        }
        
        input.bm_Submit {
            width: auto;
            margin: 1em 0 1em auto;
        }
        
        .bm_ButtonLink {
            margin:5px;
        
        }
        
        input.bm_Submit:hover,
        a.bm_ButtonLink:hover {
            color: #c00;
            background-color: #ffc;
        }
        
        input.bm_Submit:active,
        a.bm_ButtonLink:active {
            padding: 5px 3px 3px 5px;
            border-style: inset;
        }
        
        a.bm_CloseTrigger {
            width: 50px;
            float:right;
        }
        
        div.alertBoxError a.bm_CloseTrigger {
            background-color: #fcc;
        }
        div.alertBoxError a.bm_CloseTrigger:hover {
            background-color: #ffc;
        }

    /* ]]> */
    </style>
    <title><BM_LANG text="BM_Big_Medium_appname"> :: <TMPL_VAR NAME=BMCP_TITLE></title>
    <script type="text/javascript" language="javascript" charset="utf-8">
    // <![CDATA[

    function $(id) {
       if (typeof id == 'object') return id;
       var obj = document.getElementById ? document.getElementById(id)
               : document.all            ? document.all(id)
               :                           null;
       return obj;
    }


    var BM = new Object();
    BM.pathDiv = '/'; //default; may be overridden below
    BM.addLoadEvent = function(func) {
        var oldonload = window.onload;
        if (typeof window.onload != 'function') {
            window.onload = func;
        } else {
            window.onload = function() {
                oldonload();
                func();
            }
        }
    }
    
    BM.Menu = { init: function() {} }; //placeholder

    BM.Tree = function(element) {
        this.element = $(element);
        return this;
    }
    
    BM.Tree.prototype.findParentByClassName = function(tag) {
        if (!this.element || !tag) return;
        var parent = this.element.parentNode;
        if (!parent || parent.className.match(tag)) {
            return parent;
        }
        else {
            return new BM.Tree(parent).findParentByClassName(tag);
        }
    };

    BM.Behavior = {

        inputOnFocus : function(element) {
            var labelName = element.name + 'Label';
            var label = $(labelName);
            BM.FX.addClass(label,'labelHighlight');
            BM.FX.addClass(element,'inFocus');
        },

        inputOnBlur : function (element) {
            BM.Field.validate(element);
            var label = $(element.name + 'Label');
            BM.FX.removeClass(label,'labelHighlight');
            BM.FX.removeClass(element,'inFocus');
        }

    };

    
    BM.FX = {

        addClass : function(obj, newClass) {
            if ( !(obj = $(obj))) return;
            if (! obj.className.match(newClass)) {
                obj.className = obj.className + ' ' + newClass;
            }
        },

        removeClass : function(obj, oldClass) {
            if ( !(obj = $(obj))) return;
            var newClass = obj.className.replace(' ' + oldClass,'');
            newClass = newClass.replace(oldClass,'');
            obj.className = newClass;
        },

        reveal : function(obj) {
            if (! (obj = $(obj))) return;
            obj.style.display = '';
        },
        
        hide : function(obj) {
            if (! (obj = $(obj))) return;
            obj.style.display = 'none';
        },
    
        tintError : function(obj) {
            if (!obj) obj = 'bm_AlertBox';
            BM.FX.addClass(obj,'bmcp_error');
        },
        
        tintMsg : function(obj) {
            if (!obj) obj = 'bm_AlertBox';
            BM.FX.removeClass(id,'bmcp_error');
        },

        toggle : function(trigger, target) {
            if (  !(trigger = $(trigger)) || !(target = $(target)) ) return;
            if (trigger.className.match('bmTriggered')) {
                BM.FX.removeClass(trigger,'bmTriggered');
                BM.FX.hide(target);        
            }
            else {
                BM.FX.addClass(trigger,'bmTriggered');
                BM.FX.reveal(target);        
            }
        }

    };

    
    BM.Field = {
    
        focus : function(obj) {
            if ( !(obj = $(obj))) return;
            obj.focus();
            if (obj.select) obj.select();
        },
        
        validate : function(field,option) {
            if ( !(field = $(field)) || !BM.Valid.fieldInfo[field.name] ) return 1;
            if (typeof option != 'object') option = {};
            var type = BM.Valid.fieldInfo[field.name]['type'];
            var message;
            if (BM.Valid.fieldInfo[field.name].required && field.value == '') {
                message = BM.Valid.fieldInfo[field.name].name
                  + ': Please provide a value';
            }
            else if (type && BM.Valid.types[type] && field.value != '') {
                var regexp = BM.Valid.types[type]['regexp'];
                if (regexp) {
                    var checkMatch = new String(field.value);
                    if (checkMatch.match(regexp)) { //contains illegal value
                        message = BM.Valid.errorMsg(field.name);
                    }
                }
                else {
                    var do_function = BM.Valid.types[type]['function'];
                    if (do_function && do_function(field, option) == false) {
                        message = BM.Valid.errorMsg(field.name);
                    }
                }
            }
            if (message) {
                return BM.Field.showStatus(field,message,option);
            }
            BM.FX.hide(field.name + 'Status');
            return 1;
        },

        showStatus : function(field, message, option) {
            if ( !(field=$(field)) || !message ) return;
            if (typeof option != 'object ') option = {};
            var statusObj = $(field.name + 'Status');
            if (!statusObj && !option.noalert) {
                alert(message);
            }
            else {
                if (statusObj.innerHtml != message) statusObj.innerHTML = message;
                BM.FX.reveal(statusObj);
            }
            return message;
        }

    };

    
    BM.RadioTab = {
    
        init : function() {
            var allInput = document.getElementsByTagName('input');
            for (var i=0; i<allInput.length; i++) {
                if ( allInput[i].type == 'radio'
                  && allInput[i].checked
                  && allInput[i].className == 'bm_radio_tab' )
                {
                    BM.RadioTab.select(allInput[i]);
                }
            }
        },
        
        select : function(radio) {
            if ( !(radio = $(radio)) ) return;
            var seek = new BM.Tree(radio);
            var tabSet = seek.findParentByClassName('bm_tab_set');
            var allTabs = tabSet.getElementsByTagName('label');
            for (var i=0; i<allTabs.length; i++) {
                if (allTabs[i].htmlFor == radio.id) {
                    BM.FX.addClass(allTabs[i], 'bm_radio_tab_select');
                }
                else {
                    BM.FX.removeClass(allTabs[i], 'bm_radio_tab_select');
                }
            }
            var allFieldDivs = seek.findParentByClassName('bm_radio_tab_group').childNodes;
            for (var i=0; i<allFieldDivs.length; i++) {
                if (   allFieldDivs[i].className
                    && allFieldDivs[i].className.match('tabOpt') )
                {
                    if(allFieldDivs[i].id == radio.id + 'TogField') {
                        BM.FX.reveal(allFieldDivs[i]);
                    }
                    else {
                        BM.FX.hide(allFieldDivs[i]);
                    }
                }
            }
        }

    };

    
    BM.Ajax = {
    
        request : function(url, onchange, method) {
            var currentHost = document.location.protocol + '//' + document.location.host;
            if (url.indexOf(currentHost) != 0) return false;
            if (!method) method = 'GET';
            if (window.XMLHttpRequest) { //IE7, Moz, Safari etc use native obj
                var httpReq = new XMLHttpRequest();
            }
            else if (window.ActiveXObject){ //IE5 and IE6
                var httpReq = new ActiveXObject("Microsoft.XMLHTTP");
            }
            httpReq.open(method, url, true);
            httpReq.onreadystatechange = function(){ onchange(httpReq) };
            httpReq.send(null);
            return true;
        },
        
        clearStatus : function(statusObj) {
            if ( !(statusObj = $(statusObj)) ) return;
            statusObj.innerHTML = '&nbsp;';
        },
        
        inProgress : function(statusObj) {
            if ( !(statusObj = $(statusObj)) ) return;
            statusObj.innerHTML = 'Hang on...';
        },
        
        parseJSON : function(httpReq) {
            var ajaxJSON;
            try {
                eval(httpReq.responseText);
            }
            catch (e) {
                ajaxJSON = httpReq.responseText;
            }
            return ajaxJSON;
        },
        
       error : function(msg, statusObj, preamble) {
            if ( !msg || !(statusObj = $(statusObj))) return;
            if (typeof msg == 'object') { //httprequest
                //deal with safari weirdness
                msg = msg.statusText == 'OK' ? '' : ': ' + msg.statusText;
            }
            else {
                msg = ': ' + msg;
            }
            if (!preamble) preamble = 'Ran into some trouble';
            statusObj.innerHTML='<span class="bm_ajaxNotOK">' + preamble +  msg + '</span>'; 
        },

        confirmURL : function(url, statusObj) {
            if (!url || !(statusObj = $(statusObj))) return;
            var onchange = function(http) {
                if (http.readyState == 1) {
                    BM.Ajax.inProgress(statusObj);
                }
                else if (http.readyState == 4 && http.status == 200) {    
                    statusObj.innerHTML='<span class="bm_ajaxOK">'
                      + 'URL confirmed<' + '/span>';
                }
                else if (http.readyState == 4) {
                    BM.Ajax.error(
                      http, statusObj, 'Could not confirm expected file(s) at this URL'
                    );
                }
            };
            if ( !BM.Ajax.request( url, onchange, 'HEAD' ) ) {
                BM.Ajax.clearStatus(statusObj);
            }
            return true;
        },
        
        statusObj : function(field) {
            if ( !(field = $(field))) return;
            return $(field.id + 'AjaxStat');
        }
        
    };

    BM.Config = {

        confirmDir : function(dir, dirType, statusObj) {
            if (!dir) {
                BM.Ajax.clearStatus(statusObj);
                return false;
            }
            if (!dirType) dirType = '';
            if (!(statusObj = $(statusObj))) return;
            var url = document.location.href.replace(/(start\.cgi).*/, '$1');
            if ( !url.match(/bm\-start\.cgi$/) ) return false;
            url = url + BM.pathDiv + 'ajax-verify-dir?t=' + encodeURIComponent(dirType)
              + ';d=' + encodeURIComponent(dir);
            var handler = function(httpReq) {
                if (httpReq.readyState == 1) {
                    BM.Ajax.inProgress(statusObj);
                }
                else if (httpReq.readyState == 4 && httpReq.status == 200) {    
                    var ajaxJSON = BM.Ajax.parseJSON(httpReq);
                    if (ajaxJSON.error) {
                       BM.Ajax.error(ajaxJSON.error,statusObj);
                    }
                    else {
                      statusObj.innerHTML = ajaxJSON.html || ajaxJSON;
                    }
                }
                else if (httpReq.readyState == 4) {
                    BM.Ajax.clearStatus(statusObj); // look the other way
                }
            };
            if (! BM.Ajax.request(url, handler) ) {
                BM.Ajax.clearStatus(statusObj); //could not create request
            }
        }

    };
    
    
    BM.Alert = {
        display : function(html,option) {
            if (typeof option != 'object') option = {};
            var msgr = $('bm_AlertMessage');
            if (msgr) {
                msgr.innerHTML = html;
                if (option.isError) {
                    BM.FX.tintError();
                }
                else {
                    BM.FX.tintMsg();
                }
                BM.Alert.setAndReveal();
            }
            else {
                alert(html);
            }
        },

        setAndReveal : function(id) {
            if (!id) id = 'bm_AlertBox';
            var box = $(id);
            if (!box) return;
            var scrollY = 0;
            if (document.body && typeof document.body.scrollTop != "undefined") {
                scrollY += document.body.scrollTop;
                if (document.body.parentNode && typeof document.body.parentNode.scrollTop != "undefined") {
                    scrollY += document.body.parentNode.scrollTop;
                }
            }
            else if (typeof window.pageYOffset != "undefined") {
                scrollY += window.pageYOffset;
            }
            var screenHeight = 0;
            if (window.innerHeight) {
                screenHeight = window.innerHeight;
            }
            else if (document.compatMode && document.compatMode.indexOf("CSS1")) {
                //ie6; measure the html element's content height
                screenHeight = document.body.parentElement.clientHeight;
            }
            else if (document.body && document.body.clientHeight) {
                screenHeight = document.body.clientHeight
            }
            box.style.top = Math.round( (screenHeight/4) + scrollY) + 'px';
            BM.FX.reveal(box);
        }
    };

<TMPL_IF NAME=BMCP_JS_VALIDATION>
    BM.Valid = new Object();
    BM.Valid.fieldInfo = {
<TMPL_LOOP NAME=BMCP_JS_VALIDATION>
        '<TMPL_VAR NAME=FIELD_ID>' : {
            name: '<TMPL_VAR NAME=FIELD_LABEL>',
            required: '<TMPL_VAR NAME=FIELD_REQUIRED>',
            type: '<TMPL_VAR NAME=VALIDATE_TYPE>'
        }<TMPL_UNLESS NAME="__last__">,</TMPL_UNLESS>
</TMPL_LOOP>
    };

    BM.Valid.types = {
        'email': {
            'function': function(field){
                return BM.Valid.email(field)
            }
        },
        'simple_text': {
            'regexp': /[\n\r]/   //no line breaks
        },
        'username': {
            'regexp': /[\n\r]/   //no line breaks
        },
        'license' : {
            'regexp': /[^A-Za-z\d\-]/
        },
        'bmadmin_url' : {
            'function': function(fieldObj, option){
                option.suffix = 'txt';
                var mbin = document.getElementById('bigmedurl');
                if (mbin) {
                    var match = mbin.value.match(/^(https?:\/\/[^\/]+)/);
                    if (!match || fieldObj.value.indexOf(match[1]) != 0 ) {
                    return false;
                }
            }
                return BM.Valid.urlDir(fieldObj, option);
            }
        },
        'moxiebin_url' : {
            'function': function(fieldObj, option){
                option.suffix = 'cgi';
                return BM.Valid.urlDir(fieldObj, option);
            }
        },
        'dir_path' : {
            'function': function(fieldObj, option){
                return BM.Valid.dirPath(fieldObj, option);
            }
        },
        'moxiedata_path' : {
            'function': function(fieldObj, option){
                option.type = 'moxiedata';
                return BM.Valid.dirPath(fieldObj, option);
            }
        },
        'bmadmin_path' : {
            'function': function(fieldObj, option){
                option.type = 'bmadmin';
                return BM.Valid.dirPath(fieldObj, option);
            }
        }
    }
    
    BM.Valid.validateForm = function(form) {
        if (!BM.Valid.fieldInfo) return true;
        if (! (form = $(form))) return true;
        var all_msg = '';
        var inputs = form.getElementsByTagName('input');
        for (var i =0; i<inputs.length; i++) {
            var field = inputs[i];
            var result = BM.Field.validate(field, {noalert:1, submission:1});
            if (result != 1) { //it's an error message
                all_msg = all_msg + '<li>' + result + '<' + '/li>\n';
            }
        }
        if (all_msg) {
            BM.Alert.display(
              "We ran into a problem with your entry: \n<ul>" + all_msg
                + '<' + '/ul>',  {isError: 1}
            );
            return false;
        }
        return true;
    }
    
    
    BM.Valid.text = {
        'bmadmin_path' : 'This is not a valid directory path. The path should '
          + 'not contain any funky characters and must be the "absolute" path '
          + 'from the server\'s root directory. The format should look something '
          + 'like this:<br />For unix-based servers: /path/to/directory<br />'
          + 'For Windows servers: E:\path\to\directory',
        'bmadmin_url' : 'This URL is not properly formatted. It must use '
          + 'the same domain name as the moxiebin URL, and it has to start '
          + 'with http:// or https:// and include a correctly formatted domain '
          + 'name or IP address:<br />http://www.example.com/bmadmin',
        'dir_path' : 'This is not a valid directory path. The path should '
          + 'not contain any funky characters and must be the "absolute" path '
          + 'from the server\'s root directory. The format should look something '
          + 'like this:<br />For unix-based servers: /path/to/directory<br />'
          + 'For Windows servers: E:\path\to\directory',
        'dir_url' : 'This URL is not properly formatted. It has to start '
          + 'with http:// or https:// and include a correctly formatted domain '
          + 'name or IP address:<br />http://www.example.com/bmadmin',
        'email' : 'Incorrect format for an e-mail address',
        'html_path' : 'This is not a valid directory path. The path should '
          + 'not contain any funky characters and must be the "absolute" path '
          + 'from the server\'s root directory. The format should look something '
          + 'like this:<br />For unix-based servers: /path/to/directory<br />'
          + 'For Windows servers: E:\path\to\directory',
        'license' : 'Should consist only of letters, numbers and hyphens.',
        'moxiebin_url' : 'This URL is not properly formatted. It has to start '
          + 'with http:// or https:// and include a correctly formatted domain '
          + 'name or IP address:<br />http://www.example.com/bmadmin',
        'moxiedata_path' : 'This is not a valid directory path. The path should '
          + 'not contain any funky characters and must be the "absolute" path '
          + 'from the server\'s root directory. The format should look something '
          + 'like this:<br />For unix-based servers: /path/to/directory<br />'
          + 'For Windows servers: E:\path\to\directory',
        'simple_text' : 'This field may not contain line breaks.'
    };
    
    BM.Valid.errorMsg = function(fieldName) {
        var type = BM.Valid.fieldInfo[fieldName].type;
        var message =  BM.Valid.text[type] || 'Invalid value for this field.';
        message = BM.Valid.fieldInfo[fieldName].name + ": " + message;
        return message;
    }


    BM.Valid.urlDir = function (field, option) {
        if ( !(field = $(field)) ) return;
        if (typeof option != 'object') option = {};
        var url = BM.Scrub.url(field.value, {http: 1});
        if (!url) return false;
        url = url.replace(/^(.+?)[\\\/]+$/, '$1'); //trailing slashes
        field.value = url;
        if (!option.submission) {
            if (!option.suffix) option.suffix = 'txt';
            BM.Ajax.confirmURL(
              url + '/ping.' + option.suffix, BM.Ajax.statusObj(field)
            );
        }
        return true;
    }

    BM.Valid.dirPath = function(field, option) {
        if ( !(field = $(field)) ) return;
        if (typeof option != 'object') option = {};
        var dir = BM.Scrub.dir(field.value);
        if (!dir) return false;
        field.value = dir;
        if (!option.submission) {
            BM.Config.confirmDir( dir, option.type, BM.Ajax.statusObj(field) );
        }
        return true;
    }

    BM.Valid.email = function(field) {
        // based on an email-checking script by Sandeep V. Tamhankar
        var email = field.value;
        var checkTLD=1; // check top-level domains or not?
        var knownDomsPat=/^(com|net|org|edu|int|mil|gov|arpa|biz|aero|name|coop|info|pro|museum)$/;
        
        var emailPat=/^(.+)@(.+)$/;
        // don't allow  ( ) < > @ , ; : \ " . [ ] */ or space
        var specialChars="\\(\\)><@,;:\\\\\\\"\\.\\[\\]";
        var validChars="\[^\\s" + specialChars + "\]";
        
        // if user is a quoted string, no limitations on chars in user name
        var quotedUser="(\"[^\"]*\")";
        
        var ipDomainPat=/^\[(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})\]$/;
        var atom=validChars + '+';
        var word="(" + atom + "|" + quotedUser + ")";
        var userPat=new RegExp("^" + word + "(\\." + word + ")*$");
        var domainPat=new RegExp("^" + atom + "(\\." + atom +")*$");
        
        //start testing address
        var matchArray=email.match(emailPat);
        if (matchArray==null) {
            return false;
        }
        var user=matchArray[1];
        var domain=matchArray[2];
        for (i=0; i<user.length; i++) {
            if (user.charCodeAt(i)>127) {
                return false;
            }
        }
        for (i=0; i<domain.length; i++) {
            if (domain.charCodeAt(i)>127) {
                return false;
           }
        }
        if (user.match(userPat)==null) {
            return false;
        }
        var IPArray=domain.match(ipDomainPat);
        if (IPArray!=null) {
            for (var i=1;i<=4;i++) {
                if (IPArray[i]>255) {
                    return false;
                }
            }
            return true;
        }
        var atomPat=new RegExp("^" + atom + "$");
        var domArr=domain.split(".");
        var len=domArr.length;
        for (i=0;i<len;i++) {
            if (domArr[i].search(atomPat)==-1) {
                return false;
            }
        }
        if (checkTLD && domArr[domArr.length-1].length!=2 && 
        domArr[domArr.length-1].search(knownDomsPat)==-1) {
            return false;
        }
        if (len<2) {
            return false;
        }
        return true;
    }

    BM.Scrub = {
   
        url : function(url, option) {
            if (!url) return url;
            if (typeof option != 'object') option = {};
            url = url.replace(/^\s+/, '');
            url = url.replace(/\s+$/, '');
            if (option.http) {
                var IPv4address  = '([0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+)';
                var toplabel     = '([a-zA-Z][-a-zA-Z0-9]*[a-zA-Z0-9]|[a-zA-Z])';
                var domainlabel  = '(([-a-zA-Z0-9][-a-zA-Z0-9]*)?[-a-zA-Z0-9])';
                var hostName     = '((' + domainlabel + '\\.)*' + toplabel + '\\.?)';
                var host         = '(' + IPv4address + '|' + hostName + ')';
                var hostProtocol = new RegExp('^https?:\\/\\/' + host); 
                if (!url.match(hostProtocol)) return false;
            }
            return url;
        },
        
        dir : function(dir) {
            if (dir == null) dir = '';
            dir = dir.replace(/^\s+/, '');
            dir = dir.replace(/\s+$/, '');
            
            // eliminate non-leading double slashes (UNC can start with \\)
            dir = dir.replace(/([^\\\/])([\\\/]){2,}/g,'$1$2');
            dir = dir.replace(/^(.+?)[\\\/]+$/, '$1'); // trailing slash
            if (dir.match(/\.\./)
              || !dir.match(/^[^\|;<>\`\*\(\)\[\]\{\}\$\n\r]+$/)
              || !dir.match(/^(([a-zA-Z]:[\\\/])|\/|\\\\)/) ) {
                return false;
            }
            return dir;
        }

    };
</TMPL_IF>
<TMPL_VAR NAME=BMCP_JS_CUSTOM>        
<TMPL_IF NAME=BMCP_JS_ONLOAD>
        BM.addLoadEvent( function () {
<TMPL_VAR NAME=BMCP_JS_ONLOAD>        
        } );
</TMPL_IF>
    // ]]>
    </script>
    <meta name="generator" content="<TMPL_VAR NAME=BIGMEDIUM> <TMPL_VAR NAME=BMVERSION>" />
    <TMPL_VAR NAME=HEAD_CUSTOM_HTML>
</head>
<body>
<div id="bm_AlertBox" style="display:none" class="bm_alertBox">
    <a href="#" class="bm_CloseTrigger bm_ButtonLink" onclick="BM.FX.hide(this.parentNode);return false;"><BM_LANG text="BM_Close"></a>
    <div id="bm_AlertMessage" class="bm_alertMessage"></div>
</div>
<!-- END BigMed::DefaultTmpl, COMMON_HEAD -->
END_HEAD

$COMMON_FOOTER = <<'END_FOOTER';
<!-- START BigMed::DefaultTmpl, COMMON_FOOTER -->
<div id="bm_CPfooter">
    <BM_LANG text="BM_Big_Medium_appname"> <TMPL_VAR NAME=BMCP_BMVERSION>.
    Copyright &copy; 2002-<TMPL_VAR NAME=BMCP_YEAR>,
    <a href="http://globalmoxie.com/">Global Moxie, LLC</a>.
    <BM_LANG text="All rights reserved.">
</div>
</body>
</html>
<!-- END BigMed::DefaultTmpl, COMMON_FOOTER -->
END_FOOTER


$COMMON_FIELD = <<'END_FIELD';
<!-- START BigMed::DefaultTmpl, COMMON_FIELD -->
    <div class="bm_FieldEntry"<TMPL_IF NAME=FIELD_CONTAINER_ID>
      id="<TMPL_VAR NAME=FIELD_CONTAINER_ID>"</TMPL_IF><TMPL_IF NAME=FIELD_HIDDEN>
      style="display:none"</TMPL_IF>>

    <TMPL_IF NAME=SHOW_STATUS>
        <div <TMPL_IF NAME=FIELD_ID>id="<TMPL_VAR NAME=FIELD_ID>Status"</TMPL_IF>
          class="fieldStatus"
    <TMPL_IF NAME=FIELD_STATUS>      ><TMPL_VAR NAME=FIELD_STATUS>
    <TMPL_ELSE>      style="display:none">
    </TMPL_IF>
        </div>
    </TMPL_IF>

    <TMPL_IF NAME=SHOW_LABEL>
        <TMPL_IF NAME=LABEL_AS_HEAD>
          <h4 class="bm_labelHead" <TMPL_IF NAME=FIELD_ID>id="<TMPL_VAR NAME=FIELD_ID>Label"</TMPL_IF>>
            <TMPL_VAR NAME=FIELD_LABEL>
          </h4></TMPL_IF>
        <TMPL_UNLESS NAME=LABEL_AS_HEAD>
        <label <TMPL_IF NAME=FIELD_ID>id="<TMPL_VAR NAME=FIELD_ID>Label" for="<TMPL_VAR NAME=FIELD_ID>"</TMPL_IF> >
            <TMPL_VAR NAME=FIELD_LABEL>
        </label></TMPL_UNLESS>

        <TMPL_IF NAME=DESCRIPTION>
        <div class="fieldDescription"><TMPL_VAR NAME=DESCRIPTION></div>
        </TMPL_IF>
    </TMPL_IF>

        <TMPL_VAR NAME=FIELD_HTML>

        <TMPL_IF NAME=FIELD_AJAX_STATUS>
        <div id="<TMPL_VAR NAME=FIELD_ID>AjaxStat" class="bm_ajaxStat">&nbsp;</div>   
        </TMPL_IF>
    </div>
<!-- END BigMed::DefaultTmpl, COMMON_FIELD -->
END_FIELD

$COMMON_FIELDSET = <<"END_FIELDSET";
<!-- START BigMed::DefaultTmpl, COMMON_FIELDSET -->
<fieldset <TMPL_IF NAME=FIELDSET_ID>id="<TMPL_VAR NAME=FIELDSET_ID>" </TMPL_IF>
<TMPL_IF NAME=FIELDSET_CLASS>  class="<TMPL_VAR NAME=FIELDSET_CLASS>"</TMPL_IF>
>

<TMPL_IF NAME=FIELDSET_TITLE>
<legend<TMPL_IF NAME=FIELDSET_AKEY> accesskey="<TMPL_VAR NAME=FIELDSET_AKEY>"</TMPL_IF>>
    <TMPL_VAR NAME=FIELDSET_TITLE>
</legend>
</TMPL_IF>

<TMPL_IF NAME=FIELDSET_PRE_HTML>
    <div class="bm_FieldSetPre"><TMPL_VAR NAME=FIELDSET_PRE_HTML></div>
</TMPL_IF>

<TMPL_IF NAME=FIELDSET_HELP>
    <a href="#" class="bm_FieldSetHelpLink"
      onclick="BM.FX.toggle(this, '<TMPL_VAR NAME=FIELDSET_ID>HelpBox');return false"><BM_LANG text="Help!"></a>
    <div id="<TMPL_VAR NAME=FIELDSET_ID>HelpBox" class="bm_FieldSetHelpBox"
      style="display:none">
        <div class="bm_FieldSetHelpText">
        <TMPL_VAR NAME=FIELDSET_HELP>
        </div>
    </div>
</TMPL_IF>

<TMPL_LOOP NAME=FIELDSET_FIELDS>
$COMMON_FIELD
</TMPL_LOOP>

<TMPL_IF NAME=FIELDSET_POST_HTML>
    <div class="bm_FieldSetPost"><TMPL_VAR NAME=FIELDSET_POST_HTML></div>
</TMPL_IF>

</fieldset>
<!-- END BigMed::DefaultTmpl, COMMON_FIELDSET -->
END_FIELDSET

sub shell_message {
    return <<"END_MESSAGE";
$COMMON_HEAD
<div id="BasicBox"><div id="bmhtmlWrap">
<div class="fieldBox"><span class="bmcpSubhead">

<TMPL_VAR NAME=BMCP_TITLE>

</span></div>
<div class="fieldBox">

<TMPL_VAR NAME=MESSAGE>

</div>
</div>
</div>
$COMMON_FOOTER
END_MESSAGE
}

sub screen_start_generic {
    return <<"END_CONFIG_BMSETUP";
$COMMON_HEAD
<div id="CPbox"><div id="bmhtmlWrap">

<div class="fieldBox">
    <TMPL_IF NAME="SHOW_STEPS">
    <ul id="bmcp_SetupStatus">
        <li<TMPL_IF NAME="STEP1"> class="SetupStatusActive"</TMPL_IF>><h3>1</h3>
        </li>
        <li<TMPL_IF NAME="STEP2"> class="SetupStatusActive"</TMPL_IF>><h3>2</h3>
        </li>
        <li<TMPL_IF NAME="STEP3"> class="SetupStatusActive"</TMPL_IF>><h3>3</h3>
        </li>
        <li<TMPL_IF NAME="STEP4"> class="SetupStatusActive"</TMPL_IF>><h3>4</h3>
        </li>
        <li<TMPL_IF NAME="STEP5"> class="SetupStatusActive"</TMPL_IF>><h3>5</h3>
        </li>
        <li<TMPL_IF NAME="STEP6"> class="SetupStatusActive"</TMPL_IF>><h3>6</h3>
        </li>
    </ul>
    </TMPL_IF>

    <h2 class="bmcpSubhead"><TMPL_VAR NAME=BMCP_TITLE></h2>
</div>
<div class="fieldBox">

<TMPL_IF NAME=MESSAGE>
<div id="bm_MainMessage" class="bm_messageBox">
    <TMPL_VAR NAME=MESSAGE>
</div>
</TMPL_IF>

    <form action="<TMPL_VAR NAME=FORM_URL>" method="post" enctype="multipart/form-data" accept-charset="utf-8" onsubmit="return BM.Valid.validateForm(this);">

<TMPL_LOOP NAME=FIELDSETS>
$COMMON_FIELDSET
</TMPL_LOOP>

    </form>
</div>
</div>
</div>
$COMMON_FOOTER
END_CONFIG_BMSETUP
}

sub screen_web_crash {
    return <<"END_WEB_CRASH";
$COMMON_HEAD
<div id="BasicBox"><div id="bmhtmlWrap">
<div class="fieldBox"><span class="bmcpSubhead">

<TMPL_VAR NAME=BMCP_TITLE>

</span></div>
<div class="fieldBox">
    <div class="bm_messageBox">
        <h2 class="bmcpSubhead">
            <BM_LANG text="WEB_CRASH_Please tell us about this problem">
        </h2>
        
        <p>
            <BM_LANG text="WEB_CRASH_Big Medium ran into an unexpected problem">
        </p>
        <p>
            <BM_LANG text="WEB_CRASH_Please take a moment to send an error report">
        </p>
        
        <p>
            <a href="#" id="bm_ErrorShow" onclick="BM.FX.toggle(this, 'bm_ErrorBox');return false"><BM_LANG text="WEB_CRASH_Show the error report"></a>
        </p>
        <div id="bm_ErrorBox" style="display:none">
            <div id="bm_ErrorMessage">
                <TMPL_VAR NAME=ERROR_HTML>
            </div>
        </div>
    </div>
    
    <form action="http://globalmoxie.com/error_report" method="post" enctype="multipart/form-data" accept-charset="utf-8">

        <TMPL_LOOP NAME=FIELDSETS>
$COMMON_FIELDSET
        </TMPL_LOOP>

    </form>
</div>
</div>
</div>
$COMMON_FOOTER
END_WEB_CRASH
}

sub wi_form_input {
    return <<'FORM_INPUT';
<!-- START BigMed::DefaultTmpl, WI_FORM_INPUT -->
    <input type="<TMPL_VAR NAME=INPUT_TYPE>" <TMPL_IF NAME=FIELD_ID>id="<TMPL_VAR NAME=FIELD_ID>" name="<TMPL_VAR NAME=FIELD_ID>"</TMPL_IF>
<TMPL_IF NAME=FIELD_CLASS>     class="<TMPL_VAR NAME=FIELD_CLASS>"</TMPL_IF>
      value="<TMPL_VAR NAME=FIELD_VALUE>"
      onfocus="BM.Behavior.inputOnFocus(this)" onblur="BM.Behavior.inputOnBlur(this)" />
<!-- END BigMed::DefaultTmpl, WI_FORM_INPUT -->
FORM_INPUT
}

sub wi_form_textarea {
    return <<'END_TEXTAREA';
<!-- START BigMed::DefaultTmpl, WI_FORM_TEXTAREA -->
    <textarea rows="5" cols="30" <TMPL_IF NAME=FIELD_ID>id="<TMPL_VAR NAME=FIELD_ID>" name="<TMPL_VAR NAME=FIELD_ID>"</TMPL_IF>
<TMPL_IF NAME=FIELD_CLASS>     class="<TMPL_VAR NAME=FIELD_CLASS>"</TMPL_IF>
      onfocus="BM.Behavior.inputOnFocus(this)" onblur="BM.Behavior.inputOnBlur(this)"><TMPL_VAR NAME=FIELD_VALUE></textarea>
<!-- END BigMed::DefaultTmpl, WI_FORM_TEXTAREA -->
END_TEXTAREA
}

sub wi_form_radio_toggle {
    return <<"END_RADIOTOGGLE";
<!-- START BigMed::DefaultTmpl, wi_form_radio_toggle -->
<div class="bm_radio_tab_group<TMPL_IF NAME=GROUP_CLASS> <TMPL_VAR NAME=GROUP_CLASS></TMPL_IF>">
    <div class="bm_tab_set"><TMPL_LOOP NAME=TABS>
        <label for="<TMPL_VAR NAME=FIELD_ID>" class="bm_radio_tab">
            <input type="radio" name="<TMPL_VAR NAME=FIELD_NAME>" id="<TMPL_VAR NAME=FIELD_ID>"
              value="<TMPL_VAR NAME=FIELD_VALUE>" class="bm_radio_tab"
              <TMPL_IF NAME=FIELD_CHECKED>checked="checked"</TMPL_IF>
              onclick="BM.RadioTab.select(this);" />
            <TMPL_VAR NAME=FIELD_LABEL>
        </label>
    </TMPL_LOOP></div>

<TMPL_LOOP NAME=FIELD_DIVS>
    <div class="tabOpt" id="<TMPL_VAR NAME=DIV_ID>"
         style="display:<TMPL_VAR NAME=DISPLAY_STATE>">
<TMPL_LOOP NAME=FIELDS>$COMMON_FIELD</TMPL_LOOP>
    </div>
</TMPL_LOOP>
</div>
<!-- END BigMed::DefaultTmpl, wi_form_radio_toggle -->
END_RADIOTOGGLE
}

sub wi_form_select {
    return <<'END_SELECT';
<!-- START BigMed::DefaultTmpl, wi_form_select -->
    <select <TMPL_IF NAME=FIELD_ID>id="<TMPL_VAR NAME=FIELD_ID>" name="<TMPL_VAR NAME=FIELD_ID>"</TMPL_IF><TMPL_IF NAME=FIELD_CLASS>
      class="<TMPL_VAR NAME=FIELD_CLASS>"</TMPL_IF>
      onfocus="BM.Behavior.inputOnFocus(this)" onblur="BM.Behavior.inputOnBlur(this)">
<TMPL_LOOP NAME=FIELD_OPTIONS>
        <option value="<TMPL_VAR NAME="OPTION">"<TMPL_IF NAME=SELECTED> selected="selected"</TMPL_IF>>
            <TMPL_VAR NAME="LABEL">
        </option>
</TMPL_LOOP>
    </select>
<!-- END BigMed::DefaultTmpl, wi_form_select -->
END_SELECT
}

sub wi_ajax_status_ok {
    return <<'AJAX_OK';
<!-- START BigMed::DefaultTmpl, wi_ajax_status_ok -->
<span class="bm_ajaxOK"><TMPL_VAR NAME="STATUS"></span>
<!-- END BigMed::DefaultTmpl, wi_ajax_status_ok -->
AJAX_OK
}

sub wi_ajax_status_err {
    return <<'AJAX_OK';
<!-- START BigMed::DefaultTmpl, wi_ajax_status_err -->
<span class="bm_ajaxNotOK"><TMPL_VAR NAME="STATUS"></span>
<!-- END BigMed::DefaultTmpl, wi_ajax_status_err -->
AJAX_OK
}
1;