blob: 5a9076d2aaa60fe5f471b417d65de35262757a95 [file] [log] [blame]
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001{% 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 -->
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600162<div class="navbar navbar-default">
163 <div class="container-fluid">
164 <div class="navbar-header">
165 <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#table-chrome-collapse-variablehistory" aria-expanded="false">
166 <span class="sr-only">Toggle table options</span>
167 <span class="icon-bar"></span>
168 <span class="icon-bar"></span>
169 <span class="icon-bar"></span>
170 </button>
171 </div>
172 <div class="collapse navbar-collapse" id="table-chrome-collapse-variablehistory">
173 <form class="navbar-form navbar-left" id="searchform">
174 <div class="form-group">
175 <div class="btn-group">
176 <input class="form-control" 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 %}"/>
177 {% if request.GET.search %}<a href="javascript:$('#search').val('');searchform.submit()" tabindex="-1"><span class="remove-search-btn-variables glyphicon glyphicon-remove-circle"></span></a>{%endif%}
178 </div>
179 </div>
180 <input type="hidden" name="orderby" value="{{request.GET.orderby}}">
181 <input type="hidden" name="page" value="1">
182 <button class="btn btn-default" id="search-button" type="submit" value="Search">Search</button>
183 </form>
184 <form class="navbar-form navbar-right">
185 <div class="form-group">
186 <label>Show rows:</label>
187 <select class="pagesize form-control">
188 {% with "10 25 50 100 150" as list%}
189 {% for i in list.split %}
190 <option value="{{i}}">{{i}}</option>
191 {% endfor %}
192 {% endwith %}
193 </select>
194 </div>
195 </form>
196
197 <div class="btn-group navbar-right">
198 {% if tablecols %}
199 <button id="edit-columns-button" class="btn btn-default navbar-btn dropdown-toggle" data-toggle="dropdown">Edit columns
200 <span class="caret"></span>
201 </button>
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500202<!--
203 {{tablecols|sortcols}}
204-->
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600205 <ul id="editcol" class="dropdown-menu editcol">
206 {% for i in tablecols|sortcols %}
207 <li>
208 <div class="checkbox">
209 <label {% if not i.clclass %} class="muted" {%endif%}>
210 <input type="checkbox" class="chbxtoggle"
211 {% if i.clclass %}
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500212 id="{{i.clclass}}"
213 value="ct{{i.name}}"
214 {% if not i.hidden %}
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600215 checked="checked"
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500216 {%endif%}
217 onclick="showhideTableColumn(
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600218 $(this).attr('id'),
219 $(this).is(':checked'),
220 {% if i.ordericon %}
221 '{{i.orderkey}}'
222 {% else %}
223 undefined
224 {% endif %}
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500225 )"
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600226 {%else%}
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500227 checked disabled
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600228 {% endif %}/>{{i.name}}
229 </label>
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500230 </div>
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600231 </li>
232 {% endfor %}
233 </ul>
234 {% endif %}
235 </div>
236 </div> <!-- navbar-collapse -->
237 </div> <!-- container-fluid -->
238</div> <!-- navbar-default -->
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500239
240<!-- the actual rows of the table -->
241 <table class="table table-bordered table-hover tablesorter" id="otable">
242 <thead>
243 <!-- Table header row; generated from "tablecols" entry in the context dict -->
244 <tr>
245 {% for tc in tablecols %}<th class="{%if tc.dclass%}{{tc.dclass}}{%endif%} {% if tc.clclass %}{{tc.clclass}}{% endif %}">
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600246 {%if tc.qhelp%}<span class="glyphicon glyphicon-question-sign get-help" title="{{tc.qhelp}}"></span>{%endif%}
247 {%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="text-muted">{{tc.name}}</span>{%endif%}
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500248 {%if tc.ordericon%} <i class="icon-caret-{{tc.ordericon}}"></i>{%endif%}
249 {%if tc.filter%}<div class="btn-group pull-right">
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600250 <a href="#filter_{{tc.filter.class}}" role="button" class="btn btn-xs {%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-sm 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"> <span class="glyphicon glyphicon-filter filtered"></span> </a>
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500251 </div>{%endif%}
252 </th>{% endfor %}
253 </tr>
254 </thead>
255 <tbody>
256