Switch to list.js

- Legacy-Id: 19695
This commit is contained in:
Lars Eggert 2021-11-22 09:21:32 +00:00
parent e195a00d1b
commit 2b20cca858
8 changed files with 206 additions and 141 deletions

View file

@ -6,7 +6,8 @@ module.exports = {
"no-multiple-empty-lines": ["error", { max: 2, maxEOF: 0 }],
"quote-props": ["error", "as-needed"],
"brace-style": ["error", "1tbs", { allowSingleLine: true }],
"semi": ["error", "always"],
semi: ["error", "always"],
"newline-per-chained-call": ["error"]
},
env: {
browser: true,

View file

@ -1 +0,0 @@
@import "../../../node_modules/datatables.net-bs5/css/dataTables.bootstrap5";

View file

@ -61,10 +61,6 @@ $bootstrap-icons-font-src: url("~node_modules/bootstrap-icons/font/fonts/bootstr
url("~node_modules/bootstrap-icons/font/fonts/bootstrap-icons.woff?a97b3594ad416896e15824f6787370e0") format("woff") !default;
@import "../../../node_modules/bootstrap-icons/font/bootstrap-icons";
// Install the datatables.net bootstrap5 styles.
// FIXME: Including this with ~ fails for some odd reason?
@import "../../../node_modules/datatables.net-bs5/css/dataTables.bootstrap5";
// Leave room for fixed-top navbar.
body {
padding-top: 60px;

View file

@ -1,14 +0,0 @@
require('datatables.net')(window, $);
require('datatables.net-bs5')(window, $);
// Disable datatable paging by default.
$.extend($.fn.dataTable.defaults, {
info : false,
paging : false,
order: [],
"search": {
"caseInsensitive": true
}
});
$(document).ready(function() { $(".tablesorter").DataTable(); });

78
ietf/static/js/list.js Normal file
View file

@ -0,0 +1,78 @@
import * as List from "list.js";
$(document)
.ready(function () {
$("table.tablesorter")
.each(function () {
var searcher = $.parseHTML(`
<div class="input-group mb-3">
<input type="search" class="search form-control" placeholder="Search"/>
<button class="btn btn-outline-secondary search-reset" type="button">
<i class="bi bi-x"></i>
</button>
</div>`);
$(this)
.before(searcher);
var fields = $(this)
.find("thead > tr:first")
.children("th")
.map(function () {
return $(this)
.attr("data-field");
})
.toArray();
console.log(fields);
var search_field = $(searcher)
.find("input.search");
var reset_search = $(searcher)
.find("button.search-reset");
if (fields.length == 0) {
searcher.addClass("visually-hidden");
} else {
console.log($(this)[0]);
var list = new List($(this)
.parent()[0], { valueNames: fields });
reset_search.on("click", function () {
search_field.val("");
list.search();
});
search_field.on("keydown", function (e) {
if (e.key == "Escape") {
reset_search.trigger("click");
}
});
list.on("searchComplete", function () {
var last_show_with_children = -1;
for (var i = 0; i < list.items.length; i++) {
if ($(list.items[i].elm)
.hasClass("show-with-children")) {
last_show_with_children = i;
}
if (list.items[i].found &&
last_show_with_children >= 0 &&
list.items[last_show_with_children].found == false) {
list.items[last_show_with_children].found = true;
list.items[last_show_with_children].show();
last_show_with_children = -1;
}
if ($(list.items[i].elm)
.hasClass("show-always")) {
list.items[i].found = true;
list.items[i].show();
}
}
list.update();
});
}
});
});

View file

@ -118,96 +118,106 @@
<p>Check boxes below to select individual sessions.</p>
{% endif %}
<table id="agenda-table" class="table table-sm">
{% for item in filtered_assignments %}
{% ifchanged item.timeslot.time|date:"Y-m-d" %}
<tr class="table-primary">
<th colspan="6">
{# The anchor here needs to be in a div, not in the th, in order for the anchor-target margin hack to work #}
<div class="anchor-target" id="slot-{{item.timeslot.time|slugify}}"></div>
<div class="h6 mt-2">{{ item.timeslot.time|date:"l, F j, Y" }}</div>
</th>
<table id="agenda-table" class="table table-sm tablesorter">
<thead>
<tr>
<th data-field=""></th>
<th data-field=""></th>
<th data-field="loc"></th>
<th data-field="group"></th>
<th data-field="area"></th>
<th data-field="desc"></th>
</tr>
{% endifchanged %}
</thead>
<tbody class="list">
{% for item in filtered_assignments %}
{% ifchanged item.timeslot.time|date:"Y-m-d" %}
<tr class="table-primary show-with-children">
<td colspan="6">
{# The anchor here needs to be in a div, not in the th, in order for the anchor-target margin hack to work #}
<div class="anchor-target" id="slot-{{item.timeslot.time|slugify}}"></div>
<div class="fw-bold">{{ item.timeslot.time|date:"l, F j, Y" }}</div>
</td>
</tr>
{% endifchanged %}
{% if item|is_special_agenda_item %}
<tr id="row-{{ item.slug }}" data-filter-keywords="{{ item.filter_keywords|join:',' }}"
data-slot-start-ts="{{item.start_timestamp}}"
data-slot-end-ts="{{item.end_timestamp}}">
<td class="text-center">
{% if item.session_keyword %}
<input
type="checkbox"
class="pickview form-check-input"
title="Select session"
name="selected-sessions"
value="{{ item.session_keyword }}"
data-filter-keywords="{{ item.filter_keywords|join:',' }}"
data-filter-item="{{ item.session_keyword }}">
{% endif %}
</td>
{% if item|is_special_agenda_item %}
<tr id="row-{{ item.slug }}" data-filter-keywords="{{ item.filter_keywords|join:',' }}"
data-slot-start-ts="{{item.start_timestamp}}"
data-slot-end-ts="{{item.end_timestamp}}">
<td class="text-center">
{% if item.session_keyword %}
<input
type="checkbox"
class="pickview form-check-input"
title="Select session"
name="selected-sessions"
value="{{ item.session_keyword }}"
data-filter-keywords="{{ item.filter_keywords|join:',' }}"
data-filter-item="{{ item.session_keyword }}">
<td class="text-nowrap text-end">
{% include "meeting/timeslot_start_end.html" %}
</td>
<td colspan="3" class="loc">
{% location_anchor item.timeslot %}
{{ item.timeslot.get_html_location }}
{% end_location_anchor %}
{% if item.timeslot.show_location and item.timeslot.get_html_location %}
{% with item.timeslot.location.floorplan as floor %}
{% if item.timeslot.location.floorplan %}
<div class="d-none d-sm-block">
<a href="{% url 'ietf.meeting.views.floor_plan' num=schedule.meeting.number %}#{{floor.name|xslugify}}"
class="float-end" title="{{floor.name}}"><span class="badge bg-secondary label-wide">{{floor.short}}</span></a>
</div>
{% endif %}
{% endwith %}
{% endif %}
</td>
<td class="desc">
{% agenda_anchor item.session %}
{% assignment_display_name item %}
{% end_agenda_anchor %}
{% if item.session.current_status == 'canceled' %}
<span class="badge bg-danger float-end">CANCELLED</span>
{% else %}
<div class="float-end ps-3">
{% if item.slot_type.slug == 'other' %}
{% if item.session.agenda or item.session.remote_instructions or item.session.agenda_note %}
{% include "meeting/session_buttons_include.html" with show_agenda=True item=item schedule=schedule %}
{% else %}
{% for slide in item.session.slides %}
<a href="{{slide.get_href}}">{{ slide.title|clean_whitespace }}</a>
<br>
{% endfor %}
{% endif %}
{% endif %}
</td>
<td class="text-nowrap text-end">
{% include "meeting/timeslot_start_end.html" %}
</td>
<td colspan="3">
{% location_anchor item.timeslot %}
{{ item.timeslot.get_html_location }}
{% end_location_anchor %}
{% if item.timeslot.show_location and item.timeslot.get_html_location %}
{% with item.timeslot.location.floorplan as floor %}
{% if item.timeslot.location.floorplan %}
<div class="d-none d-sm-block">
<a href="{% url 'ietf.meeting.views.floor_plan' num=schedule.meeting.number %}#{{floor.name|xslugify}}"
class="float-end" title="{{floor.name}}"><span class="badge bg-secondary label-wide">{{floor.short}}</span></a>
</div>
{% endif %}
{% endwith %}
{% endif %}
</td>
<td>
{% agenda_anchor item.session %}
{% assignment_display_name item %}
{% end_agenda_anchor %}
{% if item.session.current_status == 'canceled' %}
<span class="badge bg-danger float-end">CANCELLED</span>
{% else %}
<div class="float-end ps-3">
{% if item.slot_type.slug == 'other' %}
{% if item.session.agenda or item.session.remote_instructions or item.session.agenda_note %}
{% include "meeting/session_buttons_include.html" with show_agenda=True item=item schedule=schedule %}
{% else %}
{% for slide in item.session.slides %}
<a href="{{slide.get_href}}">{{ slide.title|clean_whitespace }}</a>
<br>
{% endfor %}
{% endif %}
</div>
{% endif %}
</div>
{% endif %}
</td>
</tr>
</td>
</tr>
{% elif item|is_regular_agenda_item or item|is_plenary_agenda_item %}
{% if item|is_regular_agenda_item %}
{% ifchanged %}
<tr class="table-secondary session-label-row"
<tr class="table-secondary session-label-row show-with-children"
data-slot-start-ts="{{item.start_timestamp}}"
data-slot-end-ts="{{item.end_timestamp}}">
<td class="text-center">
</td>
<th class="text-nowrap text-end">
<td class="text-nowrap text-end fw-bold">
{% include "meeting/timeslot_start_end.html" %}
</th>
<th colspan="4">
</td>
<td colspan="4" class="fw-bold desc">
{{ item.timeslot.time|date:"l"}}
{{item.timeslot.name|capfirst_allcaps}}
</th>
</td>
</tr>
{% endifchanged %}
{% endif %}
@ -232,10 +242,10 @@
</td>
{% if item.slot_type.slug == 'plenary' %}
<th class="text-nowrap text-end">
<td class="text-nowrap text-end">
{% include "meeting/timeslot_start_end.html" %}
</th>
<td colspan="3">
</td>
<td colspan="3" class="loc">
{% location_anchor item.timeslot %}
{{item.timeslot.get_html_location}}
{% end_location_anchor %}
@ -252,15 +262,15 @@
{% endif %}
{% endwith %}
</td>
<td>
<td class="loc">
{% location_anchor item.timeslot %}
{{item.timeslot.get_html_location}}
{% end_location_anchor %}
</td>
<td><div class="d-none d-sm-block">{{item.session.historic_group.historic_parent.acronym}}</div></td>
<td class="area"><div class="d-none d-sm-block">{{item.session.historic_group.historic_parent.acronym}}</div></td>
<td>
<td class="group">
{% if item.session.historic_group %}
<a href="{% url 'ietf.group.views.group_about' acronym=item.session.historic_group.acronym %}">{{item.session.historic_group.acronym}}</a>
{% else %}
@ -269,7 +279,7 @@
</td>
{% endif %}
<td>
<td class="desc">
{% agenda_anchor item.session %}
{% assignment_display_name item %}
{% end_agenda_anchor %}
@ -291,7 +301,7 @@
RESCHEDULED
{% if item.session.rescheduled_to %}
TO
<div class="timetooltip reschedtimetooltip"><div class="time" data-start-time="{{item.session.rescheduled_to.utc_start_time|date:"U"}}" data-end-time="{{item.session.rescheduled_to.utc_end_time|date:"U"}}" {% if item.timeslot.time|date:"l" != item.session.rescheduled_to.time|date:"l" %} weekday="1"{% endif %}>
<div class="timetooltip reschedtimetooltip"><div data-start-time="{{item.session.rescheduled_to.utc_start_time|date:"U"}}" data-end-time="{{item.session.rescheduled_to.utc_end_time|date:"U"}}" {% if item.timeslot.time|date:"l" != item.session.rescheduled_to.time|date:"l" %} weekday="1"{% endif %}>
{% if "-utc" in request.path %}
{{ item.session.rescheduled_to.utc_start_time|date:"l G:i"|upper }}-{{ item.session.rescheduled_to.utc_end_time|date:"G:i" }}
{% else %}
@ -309,9 +319,11 @@
{% endif %}
</td>
</tr>
{% endif %}
{% endif %}
{% endfor %}
</tbody>
</table>
{% include "meeting/agenda_personalize_buttonlist.html" with meeting=schedule.meeting only %}
@ -428,6 +440,7 @@
}
</script>
<script src="{% static 'ietf/js/list.js' %}"></script>
<script src="{% static 'ietf/js/moment.js' %}"></script>
<script src="{% static 'ietf/js/moment-timezone-with-data-10-year-range.js' %}"></script>
<script src="{% static 'ietf/js/timezone.js' %}"></script>
@ -496,7 +509,7 @@
});
document.getElementById('agenda-table')
.addEventListener('click', handleTableClick);
.addEventListener('click', handleTableClick);
{% else %}
agenda_filter.set_update_callback(update_view);
{% endif %}

66
package-lock.json generated
View file

@ -9,10 +9,9 @@
"bootstrap": "^5.1.3",
"bootstrap-icons": "^1.7.0",
"d3": "^3.5.17",
"datatables.net": "^1.11.3",
"datatables.net-bs5": "^1.11.3",
"jquery": "^3.6.0",
"js-cookie": "^3.0.1",
"list.js": "^2.3.1",
"moment": "^2.29.1",
"moment-timezone": "^0.5.34"
},
@ -3194,23 +3193,6 @@
"whatwg-url": "^7.0.0"
}
},
"node_modules/datatables.net": {
"version": "1.11.3",
"resolved": "https://registry.npmjs.org/datatables.net/-/datatables.net-1.11.3.tgz",
"integrity": "sha512-VMj5qEaTebpNurySkM6jy6sGpl+s6onPK8xJhYr296R/vUBnz1+id16NVqNf9z5aR076OGcpGHCuiTuy4E05oQ==",
"dependencies": {
"jquery": ">=1.7"
}
},
"node_modules/datatables.net-bs5": {
"version": "1.11.3",
"resolved": "https://registry.npmjs.org/datatables.net-bs5/-/datatables.net-bs5-1.11.3.tgz",
"integrity": "sha512-u0tosKUR1XNpXzxOOt2NInnNYayt7GQoG+OM1xPRhdkZ7ZBD4oNF8S0aKve8yvSUq/ZwTMh4WJeh80GdmrJAdQ==",
"dependencies": {
"datatables.net": ">=1.10.25",
"jquery": ">=1.7"
}
},
"node_modules/debug": {
"version": "4.3.2",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz",
@ -5568,6 +5550,17 @@
"integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=",
"dev": true
},
"node_modules/list.js": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/list.js/-/list.js-2.3.1.tgz",
"integrity": "sha512-jnmm7DYpKtH3DxtO1E2VNCC9Gp7Wrp/FWA2JxQrZUhVJ2RCQBd57pCN6W5w6jpsfWZV0PCAbTX2NOPgyFeeZZg==",
"dependencies": {
"string-natural-compare": "^2.0.2"
},
"engines": {
"node": "^6.0 || ^8.0 || ^10.0 || ^12.0 || >=14"
}
},
"node_modules/lmdb-store": {
"version": "1.6.13",
"resolved": "https://registry.npmjs.org/lmdb-store/-/lmdb-store-1.6.13.tgz",
@ -8096,6 +8089,11 @@
"integrity": "sha1-6Kr8CsGFW0Zmkp7X3RJ1311sgRs=",
"dev": true
},
"node_modules/string-natural-compare": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/string-natural-compare/-/string-natural-compare-2.0.3.tgz",
"integrity": "sha512-4Kcl12rNjc+6EKhY8QyDVuQTAlMWwRiNbsxnVwBUKFr7dYPQuXVrtNU4sEkjF9LHY0AY6uVbB3ktbkIH4LC+BQ=="
},
"node_modules/string-width": {
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
@ -11206,23 +11204,6 @@
"whatwg-url": "^7.0.0"
}
},
"datatables.net": {
"version": "1.11.3",
"resolved": "https://registry.npmjs.org/datatables.net/-/datatables.net-1.11.3.tgz",
"integrity": "sha512-VMj5qEaTebpNurySkM6jy6sGpl+s6onPK8xJhYr296R/vUBnz1+id16NVqNf9z5aR076OGcpGHCuiTuy4E05oQ==",
"requires": {
"jquery": ">=1.7"
}
},
"datatables.net-bs5": {
"version": "1.11.3",
"resolved": "https://registry.npmjs.org/datatables.net-bs5/-/datatables.net-bs5-1.11.3.tgz",
"integrity": "sha512-u0tosKUR1XNpXzxOOt2NInnNYayt7GQoG+OM1xPRhdkZ7ZBD4oNF8S0aKve8yvSUq/ZwTMh4WJeh80GdmrJAdQ==",
"requires": {
"datatables.net": ">=1.10.25",
"jquery": ">=1.7"
}
},
"debug": {
"version": "4.3.2",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz",
@ -13009,6 +12990,14 @@
"integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=",
"dev": true
},
"list.js": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/list.js/-/list.js-2.3.1.tgz",
"integrity": "sha512-jnmm7DYpKtH3DxtO1E2VNCC9Gp7Wrp/FWA2JxQrZUhVJ2RCQBd57pCN6W5w6jpsfWZV0PCAbTX2NOPgyFeeZZg==",
"requires": {
"string-natural-compare": "^2.0.2"
}
},
"lmdb-store": {
"version": "1.6.13",
"resolved": "https://registry.npmjs.org/lmdb-store/-/lmdb-store-1.6.13.tgz",
@ -14930,6 +14919,11 @@
"integrity": "sha1-6Kr8CsGFW0Zmkp7X3RJ1311sgRs=",
"dev": true
},
"string-natural-compare": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/string-natural-compare/-/string-natural-compare-2.0.3.tgz",
"integrity": "sha512-4Kcl12rNjc+6EKhY8QyDVuQTAlMWwRiNbsxnVwBUKFr7dYPQuXVrtNU4sEkjF9LHY0AY6uVbB3ktbkIH4LC+BQ=="
},
"string-width": {
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",

View file

@ -4,10 +4,9 @@
"bootstrap": "^5.1.3",
"bootstrap-icons": "^1.7.0",
"d3": "^3.5.17",
"datatables.net": "^1.11.3",
"datatables.net-bs5": "^1.11.3",
"jquery": "^3.6.0",
"js-cookie": "^3.0.1",
"list.js": "^2.3.1",
"moment": "^2.29.1",
"moment-timezone": "^0.5.34"
},
@ -19,7 +18,7 @@
},
"source": [
"ietf/static/js/ietf.js",
"ietf/static/js/datatables.js",
"ietf/static/js/list.js",
"ietf/static/js/document_timeline.js",
"ietf/static/js/d3.js",
"ietf/static/js/moment.js",
@ -33,7 +32,6 @@
"ietf/static/js/doc-search.js",
"ietf/static/js/moment-timezone-with-data-10-year-range.js",
"ietf/static/css/ietf.scss",
"ietf/static/css/datatables.scss",
"ietf/static/images/ietflogo-small-transparent.png",
"ietf/static/images/ietflogo.png",
"ietf/static/images/apple-touch-icon.png",