2 .object_class_wrapper {
4 grid-template-columns: 1fr 1fr 1fr;
17 grid-template-columns: 1fr 1fr;
28 box-shadow: 0px 0px 7px 0px rgba(0,0,0,0.75);
29 transition-property: box-shadow, background-color;
30 transition-duration: .2s;
34 box-shadow: 0px 0px 14px 0px rgba(0,0,0,0.75);
35 transition-property: box-shadow;
36 transition-duration: .2s;
41 box-shadow: 0px 0px 14px 0px rgba(0,0,0,0.75);
42 background-color: #CCECD7;
43 transition-property: background-color;
44 transition-duration: .2s;
49 background-color: #EFEFEF;
50 box-shadow: 0px 0px 1px 0px rgba(0,0,0,0.75);
51 transition-property: box-shadow;
52 transition-duration: .2s;
55 .disabled_node:hover {
56 box-shadow: 0px 0px 1px 0px rgba(0,0,0,0.75);
60 background-color: #FFFFFF;
70 #dropdown_wrapper > div > h5 {
72 display: inline-block;
73 vertical-align: middle;
76 #dropdown_wrapper > div > button {
82 #dropdown_wrapper > div > input {
87 width: calc(100% - 240px);
90 #dropdown_wrapper > div {
97 box-shadow: 0px 0px 7px 0px rgba(0,0,0,0.75);
98 transition-property: box-shadow, background-color;
99 transition-duration: .2s;
100 display: inline-block;
101 vertical-align: middle;
106 grid-template-columns: 3fr 5fr;
110 <input name="filter_field" id="filter_field" type="hidden"/>
111 <div id="grid_wrapper" class="grid_wrapper">
112 {% for object_class, object_list in filter_objects %}
113 <div class="class_grid_wrapper">
114 <div style="display:inline-block;margin:auto">
115 <h4>{{object_class}}</h4>
117 <div id="{{object_class}}" class="object_class_wrapper">
118 {% for obj in object_list %}
119 <div id="object_parent">
120 <div id="{{ obj.id|default:'not_provided' }}" class="grid-item">
121 <p class="grid-item-header">{{obj.name}}</p>
122 <p class="grid-item-description">{{obj.description}}</p>
123 <button type="button" class="btn btn-success grid-item-select-btn" onclick="processClick('{{obj.id}}', {% if obj.multiple %}true{% else %}false{% endif %});">{% if obj.multiple %}Add{% else %}Select{% endif %}</button>
125 <input type="hidden" name="{{obj.id}}_selected" value="false"/>
133 <div id="dropdown_wrapper">
137 var initialized = false;
138 var mapping = {{ mapping|safe }};
139 var filter_items = {{ filter_items|safe }};
141 var selection = {{selection_data|default_if_none:"null"|safe}};
142 var dropdown_count = 0;
144 {% if selection_data %}
145 make_selection({{selection_data|safe}});
148 function make_selection( selection_data ){
152 for(var k in selection_data) {
153 selected_items = selection_data[k];
154 for( var selected_item in selected_items ){
155 var node = filter_items[selected_item];
156 if(!node['multiple']){
157 var input_value = selected_items[selected_item];
158 if( input_value != 'false' ) {
162 var div = document.getElementById(selected_item)
163 var inputs = div.parentNode.getElementsByTagName("input")
164 var input = div.parentNode.getElementsByTagName("input")[0]
165 input.value = input_value;
166 updateResult(selected_item);
168 make_multiple_selection(selected_items, selected_item);
174 function make_multiple_selection(data, item_class){
175 var node = filter_items[item_class];
178 prepop_data = data[item_class];
179 for(var i=0; i<prepop_data.length; i++){
180 var div = add_item_prepopulate(node, prepop_data[i]);
181 updateObjectResult(div);
185 function markAndSweep(root){
186 for(var nodeId in filter_items) {
187 node = filter_items[nodeId];
188 node['marked'] = true; //mark all nodes
189 //clears grey background of everything
195 while(toCheck.length > 0){
196 node = toCheck.pop();
197 if(!node['marked']) {
198 //already visited, just continue
201 node['marked'] = false; //mark as visited
202 if(node['follow'] || node == root){ //add neighbors if we want to follow this node (labs)
203 var mappingId = node.id
204 var neighbors = mapping[mappingId];
205 for(var neighId in neighbors) {
206 neighId = neighbors[neighId];
207 var neighbor = filter_items[neighId];
208 toCheck.push(neighbor);
213 //now remove all nodes still marked
214 for(var nodeId in filter_items){
215 node = filter_items[nodeId];
222 function process(node) {
223 if(node['selected']) {
228 //remember the currently selected, then reset everything and reselect one at a time
229 for(var nodeId in filter_items) {
230 node = filter_items[nodeId];
231 if(node['selected']) {
237 for(var i=0; i<selected.length; i++) {
240 markAndSweep(selected[i]);
245 function select(node) {
246 elem = document.getElementById(node['id']);
247 node['selected'] = true;
248 elem.classList.remove('cleared_node');
249 elem.classList.remove('disabled_node');
250 elem.classList.add('selected_node');
251 var input = elem.parentNode.getElementsByTagName("input")[0];
252 input.disabled = false;
256 function clear(node) {
257 elem = document.getElementById(node['id']);
258 node['selected'] = false;
259 node['selectable'] = true;
260 elem.classList.add('cleared_node')
261 elem.classList.remove('disabled_node');
262 elem.classList.remove('selected_node');
263 elem.parentNode.getElementsByTagName("input")[0].disabled = true;
266 function disable_node(node) {
267 elem = document.getElementById(node['id']);
268 node['selected'] = false;
269 node['selectable'] = false;
270 elem.classList.remove('cleared_node');
271 elem.classList.add('disabled_node');
272 elem.classList.remove('selected_node');
273 elem.parentNode.getElementsByTagName("input")[0].disabled = true;
276 function processClick(id, multiple){
280 var element = document.getElementById(id);
281 var node = filter_items[id];
282 if(!node['selectable']){
286 return processClickMultipleObject(node);
288 node['selected'] = !node['selected']; //toggle on click
290 if(node['selected']) {
300 function processClickMultipleObject(node){
306 function add_node(node){
307 return add_item_prepopulate(node, {});
312 function restrictchars(input)
314 if( input.validity.patternMismatch )
316 input.setCustomValidity("Only alphanumeric characters (a-z, A-Z, 0-9), underscore(_), and hyphen (-) are allowed");
317 input.reportValidity();
320 input.value = input.value.replace(/([^A-Za-z0-9-_.])+/g, "");
325 function checkunique(tocheck)
328 for( var i = 0; i < inputs.length; i++ )
330 if( inputs[i].value == val && inputs[i] != tocheck)
332 tocheck.setCustomValidity("All hostnames must be unique");
333 tocheck.reportValidity();
337 tocheck.setCustomValidity("");
340 function add_item_prepopulate(node, prepopulate){
342 var div = document.createElement("DIV");
343 div.class = node['id'];
344 div.id = "dropdown_" + dropdown_count;
346 var label = document.createElement("H5");
347 label.appendChild(document.createTextNode(node['name']));
348 div.appendChild(label);
349 button = document.createElement("BUTTON");
350 button.type = "button";
351 button.appendChild(document.createTextNode("Remove"));
352 button.classList.add("btn-danger");
353 button.classList.add("btn");
354 div.appendChild(button);
355 for(var i=0; i<node['forms'].length; i++){
356 form = node['forms'][i];
357 var input = document.createElement("INPUT");
358 input.type = form['type'];
359 input.name = form['name'];
360 input.pattern = "(?=^.{1,253}$)(^([A-Za-z0-9-_]{1,62}\.)*[A-Za-z0-9-_]{1,63})";
361 input.title = "Only alphanumeric characters (a-z, A-Z, 0-9), underscore(_), and hyphen (-) are allowed"
362 input.placeholder = form['placeholder'];
364 input.onchange = function() { updateObjectResult(div); restrictchars(this); };
365 input.oninput = function() { restrictchars(this); };
366 if(form['name'] in prepopulate){
367 input.value = prepopulate[form['name']];
369 div.appendChild(input);
371 //add class id to dropdown object
372 var hiddenInput = document.createElement("INPUT");
373 hiddenInput.type = "hidden";
374 hiddenInput.name = "class";
375 hiddenInput.value = node['id'];
376 div.appendChild(hiddenInput);
377 button.onclick = function(){
378 remove_dropdown(div.id);
380 document.getElementById("dropdown_wrapper").appendChild(div);
381 var linebreak = document.createElement("BR");
382 document.getElementById("dropdown_wrapper").appendChild(linebreak);
383 updateObjectResult(div);
387 function remove_dropdown(id){
388 var div = document.getElementById(id);
389 var parent = div.parentNode;
390 div.parentNode.removeChild(div);
391 //checks if we have removed last item in class
392 var deselect_class = true;
393 var div_inputs = div.getElementsByTagName("input");
394 var div_class = div_inputs[div_inputs.length-1].value;
395 var result_class = document.getElementById(div_class).parentNode.parentNode.id;
396 delete result[result_class][div.id];
397 for(var i=0; i<parent.children.length; i++){
398 var inputs = parent.children[i].getElementsByTagName("input");
399 var object_class = "";
400 for(var k=0; k<inputs.length; k++){
401 if(inputs[k].name == "class"){
402 object_class = inputs[k].value;
405 if(object_class == div_class){
406 deselect_class = false;
410 clear(filter_items[div_class]);
414 function updateResult(nodeId){
418 if(!filter_items[nodeId]['multiple']){
419 var node = document.getElementById(nodeId);
421 value[nodeId] = node.parentNode.getElementsByTagName("input")[0].value;
422 result[node.parentNode.parentNode.id] = {};
423 result[node.parentNode.parentNode.id][nodeId] = value;
427 function updateObjectResult(parentElem){
428 node_type = document.getElementById(parentElem.class).parentNode.parentNode.id;
430 inputs = parentElem.getElementsByTagName("input");
431 for(var i in inputs){
433 input[e.name] = e.value;
435 result[node_type][parentElem.id] = input;
438 function filter_field_init() {
439 for(nodeId in filter_items) {
440 element = document.getElementById(nodeId);
441 node = filter_items[nodeId];
442 result[element.parentNode.parentNode.id] = {}