Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame^] | 1 | {% load projecttags %} |
| 2 | <!-- component to display a generic table --> |
| 3 | <script> |
| 4 | |
| 5 | // |
| 6 | // most of the following javascript is for managing the 'Edit Columns' |
| 7 | // pop-up dialog and actions. the idea is that there are 2 types |
| 8 | // of actions: immediate - performed while the dialog is still |
| 9 | // visible - hide/show columns, and delayed - performed when the |
| 10 | // dialog becomes invisible - any resorting if necessary. |
| 11 | // |
| 12 | // When the dialog is open, an interval timer is set up to |
| 13 | // determine if the dialog is still visible. when the dialog |
| 14 | // closes - goes invisible, the delayed actions are performed. |
| 15 | // |
| 16 | // the interval timer and interrupt handler is a way of simulating |
| 17 | // an onclose event. there is probably a simpler way to do this |
| 18 | // however the pop-up window id was elusive. |
| 19 | // |
| 20 | |
| 21 | var editColTimer; |
| 22 | var editColAction; |
| 23 | |
| 24 | // |
| 25 | // this is the target function of the interval timeout. |
| 26 | // check to see if the dialog is visible. if the dialog |
| 27 | // has gone invisible since the last check, take any delayed |
| 28 | // actions indicated in the action list and clear the timer. |
| 29 | // |
| 30 | |
| 31 | function checkVisible( ) { |
| 32 | editcol = document.getElementById( 'editcol' ); |
| 33 | if ( editcol.offsetWidth <= 0 ) { |
| 34 | clearInterval( editColTimer ); |
| 35 | editColTimer = false; |
| 36 | hideshowColumns( ); |
| 37 | editColAction = [ ]; |
| 38 | } |
| 39 | } |
| 40 | |
| 41 | function filterTableRows(test) { |
| 42 | if (test.length > 0) { |
| 43 | var r = test.split(/[ ,]+/).map(function (e) { return new RegExp(e, 'i') }); |
| 44 | $('tr.data').map( function (i, el) { |
| 45 | (! r.map(function (j) { return j.test($(el).html())}).reduce(function (c, p) { return c && p;} )) ? $(el).hide() : $(el).show(); |
| 46 | }); |
| 47 | } else |
| 48 | { |
| 49 | $('tr.data').show(); |
| 50 | } |
| 51 | } |
| 52 | |
| 53 | // |
| 54 | // determine the value of the indicated url arg. |
| 55 | // this is needed to determine whether a resort |
| 56 | // is necessary. it looks like a lot of gorp stuff |
| 57 | // but its actually pretty simple. |
| 58 | // |
| 59 | |
| 60 | function getURLParameter( name ) { |
| 61 | return decodeURIComponent((new RegExp('[?|&]' + name + '=' + |
| 62 | '([^&;]+?)(&|#|;|$)').exec(location.search)||[,""])[1].replace(/\+/g, |
| 63 | '%20'))||null |
| 64 | } |
| 65 | |
| 66 | // |
| 67 | // when the dialog box goes invisible |
| 68 | // this function is called to interpret |
| 69 | // the action list and take any delayed actions necessary. |
| 70 | // the editColAction list is a hash table with |
| 71 | // the column name as the hash key, the hash value |
| 72 | // is a 2 element list. the first element is a flag |
| 73 | // indicating whether the column is on or off. the |
| 74 | // 2nd element is the sort order indicator for the column. |
| 75 | // |
| 76 | |
| 77 | function hideshowColumns( ) { |
| 78 | for( var k in editColAction ) { |
| 79 | showhideDelayedTableAction( k, editColAction[ k ][ 0 ], editColAction[ k ][ 1 ]); |
| 80 | } |
| 81 | } |
| 82 | |
| 83 | // |
| 84 | // this function actually performs the delayed table actions |
| 85 | // namely any resorting if necessary |
| 86 | // |
| 87 | |
| 88 | function showhideDelayedTableAction( clname, sh, orderkey ) { |
| 89 | if ( !sh ) { |
| 90 | p = getURLParameter( "orderby" ).split( ":" )[ 0 ]; |
| 91 | if ( p == orderkey ) { |
| 92 | reload_params({ 'orderby' : '{{default_orderby}}'}); |
| 93 | } |
| 94 | } |
| 95 | } |
| 96 | |
| 97 | // |
| 98 | // this function actually performs the immediate table actions |
| 99 | // namely any colums that need to be hidden/shown |
| 100 | // |
| 101 | |
| 102 | function showhideImmediateTableAction( clname, sh, orderkey ) { |
| 103 | if ( sh ) { |
| 104 | $( '.' + clname ).show( 100 ); |
| 105 | } |
| 106 | else { |
| 107 | $( '.' + clname ).hide( 100 ); |
| 108 | } |
| 109 | |
| 110 | // save cookie for all checkboxes |
| 111 | save = ''; |
| 112 | $( '.chbxtoggle' ).each(function( ) { |
| 113 | if ( $( this ).attr( 'id' ) != undefined ) { |
| 114 | save += ';' + $( this ).attr( 'id' ) +':'+ $( this ).is( ':checked' ) |
| 115 | } |
| 116 | }); |
| 117 | $.cookie( '_displaycols_{{objectname}}', save ); |
| 118 | save = ''; |
| 119 | } |
| 120 | |
| 121 | // |
| 122 | // this is the onclick handler for all of the check box |
| 123 | // items in edit columns dialog |
| 124 | // |
| 125 | |
| 126 | function showhideTableColumn( clname, sh, orderkey ) { |
| 127 | editcol = document.getElementById( 'editcol' ); |
| 128 | if ( editcol.offsetWidth <= 0 ) { |
| 129 | |
| 130 | // |
| 131 | // this path is taken when the page is first |
| 132 | // getting initialized - no dialog visible, |
| 133 | // perform both the immediate and delayed actions |
| 134 | // |
| 135 | |
| 136 | showhideImmediateTableAction( clname, sh, orderkey ); |
| 137 | showhideDelayedTableAction( clname, sh, orderkey ); |
| 138 | return; |
| 139 | } |
| 140 | if ( !editColTimer ) { |
| 141 | |
| 142 | // |
| 143 | // we don't have a timer active so set one up |
| 144 | // and clear the action list |
| 145 | // |
| 146 | |
| 147 | editColTimer = setInterval( checkVisible, 250 ); |
| 148 | editColAction = [ ]; |
| 149 | } |
| 150 | |
| 151 | // |
| 152 | // save the action to be taken when the dialog closes |
| 153 | // |
| 154 | |
| 155 | editColAction[ clname ] = [ sh, orderkey ]; |
| 156 | showhideImmediateTableAction( clname, sh, orderkey ); |
| 157 | } |
| 158 | |
| 159 | </script> |
| 160 | |
| 161 | <!-- control header --> |
| 162 | <div class="navbar"> |
| 163 | <div class="navbar-inner"> |
| 164 | <form class="navbar-search input-append pull-left" id="searchform"> |
| 165 | <input class="input-xxlarge" id="search" name="search" type="text" placeholder="Search {%if object_search_display %}{{object_search_display}}{%else%}{{objectname}}{%endif%}" value="{%if request.GET.search %}{{request.GET.search}}{% endif %}"/>{% if request.GET.search %}<a href="javascript:$('#search').val('');searchform.submit()" class="add-on btn" tabindex="-1"><i class="icon-remove"></i></a>{%endif%} |
| 166 | <input type="hidden" name="orderby" value="{{request.GET.orderby}}"> |
| 167 | <input type="hidden" name="page" value="1"> |
| 168 | <button class="btn" id="search-button" type="submit" value="Search">Search</button> |
| 169 | </form> |
| 170 | <div class="pull-right"> |
| 171 | {% if tablecols %} |
| 172 | <div class="btn-group"> |
| 173 | <button id="edit-columns-button" class="btn dropdown-toggle" data-toggle="dropdown">Edit columns |
| 174 | <span class="caret"></span> |
| 175 | </button> |
| 176 | <!-- |
| 177 | {{tablecols|sortcols}} |
| 178 | --> |
| 179 | <ul id='editcol' class="dropdown-menu"> |
| 180 | {% for i in tablecols|sortcols %} |
| 181 | <li> |
| 182 | <label {% if not i.clclass %} class="checkbox muted" {%else%} class="checkbox" {%endif%}> |
| 183 | <input type="checkbox" class="chbxtoggle" |
| 184 | {% if i.clclass %} |
| 185 | id="{{i.clclass}}" |
| 186 | value="ct{{i.name}}" |
| 187 | {% if not i.hidden %} |
| 188 | checked="checked" |
| 189 | {%endif%} |
| 190 | onclick="showhideTableColumn( |
| 191 | $(this).attr('id'), |
| 192 | $(this).is(':checked'), |
| 193 | {% if i.ordericon %} |
| 194 | '{{i.orderkey}}' |
| 195 | {% else %} |
| 196 | undefined |
| 197 | {% endif %} |
| 198 | )" |
| 199 | {%else%} |
| 200 | checked disabled |
| 201 | {% endif %}/> {{i.name}} |
| 202 | </label> |
| 203 | </li> |
| 204 | {% endfor %} |
| 205 | </ul> |
| 206 | </div> |
| 207 | {% endif %} |
| 208 | <div style="display:inline"> |
| 209 | <span class="divider-vertical"></span> |
| 210 | <span class="help-inline" style="padding-top:5px;">Show rows:</span> |
| 211 | <select style="margin-top:5px;margin-bottom:0px;" class="pagesize"> |
| 212 | {% with "10 25 50 100 150" as list%} |
| 213 | {% for i in list.split %} |
| 214 | <option value="{{i}}">{{i}}</option> |
| 215 | {% endfor %} |
| 216 | {% endwith %} |
| 217 | </select> |
| 218 | </div> |
| 219 | </div> |
| 220 | </div> <!-- navbar-inner --> |
| 221 | </div> |
| 222 | |
| 223 | <!-- the actual rows of the table --> |
| 224 | <table class="table table-bordered table-hover tablesorter" id="otable"> |
| 225 | <thead> |
| 226 | <!-- Table header row; generated from "tablecols" entry in the context dict --> |
| 227 | <tr> |
| 228 | {% for tc in tablecols %}<th class="{%if tc.dclass%}{{tc.dclass}}{%endif%} {% if tc.clclass %}{{tc.clclass}}{% endif %}"> |
| 229 | {%if tc.qhelp%}<i class="icon-question-sign get-help" title="{{tc.qhelp}}"></i>{%endif%} |
| 230 | {%if tc.orderfield%}<a {%if tc.ordericon%} class="sorted" {%endif%}href="javascript:reload_params({'page': 1, 'orderby' : '{{tc.orderfield}}' })">{{tc.name}}</a>{%else%}<span class="muted">{{tc.name}}</span>{%endif%} |
| 231 | {%if tc.ordericon%} <i class="icon-caret-{{tc.ordericon}}"></i>{%endif%} |
| 232 | {%if tc.filter%}<div class="btn-group pull-right"> |
| 233 | <a href="#filter_{{tc.filter.class}}" role="button" class="btn btn-mini {%if request.GET.filter%}{{tc.filter.options|filtered_icon:request.GET.filter}} {%endif%}" {%if request.GET.filter and tc.filter.options|filtered_tooltip:request.GET.filter %} title="<p>{{tc.filter.options|filtered_tooltip:request.GET.filter}}</p><p><a class='btn btn-small btn-primary' href=javascript:reload_params({'filter':''})>Show all {% if filter_search_display %}{{filter_search_display}}{% else %}{{objectname}}{% endif %}</a></p>" {%endif%} data-toggle="modal"> <i class="icon-filter filtered"></i> </a> |
| 234 | </div>{%endif%} |
| 235 | </th>{% endfor %} |
| 236 | </tr> |
| 237 | </thead> |
| 238 | <tbody> |
| 239 | |