<!doctype html>
<html>
    <head>
        <title>Database Tables Sheet</title>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    </head>
    
    <style>
    /* 
    Eric Meyer's CSS Reset
    http://meyerweb.com/eric/tools/css/reset/
    v1.0 | 20080212
    CSSresetr.com
    */
    html, body, div, span, applet, object, iframe,
    h1, h2, h3, h4, h5, h6, p, blockquote, pre,
    a, abbr, acronym, address, big, cite, code,
    del, dfn, em, font, img, ins, kbd, q, s, samp,
    small, strike, strong, sub, sup, tt, var,
    b, u, i, center,
    dl, dt, dd, ol, ul, li,
    fieldset, form, label, legend,
    table, caption, tbody, tfoot, thead, tr, th, td {
    	margin: 0;
    	padding: 0;
    	border: 0;
    	outline: 0;
    	font-size: 100%;
    	vertical-align: baseline;
    	background: transparent;
    }
    body {
    	line-height: 1;
    }
    ol, ul {
    	list-style: none;
    }
    blockquote, q {
    	quotes: none;
    }
    blockquote:before, blockquote:after,
    q:before, q:after {
    	content: '';
    	content: none;
    }
    
    /* remember to define focus styles! */
    :focus {
    	outline: 0;
    }
    
    /* remember to highlight inserts somehow! */
    ins {
    	text-decoration: none;
    }
    del {
    	text-decoration: line-through;
    }
    
    /* tables still need 'cellspacing="0"' in the markup */
    table {
    	border-collapse: collapse;
    	border-spacing: 0;
    }
    #footer {clear:both;width:100%;border-top:1px solid #ccc;padding-top:20px;padding-bottom:20px;background:#dfdfdf;}
       #footer p{text-align:center;font-size:12px;}
    
    
    </style>
	<style>
[class^="icon-"], [class*=" icon-"] {
  display: inline-block;
  width: 14px;
  height: 14px;
  line-height: 14px;
  vertical-align: text-top;
  background-image:url("data:image/png;base64, ");
  background-position: 14px 14px;
  background-repeat: no-repeat;
  *margin-right: .3em;
  font-size:0;
}

[class^="icon-"]:last-child, [class*=" icon-"]:last-child {
  *margin-left: 0;
}

.icon-ok {
  background-position: -288px 0;
}

.icon-tag {
  background-position: 0 -48px;
}

.icon-share {
  background-position: -120px -72px;
}

.icon-star {
  background-position: -120px 0;
}

.icon-list-alt {
  background-position: -264px -24px;
}
   
#content{padding-left:340px;padding-right:20px;margin-top:74px;width:auto;font-family:arial;color:#333;margin-bottom:100px}
table {border-bottom:1px solid #ccc;border-right:1px solid #ccc;font-size:12px;width:100%;}
th {background-color:#eee;color:#888;}
td, th {padding:8px;border-top:1px solid #ccc;border-left:1px solid #ccc}
#header {position:fixed;width:100%;top:0px;background-color:#e7eef8;border-bottom:4px solid #000;height:66px;}
h1{font-size:30px;text-align:center;margin:20px;}
h2{margin:20px 0px;border-bottom:3px solid #ccc;background-color:#08C;padding:10px;font-size:14px;color:#fff}
h2 .inapp{font-size:10px;float:right;color:#ccc}
h2 .inapp a {color:#ccc}
ul.menu{position:fixed;left:0px;top:74px;width:320px;overflow-y:auto;font-size:12px;}
ul.menu a{text-decoration:none;vertical-align: top;}
ul.menu a:hover{text-decoration:underline;}
li.sec {padding:8px;background-color:#eee}
li.sec span{padding:8px;background-color:#08C;display:block;color:white;font-size:12px}
li.item {margin-left:2px;padding:3px;}
a{color:#444;text-decoration:underline}
a:hover{color:#08C;text-decoration:underline}
a.star{color:red;text-decoration:none;cursor:pointer;font-size:10px;background-color:red;padding-left:3px;color:#fff;display:inline-block;width:9px;height:12px;border-radius:100% 100%;}
a.star:hover{color:#08C;text-decoration:none}

tr.key{font-weight:bold}
td.ref{cursor:pointer}
.comment{font-size:12px;color:#666}
.comment li {margin-left:10px;padding:2px 2px;}
#tips{position:absolute;z-index:10001;display:none;}
#tips_content{text-align:left;padding:3px;line-height:18px;color:#000;font-size:12px;border:1px solid #999;background:Khaki;}

    </style>
    <script>
        var $ = function(name){ return document.getElementById(name) };
        var tips = { 
            opts : {
                id : 'tips',
                cls : 'a',
                cid : 'tips_content',
                tpl : '<div id="tips_content"></div>',
                txt : 'test'
            },
            show : function (el) {
                this.opts.txt = $(el).children[0].innerHTML;
                var o = document.getElementById(this.opts.id)||'';
                if (!o) {
                    o = document.createElement('DIV');
                    o.setAttribute("id", this.opts.id);
                    o.className=this.opts.cls;
                    o.innerHTML=this.opts.tpl;
                    document.body.appendChild(o);
                }
                document.getElementById(this.opts.cid).innerHTML = this.opts.txt;
                var cw = Math.max(document.body.clientWidth, document.documentElement.clientWidth);
                var st = Math.max(document.body.scrollTop, document.documentElement.scrollTop);
                var evt = window.event;
                o.style.display = "block";
                o.style.left = (evt.clientX + o.offsetWidth + 20 > cw) ? (evt.clientX - o.offsetWidth - 20) + "px" : (evt.clientX + 20) + "px";
                o.style.top = (evt.clientY + document.body.scrollTop + o.clientHeight + 20 > 580) ? (evt.clientY - o.clientHeight + 50 + document.body.scrollTop) + "px" : (evt.clientY + 20 + st) + "px";
                o=cw=st=null;
            },
            hide : function () {
                document.getElementById(this.opts.id)&&(document.getElementById(this.opts.id).style.display = 'none');
            }
        };
        var getElementsByClassName = function (className, tag, elm){
        	if (document.getElementsByClassName) {
        		getElementsByClassName = function (className, tag, elm) {
        			elm = elm || document;
        			var elements = elm.getElementsByClassName(className),
        				nodeName = (tag)? new RegExp("\\b" + tag + "\\b", "i") : null,
        				returnElements = [],
        				current;
        			for(var i=0, il=elements.length; i<il; i+=1){
        				current = elements[i];
        				if(!nodeName || nodeName.test(current.nodeName)) {
        					returnElements.push(current);
        				}
        			}
        			return returnElements;
        		};
        	}
        	else if (document.evaluate) {
        		getElementsByClassName = function (className, tag, elm) {
        			tag = tag || "*";
        			elm = elm || document;
        			var classes = className.split(" "),
        				classesToCheck = "",
        				xhtmlNamespace = "http://www.w3.org/1999/xhtml",
        				namespaceResolver = (document.documentElement.namespaceURI === xhtmlNamespace)? xhtmlNamespace : null,
        				returnElements = [],
        				elements,
        				node;
        			for(var j=0, jl=classes.length; j<jl; j+=1){
        				classesToCheck += "[contains(concat(' ', @class, ' '), ' " + classes[j] + " ')]";
        			}
        			try	{
        				elements = document.evaluate(".//" + tag + classesToCheck, elm, namespaceResolver, 0, null);
        			}
        			catch (e) {
        				elements = document.evaluate(".//" + tag + classesToCheck, elm, null, 0, null);
        			}
        			while ((node = elements.iterateNext())) {
        				returnElements.push(node);
        			}
        			return returnElements;
        		};
        	}
        	else {
        		getElementsByClassName = function (className, tag, elm) {
        			tag = tag || "*";
        			elm = elm || document;
        			var classes = className.split(" "),
        				classesToCheck = [],
        				elements = (tag === "*" && elm.all)? elm.all : elm.getElementsByTagName(tag),
        				current,
        				returnElements = [],
        				match;
        			for(var k=0, kl=classes.length; k<kl; k+=1){
        				classesToCheck.push(new RegExp("(^|\\s)" + classes[k] + "(\\s|$)"));
        			}
        			for(var l=0, ll=elements.length; l<ll; l+=1){
        				current = elements[l];
        				match = false;
        				for(var m=0, ml=classesToCheck.length; m<ml; m+=1){
        					match = classesToCheck[m].test(current.className);
        					if (!match) {
        						break;
        					}
        				}
        				if (match) {
        					returnElements.push(current);
        				}
        			}
        			return returnElements;
        		};
        	}
        	return getElementsByClassName(className, tag, elm);
        };
        function viewport()
        {
        var e = window
        , a = 'inner';
        if ( !( 'innerWidth' in window ) )
        {
        a = 'client';
        e = document.documentElement || document.body;
        }
        return { width : e[ a+'Width' ] , height : e[ a+'Height' ] }
        }
        
    </script>
<body>
  <div id="header">
    <h1>Database Tables Sheet</h1>
  </div>

  <ul class='menu'>
  {{ for menu in sorted(menus):}}
        <li class="sec">
        <span id="{{=menu['name']}}">{{=menu['name']}}</span>
        <ul class="items">
        {{ for item in menu['items']:}}
            <li class='item'><i class="icon-list-alt"></i>&nbsp;<a href="#tt-{{=item['name']}}" title="{{=item['label']}}">{{=item['name']}}</a></li>
            {{pass}}
        </ul>
        </li>
        {{pass}}
  </ul>
  <div id="content">
  
  {{ for table in tables: }}
      <a name="tt-{{= table['name']}}"></a>
      <h2 id="h-{{= table['name']}}">{{= table['label'] }} 
        {{if table['appname']:}}
            <span class="inapp"> <a href="#app-{{= table['appname'] }}">{{= table['appname'] }}</a> </span> 
        {{else:}} &nbsp; {{pass}}
      </h2>
      <div id="tb-{{= table['name']}}">
          <table cellpadding="0" cellspacing="0"> 
          <tr>
              <th>P</th>
              <th>Display</th>
              <th>Fieldname</th>
              <th>Data Type</th>
              <th>Can be Null</th>
              <th>Relation</th>
          </tr>
          {{ for field in sorted(table['fields'], key=lambda x:(not x['primary_key'], x['name'])): }}
             <tr class="{{if field['primary_key']:}}key{{pass}}">
                <td>{{if field['primary_key']:}} <i class="icon-tag" title="Yes">Y</i>  {{else:}} &nbsp; {{pass}}</td>
                <td>{{= field['label']}} {{if field['star']:}} <a class="star" href="#comment-{{= table['name']}}-{{= field['name']}}" onmousemove="tips.show('comment-{{= table['name']}}-{{= field['name']}}')" onmouseout="tips.hide()">{{=field['star']}}</a> {{pass}}</td>
                <td>{{= field['name']}}</td>
                <td>{{= field['type']}}</td>
                <td>{{if field['nullable']:}}<i class="icon-ok" title="True">True</i>  {{else:}} &nbsp; {{pass}}</td>
                {{if field['reftable']:}}
                    <td class="ref"><a href="#tt-{{= field['reftable']}}"><i class="icon-share"></i> {{= field['reftable']}}</a></td>
                {{else:}} <td>&nbsp;</td> {{pass}}
             </tr>
          {{ pass }}
        </table>
		<div class="comment">
		  <ul>
		  {{ if table['choices'] : }} Description:<br/> {{pass}}
          {{ for comment in table['choices']: }}
			<li id="comment-{{= table['name']}}-{{=comment['fieldname']}}">{{=comment['index']}}.{{=comment['fieldlabel']}}:
            <span>
			{{ for i, value in comment['list']: }}
			    ({{=repr(i)}},{{=value}}) 
			{{ pass }}
            </span>
			</li>
          {{ pass }}
		  </ul>
		</div>
    </div>  
    {{ pass }}
  </div>  
  <div id="footer">
    This documentation is generated by Uliweb.
  </div>
<script>
    var menu = getElementsByClassName('menu')[0];
    menu.style.height = (viewport().height - 78)+'px';
</script>
  </body>
</html>
