Feature #34420 » wip_custom_dropdown_with_sortable_items.patch
| app/views/queries/_columns.html.erb | ||
|---|---|---|
| 2 | 2 |
<% available_tag_id = "available_#{tag_id}" %>
|
| 3 | 3 |
<% selected_tag_id = "selected_#{tag_id}" %>
|
| 4 | 4 | |
| 5 |
<span class="query-columns"> |
|
| 6 |
<span> |
|
| 7 |
<%= label_tag available_tag_id, l(:description_available_columns) %> |
|
| 8 |
<%= select_tag 'available_columns', |
|
| 9 |
options_for_select(query_available_inline_columns_options(query)), |
|
| 10 |
:id => available_tag_id, |
|
| 11 |
:multiple => true, :size => 10, |
|
| 12 |
:ondblclick => "moveOptions(this.form.#{available_tag_id}, this.form.#{selected_tag_id});" %>
|
|
| 13 |
</span> |
|
| 14 |
<span class="buttons"> |
|
| 15 |
<input type="button" value="→" class="move-right" |
|
| 16 |
onclick="moveOptions(this.form.<%= available_tag_id %>, this.form.<%= selected_tag_id %>);" /> |
|
| 17 |
<input type="button" value="←" class="move-left" |
|
| 18 |
onclick="moveOptions(this.form.<%= selected_tag_id %>, this.form.<%= available_tag_id %>);" /> |
|
| 19 |
</span> |
|
| 20 |
<span> |
|
| 21 |
<%= label_tag selected_tag_id, l(:description_selected_columns) %> |
|
| 22 |
<%= select_tag tag_name, |
|
| 23 |
options_for_select(query_selected_inline_columns_options(query)), |
|
| 24 |
:id => selected_tag_id, |
|
| 25 |
:multiple => true, :size => 10, |
|
| 26 |
:ondblclick => "moveOptions(this.form.#{selected_tag_id}, this.form.#{available_tag_id});" %>
|
|
| 27 |
</span> |
|
| 28 |
<span class="buttons"> |
|
| 29 |
<input type="button" value="⇈" onclick="moveOptionTop(this.form.<%= selected_tag_id %>);" /> |
|
| 30 |
<input type="button" value="↑" onclick="moveOptionUp(this.form.<%= selected_tag_id %>);" /> |
|
| 31 |
<input type="button" value="↓" onclick="moveOptionDown(this.form.<%= selected_tag_id %>);" /> |
|
| 32 |
<input type="button" value="⇊" onclick="moveOptionBottom(this.form.<%= selected_tag_id %>);" /> |
|
| 5 |
<% selected_columns = query_selected_inline_columns_options(query) %> |
|
| 6 |
<% available_columns = query_available_inline_columns_options(query) %> |
|
| 7 |
<div class="query-columns drdn"> |
|
| 8 |
<span class="drdn-trigger"> |
|
| 9 |
<%= "#{selected_columns.count} out of #{available_columns.count} columns" %>
|
|
| 33 | 10 |
</span> |
| 11 |
<div class="drdn-content"> |
|
| 12 |
<div class="quick-search"> |
|
| 13 |
<%= search_field_tag('q', '', :id => nil, :class => 'autocomplete', :autocomplete => 'off') %>
|
|
| 14 |
</div> |
|
| 15 |
<ul class="drdn-items"> |
|
| 16 |
<% query_selected_inline_columns_options(query).each do |c| %> |
|
| 17 |
<li> |
|
| 18 |
<span class="item-content"> |
|
| 19 |
<%= check_box_tag 'c[]', c.last, true, id: "c_#{c.last}" %>
|
|
| 20 |
<%= label_tag "c_#{c.last}", c.first %>
|
|
| 21 |
</span> |
|
| 22 |
<span class="icon-only icon-sort-handle sort-handle"></span> |
|
| 23 |
</li> |
|
| 24 |
<% end %> |
|
| 25 |
<% query_available_inline_columns_options(query).each do |c| %> |
|
| 26 |
<li> |
|
| 27 |
<span class="item-content"> |
|
| 28 |
<%= check_box_tag 'c[]', c.last, nil, id: "c_#{c.last}" %>
|
|
| 29 |
<%= label_tag "c_#{c.last}", c.first %>
|
|
| 30 |
</span> |
|
| 31 |
<span class="icon-only icon-sort-handle sort-handle"></span> |
|
| 32 |
</li> |
|
| 33 |
<% end %> |
|
| 34 |
</ul> |
|
| 35 |
</div> |
|
| 34 | 36 |
</span> |
| 35 | ||
| 36 | 37 |
<%= javascript_tag do %> |
| 37 |
$(document).ready(function(){
|
|
| 38 |
$('.query-columns').closest('form').submit(function(){
|
|
| 39 |
$('#<%= selected_tag_id %> option:not(:disabled)').prop('selected', true);
|
|
| 38 |
$(document).ready(function(){
|
|
| 39 |
$('.query-columns').closest('form').submit(function(){
|
|
| 40 |
$('#<%= selected_tag_id %> option:not(:disabled)').prop('selected', true);
|
|
| 41 |
}); |
|
| 40 | 42 |
}); |
| 41 |
});
|
|
| 43 |
enableAutocomplete(document.querySelector(".query-columns"));
|
|
| 42 | 44 |
<% end %> |
| 45 | ||
| app/views/queries/_query_form.html.erb | ||
|---|---|---|
| 12 | 12 |
</fieldset> |
| 13 | 13 | |
| 14 | 14 |
<% if @query.available_columns.any? %> |
| 15 |
<fieldset id="options" class="collapsible collapsed">
|
|
| 15 |
<fieldset id="options" class="collapsible"> |
|
| 16 | 16 |
<legend onclick="toggleFieldset(this);" class="icon icon-collapsed"><%= l(:label_options) %></legend> |
| 17 |
<div class="hidden">
|
|
| 17 |
<div class=""> |
|
| 18 | 18 |
<% if @query.available_display_types.size > 1 %> |
| 19 | 19 |
<div> |
| 20 | 20 |
<span class="field"><label for='display_type'><%= l(:label_display_type) %></label></span> |
| public/javascripts/application.js | ||
|---|---|---|
| 1103 | 1103 |
tribute.attach(element); |
| 1104 | 1104 |
} |
| 1105 | 1105 | |
| 1106 |
function enableAutocomplete(element) {
|
|
| 1107 |
const items = $(element).find('.drdn-items')
|
|
| 1108 |
items.sortable(); |
|
| 1109 |
// ToDo: Replace disableSelection with CSS user-select |
|
| 1110 |
items.disableSelection(); |
|
| 1111 | ||
| 1112 |
element.querySelector("input.autocomplete").addEventListener('input', function(event) {
|
|
| 1113 |
filterValues(element, event) |
|
| 1114 |
}) |
|
| 1115 | ||
| 1116 |
function filterValues(context, event) {
|
|
| 1117 |
var input, filter, ul, li, a, i, txtValue; |
|
| 1118 |
input = event.currentTarget; |
|
| 1119 |
filter = input.value.toLowerCase(); |
|
| 1120 | ||
| 1121 |
ul = element.querySelector(".drdn-items");
|
|
| 1122 |
li = ul.getElementsByTagName("li");
|
|
| 1123 | ||
| 1124 |
for (i = 0; i < li.length; i++) {
|
|
| 1125 |
a = li[i].querySelector("span");
|
|
| 1126 |
txtValue = a.textContent || a.innerText; |
|
| 1127 | ||
| 1128 |
if (txtValue.toLowerCase().indexOf(filter) > -1) {
|
|
| 1129 |
li[i].style.display = ''; |
|
| 1130 |
} else {
|
|
| 1131 |
li[i].style.display = 'none'; |
|
| 1132 |
} |
|
| 1133 |
} |
|
| 1134 |
} |
|
| 1135 |
} |
|
| 1136 | ||
| 1106 | 1137 | |
| 1107 | 1138 |
$(document).ready(setupAjaxIndicator); |
| 1108 | 1139 |
$(document).ready(hideOnLoad); |
| public/stylesheets/application.css | ||
|---|---|---|
| 155 | 155 | |
| 156 | 156 |
/***** Dropdown *****/ |
| 157 | 157 |
.drdn {position:relative;}
|
| 158 |
.drdn ul {
|
|
| 159 |
margin: 0; |
|
| 160 |
padding: 0; |
|
| 161 |
} |
|
| 158 | 162 |
.drdn-trigger {
|
| 159 | 163 |
box-sizing:border-box; |
| 160 | 164 |
overflow:hidden; |
| ... | ... | |
| 190 | 194 |
overflow:hidden; |
| 191 | 195 |
text-overflow: ellipsis; |
| 192 | 196 |
white-space:nowrap; |
| 193 |
padding:4px 8px; |
|
| 197 |
padding-left: 8px; |
|
| 198 |
padding-right: 8px; |
|
| 194 | 199 |
} |
| 195 | 200 |
.drdn-items>a:hover {text-decoration:none;}
|
| 196 | 201 |
.drdn-items>*:focus {border:1px dotted #bbb;}
|
| ... | ... | |
| 216 | 221 |
.contextual .drdn-items {padding:2px; min-width: 160px;}
|
| 217 | 222 |
.contextual .drdn-items>a {padding: 5px 8px;}
|
| 218 | 223 |
.contextual .drdn-items>a.icon {padding-left: 24px; background-position-x: 4px;}
|
| 219 |
.contextual .drdn-items>a:hover {color:#2A5685; border:1px solid #628db6; background-color:#eef5fd; border-radius:3px;}
|
|
| 224 |
.contextual .drdn-items>a:hover, .query-columns .drdn-items li:hover {color:#2A5685; border:1px solid #628db6; background-color:#eef5fd; border-radius:3px;}
|
|
| 220 | 225 | |
| 221 | 226 |
#project-jump.drdn {width:200px;display:inline-block;}
|
| 222 |
#project-jump .drdn-trigger {
|
|
| 227 |
#project-jump .drdn-trigger, .query-columns .drdn-trigger {
|
|
| 223 | 228 |
width:100%; |
| 224 | 229 |
height:24px; |
| 225 | 230 |
display:inline-block; |
| ... | ... | |
| 233 | 238 |
} |
| 234 | 239 |
#project-jump .drdn.expanded .drdn-trigger {background-image:url(../images/arrow_up.png);}
|
| 235 | 240 |
#project-jump .drdn-content {width:280px;}
|
| 236 |
#project-jump .drdn-items>* {color:#555 !important;}
|
|
| 241 |
#project-jump .drdn-items>* {color:#555 !important; padding-top: 4px; padding-bottom: 8px;}
|
|
| 237 | 242 |
#project-jump .drdn-items>a:hover {background-color:#759FCF; color:#fff !important;}
|
| 238 | 243 | |
| 239 | 244 |
/***** Tables *****/ |
| ... | ... | |
| 397 | 402 |
height:100%; |
| 398 | 403 |
vertical-align: middle; |
| 399 | 404 |
} |
| 400 |
.query-columns label {
|
|
| 405 |
/*.query-columns label {
|
|
| 401 | 406 |
display:block; |
| 402 |
} |
|
| 407 |
}*/
|
|
| 403 | 408 |
.query-columns .buttons input[type=button] {
|
| 404 | 409 |
width:35px; |
| 405 | 410 |
display:block; |
| ... | ... | |
| 407 | 412 |
.query-columns select {
|
| 408 | 413 |
min-width:150px; |
| 409 | 414 |
} |
| 415 |
.query-columns .drdn-trigger {
|
|
| 416 |
height: 24px; |
|
| 417 |
} |
|
| 418 | ||
| 419 |
.query-columns .drdn-items span.sort-handle {
|
|
| 420 |
float: right; |
|
| 421 |
display: none; |
|
| 422 |
} |
|
| 423 |
.query-columns .drdn-items li:hover span.sort-handle {
|
|
| 424 |
display: block; |
|
| 425 |
} |
|
| 426 | ||
| 410 | 427 | |
| 411 | 428 |
.query-totals {text-align:right; margin-top:-2.3em;}
|
| 412 | 429 |
.query-totals>span:not(:first-child) {margin-left:0.6em;}
|