Fix tag selector dropdown style
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
/*!
|
/*!
|
||||||
* Tag Selector plugin for jQuery: Facilitates selecting multiple tags by extending jQuery UI Autocomplete.
|
* Tag Selector plugin for jQuery: Facilitates selecting multiple tags by extending jQuery UI Autocomplete.
|
||||||
* You may use Tag Selector under the terms of either the MIT License or the GNU General Public License (GPL) Version 2.
|
* License: MIT
|
||||||
* https://petprojects.googlecode.com/svn/trunk/MIT-LICENSE.txt
|
* https://petprojects.googlecode.com/svn/trunk/MIT-LICENSE.txt
|
||||||
*/
|
*/
|
||||||
(function($) {
|
(function($) {
|
||||||
@@ -20,7 +20,6 @@
|
|||||||
|
|
||||||
function show_error(input, msg) {
|
function show_error(input, msg) {
|
||||||
const err = input.parent().parent().find(".invalid-remaining");
|
const err = input.parent().parent().find(".invalid-remaining");
|
||||||
console.log(err.length);
|
|
||||||
err.text(msg);
|
err.text(msg);
|
||||||
err.show();
|
err.show();
|
||||||
}
|
}
|
||||||
@@ -30,14 +29,22 @@
|
|||||||
const selector = $(this),
|
const selector = $(this),
|
||||||
input = $('input[type=text]', this);
|
input = $('input[type=text]', this);
|
||||||
|
|
||||||
selector.click(function() { input.focus(); })
|
const lookup = {};
|
||||||
|
for (let i = 0; i < source.length; i++) {
|
||||||
|
lookup[source[i].id] = source[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
selector.click(() => input.focus())
|
||||||
.delegate('.badge a', 'click', function() {
|
.delegate('.badge a', 'click', function() {
|
||||||
const id = $(this).parent().data("id");
|
const id = $(this).parent().data("id");
|
||||||
select.find("option[value=" + id + "]").attr("selected", false)
|
select.find("option[value=" + id + "]").attr("selected", false)
|
||||||
recreate();
|
recreate();
|
||||||
});
|
});
|
||||||
|
|
||||||
function addTag(id, text) {
|
function addTag(item) {
|
||||||
|
const id = item.id;
|
||||||
|
|
||||||
|
let text = item.text;
|
||||||
const idx = text.indexOf(':');
|
const idx = text.indexOf(':');
|
||||||
if (idx > 0) {
|
if (idx > 0) {
|
||||||
text = text.substr(0, idx);
|
text = text.substr(0, idx);
|
||||||
@@ -57,7 +64,7 @@
|
|||||||
selector.find("span").remove();
|
selector.find("span").remove();
|
||||||
select.find("option").each(function() {
|
select.find("option").each(function() {
|
||||||
if (this.hasAttribute("selected")) {
|
if (this.hasAttribute("selected")) {
|
||||||
addTag(this.getAttribute("value"), this.innerText);
|
addTag(lookup[this.getAttribute("value")]);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -65,185 +72,44 @@
|
|||||||
|
|
||||||
input.focusout(function() {
|
input.focusout(function() {
|
||||||
const value = input.val().trim();
|
const value = input.val().trim();
|
||||||
if (value != "") {
|
if (value !== "") {
|
||||||
show_error(input, "Please select an existing tag, it;s not possible to add custom ones.");
|
show_error(input, "Please select an existing tag, it's not possible to add custom ones.");
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
input.keydown(function(e) {
|
input.keydown(function(e) {
|
||||||
if (e.keyCode === $.ui.keyCode.TAB && $(this).data('ui-autocomplete').menu.active)
|
if (e.keyCode === $.ui.keyCode.TAB && $(this).data('ui-autocomplete').menu.active) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
})
|
}
|
||||||
.autocomplete({
|
}).autocomplete({
|
||||||
minLength: 0,
|
minLength: 0,
|
||||||
source: source,
|
source: source,
|
||||||
select: function(event, ui) {
|
select: function(event, ui) {
|
||||||
addTag(ui.item.id, ui.item.toString());
|
addTag(ui.item);
|
||||||
input.val("");
|
input.val("");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}).focus(function() {
|
}).focus(function() {
|
||||||
// The following works only once.
|
$(this).data("ui-autocomplete").search($(this).val());
|
||||||
// $(this).trigger('keydown.autocomplete');
|
});
|
||||||
// As suggested by digitalPBK, works multiple times
|
|
||||||
// $(this).data("autocomplete").search($(this).val());
|
|
||||||
// As noted by Jonny in his answer, with newer versions use uiAutocomplete
|
|
||||||
$(this).data("ui-autocomplete").search($(this).val());
|
|
||||||
});
|
|
||||||
|
|
||||||
input.data('ui-autocomplete')._renderItem = function(ul, item) {
|
input.data('ui-autocomplete')._renderItem = function(ul, item) {
|
||||||
return $('<li/>')
|
return $('<li/>')
|
||||||
.data('item.autocomplete', item)
|
.data('item.autocomplete', item)
|
||||||
.append($('<a/>').html(item.toString()))
|
.append($('<a/>').html(item.toString()))
|
||||||
.appendTo(ul);
|
.appendTo(ul);
|
||||||
};
|
};
|
||||||
|
|
||||||
input.data('ui-autocomplete')._resizeMenu = function(ul, item) {
|
input.data('ui-autocomplete')._resizeMenu = function() {
|
||||||
var ul = this.menu.element;
|
const ul = this.menu.element;
|
||||||
ul.outerWidth(Math.max(
|
ul.outerWidth(Math.max(
|
||||||
ul.width('').outerWidth(),
|
ul.width('').outerWidth(),
|
||||||
selector.outerWidth()
|
selector.outerWidth()
|
||||||
));
|
));
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
$.fn.csvSelector = function(source, name, result, allowSlash) {
|
|
||||||
return this.each(function() {
|
|
||||||
const selector = $(this),
|
|
||||||
input = $('input[type=text]', this);
|
|
||||||
|
|
||||||
let selected = [];
|
|
||||||
const lookup = {};
|
|
||||||
for (var i = 0; i < source.length; i++) {
|
|
||||||
lookup[source[i].id] = source[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
selector.click(function() { input.focus(); })
|
|
||||||
.delegate('.badge a', 'click', function() {
|
|
||||||
const id = $(this).parent().data("id");
|
|
||||||
for (let i = 0; i < selected.length; i++) {
|
|
||||||
if (selected[i] == id) {
|
|
||||||
selected.splice(i, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
recreate();
|
|
||||||
});
|
|
||||||
|
|
||||||
function selectItem(id) {
|
|
||||||
for (let i = 0; i < selected.length; i++) {
|
|
||||||
if (selected[i] == id) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
selected.push(id);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
function addTag(id, value) {
|
|
||||||
const tag = $('<span class="badge badge-pill badge-primary"/>')
|
|
||||||
.text(value)
|
|
||||||
.data("id", id)
|
|
||||||
.append(' <a>x</a>')
|
|
||||||
.insertBefore(input);
|
|
||||||
|
|
||||||
input.attr("placeholder", null);
|
|
||||||
hide_error(input);
|
|
||||||
}
|
|
||||||
|
|
||||||
function recreate() {
|
|
||||||
selector.find("span").remove();
|
|
||||||
for (let i = 0; i < selected.length; i++) {
|
|
||||||
const value = lookup[selected[i]] || {value: selected[i]};
|
|
||||||
addTag(selected[i], value.value);
|
|
||||||
}
|
|
||||||
result.val(selected.join(","))
|
|
||||||
}
|
|
||||||
|
|
||||||
function readFromResult() {
|
|
||||||
selected = [];
|
|
||||||
const selected_raw = result.val().split(",");
|
|
||||||
for (let i = 0; i < selected_raw.length; i++) {
|
|
||||||
const raw = selected_raw[i].trim();
|
|
||||||
if (lookup[raw] || raw.match(/^([a-z0-9_]+)$/)) {
|
|
||||||
selected.push(raw);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
recreate();
|
|
||||||
}
|
|
||||||
readFromResult();
|
|
||||||
|
|
||||||
result.change(readFromResult);
|
|
||||||
|
|
||||||
input.focusout(function() {
|
|
||||||
const item = input.val();
|
|
||||||
if (item.length == 0) {
|
|
||||||
input.data("ui-autocomplete").search("");
|
|
||||||
} else if (item.match(/^([a-z0-9_]+)$/)) {
|
|
||||||
selectItem(item);
|
|
||||||
recreate();
|
|
||||||
input.val("");
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
|
|
||||||
input.keydown(function(e) {
|
|
||||||
if (e.keyCode === $.ui.keyCode.TAB && $(this).data('ui-autocomplete').menu.active)
|
|
||||||
e.preventDefault();
|
|
||||||
else if (e.keyCode === $.ui.keyCode.COMMA) {
|
|
||||||
var item = input.val();
|
|
||||||
if (item.length == 0) {
|
|
||||||
input.data("ui-autocomplete").search("");
|
|
||||||
} else if (item.match(/^([a-z0-9_]+)$/)) {
|
|
||||||
selectItem(item);
|
|
||||||
recreate();
|
|
||||||
input.val("");
|
|
||||||
} else {
|
|
||||||
show_error(input, "Only lowercase alphanumeric and number names allowed.");
|
|
||||||
}
|
|
||||||
e.preventDefault();
|
|
||||||
return true;
|
|
||||||
} else if (e.keyCode === $.ui.keyCode.BACKSPACE) {
|
|
||||||
if (input.val() == "") {
|
|
||||||
var item = selected[selected.length - 1];
|
|
||||||
selected.splice(selected.length - 1, 1);
|
|
||||||
recreate();
|
|
||||||
if (!(item.indexOf("/") > 0))
|
|
||||||
input.val(item);
|
|
||||||
e.preventDefault();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.autocomplete({
|
|
||||||
minLength: 0,
|
|
||||||
source: source,
|
|
||||||
select: function(event, ui) {
|
|
||||||
selectItem(ui.item.id);
|
|
||||||
recreate();
|
|
||||||
input.val("");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
input.data('ui-autocomplete')._renderItem = function(ul, item) {
|
|
||||||
return $('<li/>')
|
|
||||||
.data('item.autocomplete', item)
|
|
||||||
.append($('<a/>').text(item.toString()))
|
|
||||||
.appendTo(ul);
|
|
||||||
};
|
|
||||||
|
|
||||||
input.data('ui-autocomplete')._resizeMenu = function(ul, item) {
|
|
||||||
var ul = this.menu.element;
|
|
||||||
ul.outerWidth(Math.max(
|
|
||||||
ul.width('').outerWidth(),
|
|
||||||
selector.outerWidth()
|
|
||||||
));
|
|
||||||
};
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
$(function() {
|
$(function() {
|
||||||
$(".multichoice_selector").each(function() {
|
$(".multichoice_selector").each(function() {
|
||||||
const ele = $(this);
|
const ele = $(this);
|
||||||
@@ -253,27 +119,25 @@
|
|||||||
const options = [];
|
const options = [];
|
||||||
sel.find("option").each(function() {
|
sel.find("option").each(function() {
|
||||||
const text = $(this).text();
|
const text = $(this).text();
|
||||||
options.push({
|
const option = {
|
||||||
id: $(this).attr("value"),
|
id: $(this).attr("value"),
|
||||||
value: text,
|
text: text,
|
||||||
selected: !!$(this).attr("selected"),
|
selected: !!$(this).attr("selected"),
|
||||||
toString: function() { return make_bold(text); },
|
toString: function() { return make_bold(text); },
|
||||||
});
|
};
|
||||||
|
|
||||||
|
const idx = text.indexOf(":");
|
||||||
|
if (idx > 0) {
|
||||||
|
option.title = text.substring(0, idx);
|
||||||
|
option.description = text.substring(idx + 1);
|
||||||
|
} else {
|
||||||
|
option.title = text
|
||||||
|
}
|
||||||
|
|
||||||
|
options.push(option);
|
||||||
});
|
});
|
||||||
|
|
||||||
ele.selectSelector(options, sel);
|
ele.selectSelector(options, sel);
|
||||||
});
|
});
|
||||||
|
|
||||||
$(".metapackage_selector").each(function() {
|
|
||||||
const input = $(this).parent().children("input[type='text']");
|
|
||||||
input.hide();
|
|
||||||
$(this).csvSelector(meta_packages, input.attr("name"), input);
|
|
||||||
});
|
|
||||||
|
|
||||||
$(".deps_selector").each(function() {
|
|
||||||
const input = $(this).parent().children("input[type='text']");
|
|
||||||
input.hide();
|
|
||||||
$(this).csvSelector(all_packages, input.attr("name"), input);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
})(jQuery);
|
})(jQuery);
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
border: 1px solid #444 !important;
|
border: 1px solid #444 !important;
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
|
max-width: 700px;
|
||||||
max-height: 400px;
|
max-height: 400px;
|
||||||
|
|
||||||
li {
|
li {
|
||||||
@@ -22,6 +23,13 @@
|
|||||||
padding: 0.3em 0.5em !important;
|
padding: 0.3em 0.5em !important;
|
||||||
margin: 0 !important;
|
margin: 0 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
a:hover, a:focus, li:focus a {
|
||||||
|
font-weight: normal !important;
|
||||||
|
text-decoration: none;
|
||||||
|
padding: 0.3em 0.5em !important;
|
||||||
|
margin: 0 !important;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.bulletselector {
|
.bulletselector {
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<title>{% block title %}title{% endblock %} - {{ config.USER_APP_NAME }}</title>
|
<title>{% block title %}title{% endblock %} - {{ config.USER_APP_NAME }}</title>
|
||||||
<link rel="stylesheet" type="text/css" href="/static/libs/bootstrap.min.css">
|
<link rel="stylesheet" type="text/css" href="/static/libs/bootstrap.min.css">
|
||||||
<link rel="stylesheet" type="text/css" href="/static/custom.css?v=22">
|
<link rel="stylesheet" type="text/css" href="/static/custom.css?v=23">
|
||||||
<link rel="search" type="application/opensearchdescription+xml" href="/static/opensearch.xml" title="ContentDB" />
|
<link rel="search" type="application/opensearchdescription+xml" href="/static/opensearch.xml" title="ContentDB" />
|
||||||
<link rel="shortcut icon" href="/favicon-16.png" sizes="16x16">
|
<link rel="shortcut icon" href="/favicon-16.png" sizes="16x16">
|
||||||
<link rel="icon" href="/favicon-128.png" sizes="128x128">
|
<link rel="icon" href="/favicon-128.png" sizes="128x128">
|
||||||
@@ -196,7 +196,7 @@
|
|||||||
<script src="/static/libs/easymde.min.js"></script>
|
<script src="/static/libs/easymde.min.js"></script>
|
||||||
<link rel="stylesheet" type="text/css" href="/static/libs/easymde.min.css">
|
<link rel="stylesheet" type="text/css" href="/static/libs/easymde.min.css">
|
||||||
<link href="/static/fa/css/all.css" rel="stylesheet">
|
<link href="/static/fa/css/all.css" rel="stylesheet">
|
||||||
<script src="/static/markdowntextarea.js"></script>
|
<script src="/static/markdowntextarea.js?v=2"></script>
|
||||||
|
|
||||||
{% block scriptextra %}{% endblock %}
|
{% block scriptextra %}{% endblock %}
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
@@ -58,9 +58,9 @@
|
|||||||
{%- endmacro %}
|
{%- endmacro %}
|
||||||
|
|
||||||
{% macro form_scripts() -%}
|
{% macro form_scripts() -%}
|
||||||
<link href="/static/libs/jquery-ui.min.css?v=2" rel="stylesheet" type="text/css">
|
<link href="/static/libs/jquery-ui.min.css" rel="stylesheet" type="text/css">
|
||||||
<script src="/static/libs/jquery-ui.min.js?v=2"></script>
|
<script src="/static/libs/jquery-ui.min.js"></script>
|
||||||
<script src="/static/tagselector.js?v=3"></script>
|
<script src="/static/tagselector.js?v=4"></script>
|
||||||
{% endmacro %}
|
{% endmacro %}
|
||||||
|
|
||||||
{% macro package_lists() -%}
|
{% macro package_lists() -%}
|
||||||
@@ -113,38 +113,6 @@
|
|||||||
</div>
|
</div>
|
||||||
{% endmacro %}
|
{% endmacro %}
|
||||||
|
|
||||||
{% macro render_mpackage_field(field, label=None, label_visible=true, right_url=None, right_label=None) -%}
|
|
||||||
<div class="form-group {% if field.errors %}has-danger{% endif %} {{ kwargs.pop('class_', '') }}">
|
|
||||||
{% if field.type != 'HiddenField' and label_visible %}
|
|
||||||
{% if not label %}{% set label=field.label.text %}{% endif %}
|
|
||||||
<label for="{{ field.id }}">{{ label|safe }}</label>
|
|
||||||
{% endif %}
|
|
||||||
<div class="metapackage_selector bulletselector form-control">
|
|
||||||
<input type="text" placeholder="Comma-seperated values">
|
|
||||||
<div class="clearboth"></div>
|
|
||||||
</div>
|
|
||||||
{{ field(class_='form-control', **kwargs) }}
|
|
||||||
<div class="invalid-remaining invalid-feedback"></div>
|
|
||||||
{{ render_errors(field) }}
|
|
||||||
</div>
|
|
||||||
{% endmacro %}
|
|
||||||
|
|
||||||
{% macro render_deps_field(field, label=None, label_visible=true, right_url=None, right_label=None) -%}
|
|
||||||
<div class="form-group {% if field.errors %}has-danger{% endif %} {{ kwargs.pop('class_', '') }}">
|
|
||||||
{% if field.type != 'HiddenField' and label_visible %}
|
|
||||||
{% if not label %}{% set label=field.label.text %}{% endif %}
|
|
||||||
<label for="{{ field.id }}">{{ label|safe }}</label>
|
|
||||||
{% endif %}
|
|
||||||
<div class="deps_selector bulletselector form-control">
|
|
||||||
<input type="text" placeholder="Comma-seperated values">
|
|
||||||
<div class="clearboth"></div>
|
|
||||||
</div>
|
|
||||||
{{ field(class_='form-control', **kwargs) }}
|
|
||||||
<div class="invalid-remaining invalid-feedback"></div>
|
|
||||||
{{ render_errors(field) }}
|
|
||||||
</div>
|
|
||||||
{% endmacro %}
|
|
||||||
|
|
||||||
{% macro render_checkbox_field(field, label=None) -%}
|
{% macro render_checkbox_field(field, label=None) -%}
|
||||||
{% if not label %}{% set label=field.label.text %}{% endif %}
|
{% if not label %}{% set label=field.label.text %}{% endif %}
|
||||||
<div class="checkbox {{ kwargs.pop('class_', '') }}">
|
<div class="checkbox {{ kwargs.pop('class_', '') }}">
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% from "macros/forms.html" import render_field, render_field_prefix_button, render_submit_field, form_scripts,
|
{% from "macros/forms.html" import render_field, render_field_prefix_button, render_submit_field, form_scripts,
|
||||||
render_multiselect_field, render_mpackage_field, render_deps_field, package_lists %}
|
render_multiselect_field, package_lists %}
|
||||||
|
|
||||||
{% block scriptextra %}
|
{% block scriptextra %}
|
||||||
{{ form_scripts() }}
|
{{ form_scripts() }}
|
||||||
@@ -87,19 +87,6 @@
|
|||||||
{{ render_field(form.desc, class_="pkg_meta", fieldclass="form-control markdown") }}
|
{{ render_field(form.desc, class_="pkg_meta", fieldclass="form-control markdown") }}
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
||||||
<fieldset class="pkg_meta">
|
|
||||||
<legend class="not_txp">{{ _("Dependencies") }}</legend>
|
|
||||||
|
|
||||||
<p class="alert alert-secondary not_txp">
|
|
||||||
<span class="fas fa-info pr-1"></span>
|
|
||||||
|
|
||||||
{{ _("Note: This information is now updated automatically when creating a release.") }}
|
|
||||||
</p>
|
|
||||||
|
|
||||||
{# {{ render_deps_field(form.harddep_str, class_="not_txp not_game", placeholder="Comma separated list") }}
|
|
||||||
{{ render_deps_field(form.softdep_str, class_="not_txp not_game", placeholder="Comma separated list") }} #}
|
|
||||||
</fieldset>
|
|
||||||
|
|
||||||
<fieldset class="mt-4">
|
<fieldset class="mt-4">
|
||||||
<legend class="pkg_meta">{{ _("Repository and Links") }}</legend>
|
<legend class="pkg_meta">{{ _("Repository and Links") }}</legend>
|
||||||
|
|
||||||
|
|||||||
@@ -77,7 +77,7 @@
|
|||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block scriptextra %}
|
{% block scriptextra %}
|
||||||
<script src="/static/libs/jquery-ui.min.js?v=2"></script>
|
<script src="/static/libs/jquery-ui.min.js"></script>
|
||||||
<script>
|
<script>
|
||||||
function update() {
|
function update() {
|
||||||
const elements = Array.from(document.getElementsByClassName("sortable")[0].children);
|
const elements = Array.from(document.getElementsByClassName("sortable")[0].children);
|
||||||
|
|||||||
Reference in New Issue
Block a user