Initial commit

This commit is contained in:
isUnknown 2026-02-12 15:22:46 +01:00
commit 65e0da7e11
1397 changed files with 596542 additions and 0 deletions

View file

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2017 Jon Gacnik
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View file

@ -0,0 +1,12 @@
{
"name": "kirby-index-field",
"description": "Kirby field for displaying pages as a datalist",
"author": "Jon Gacnik <https://github.com/jongacnik>",
"repository": {
"type": "git",
"url": "https://github.com/jongacnik/kirby-index-field"
},
"version": "2.1.0",
"type": "kirby-plugin",
"license": "MIT"
}

View file

@ -0,0 +1,455 @@
/*
* Table styles
*/
table.dataTable {
width: 100%;
margin: 0 auto;
clear: both;
border-collapse: separate;
border-spacing: 0;
/*
* Header and footer styles
*/
/*
* Body styles
*/
}
table.dataTable thead th,
table.dataTable tfoot th {
font-weight: bold;
}
table.dataTable thead th,
table.dataTable thead td {
padding: 10px 18px;
border-bottom: 1px solid #111;
}
table.dataTable thead th:active,
table.dataTable thead td:active {
outline: none;
}
table.dataTable tfoot th,
table.dataTable tfoot td {
padding: 10px 18px 6px 18px;
border-top: 1px solid #111;
}
table.dataTable thead .sorting,
table.dataTable thead .sorting_asc,
table.dataTable thead .sorting_desc,
table.dataTable thead .sorting_asc_disabled,
table.dataTable thead .sorting_desc_disabled {
cursor: pointer;
*cursor: hand;
}
table.dataTable thead .sorting,
table.dataTable thead .sorting_asc,
table.dataTable thead .sorting_desc,
table.dataTable thead .sorting_asc_disabled,
table.dataTable thead .sorting_desc_disabled {
background-repeat: no-repeat;
background-position: center right;
}
table.dataTable thead .sorting {
background-image: url("../images/sort_both.png");
}
table.dataTable thead .sorting_asc {
background-image: url("../images/sort_asc.png");
}
table.dataTable thead .sorting_desc {
background-image: url("../images/sort_desc.png");
}
table.dataTable thead .sorting_asc_disabled {
background-image: url("../images/sort_asc_disabled.png");
}
table.dataTable thead .sorting_desc_disabled {
background-image: url("../images/sort_desc_disabled.png");
}
table.dataTable tbody tr {
background-color: #ffffff;
}
table.dataTable tbody tr.selected {
background-color: #B0BED9;
}
table.dataTable tbody th,
table.dataTable tbody td {
padding: 8px 10px;
}
table.dataTable.row-border tbody th, table.dataTable.row-border tbody td, table.dataTable.display tbody th, table.dataTable.display tbody td {
border-top: 1px solid #ddd;
}
table.dataTable.row-border tbody tr:first-child th,
table.dataTable.row-border tbody tr:first-child td, table.dataTable.display tbody tr:first-child th,
table.dataTable.display tbody tr:first-child td {
border-top: none;
}
table.dataTable.cell-border tbody th, table.dataTable.cell-border tbody td {
border-top: 1px solid #ddd;
border-right: 1px solid #ddd;
}
table.dataTable.cell-border tbody tr th:first-child,
table.dataTable.cell-border tbody tr td:first-child {
border-left: 1px solid #ddd;
}
table.dataTable.cell-border tbody tr:first-child th,
table.dataTable.cell-border tbody tr:first-child td {
border-top: none;
}
table.dataTable.stripe tbody tr.odd, table.dataTable.display tbody tr.odd {
background-color: #f9f9f9;
}
table.dataTable.stripe tbody tr.odd.selected, table.dataTable.display tbody tr.odd.selected {
background-color: #acbad4;
}
table.dataTable.hover tbody tr:hover, table.dataTable.display tbody tr:hover {
background-color: #f6f6f6;
}
table.dataTable.hover tbody tr:hover.selected, table.dataTable.display tbody tr:hover.selected {
background-color: #aab7d1;
}
table.dataTable.order-column tbody tr > .sorting_1,
table.dataTable.order-column tbody tr > .sorting_2,
table.dataTable.order-column tbody tr > .sorting_3, table.dataTable.display tbody tr > .sorting_1,
table.dataTable.display tbody tr > .sorting_2,
table.dataTable.display tbody tr > .sorting_3 {
background-color: #fafafa;
}
table.dataTable.order-column tbody tr.selected > .sorting_1,
table.dataTable.order-column tbody tr.selected > .sorting_2,
table.dataTable.order-column tbody tr.selected > .sorting_3, table.dataTable.display tbody tr.selected > .sorting_1,
table.dataTable.display tbody tr.selected > .sorting_2,
table.dataTable.display tbody tr.selected > .sorting_3 {
background-color: #acbad5;
}
table.dataTable.display tbody tr.odd > .sorting_1, table.dataTable.order-column.stripe tbody tr.odd > .sorting_1 {
background-color: #f1f1f1;
}
table.dataTable.display tbody tr.odd > .sorting_2, table.dataTable.order-column.stripe tbody tr.odd > .sorting_2 {
background-color: #f3f3f3;
}
table.dataTable.display tbody tr.odd > .sorting_3, table.dataTable.order-column.stripe tbody tr.odd > .sorting_3 {
background-color: whitesmoke;
}
table.dataTable.display tbody tr.odd.selected > .sorting_1, table.dataTable.order-column.stripe tbody tr.odd.selected > .sorting_1 {
background-color: #a6b4cd;
}
table.dataTable.display tbody tr.odd.selected > .sorting_2, table.dataTable.order-column.stripe tbody tr.odd.selected > .sorting_2 {
background-color: #a8b5cf;
}
table.dataTable.display tbody tr.odd.selected > .sorting_3, table.dataTable.order-column.stripe tbody tr.odd.selected > .sorting_3 {
background-color: #a9b7d1;
}
table.dataTable.display tbody tr.even > .sorting_1, table.dataTable.order-column.stripe tbody tr.even > .sorting_1 {
background-color: #fafafa;
}
table.dataTable.display tbody tr.even > .sorting_2, table.dataTable.order-column.stripe tbody tr.even > .sorting_2 {
background-color: #fcfcfc;
}
table.dataTable.display tbody tr.even > .sorting_3, table.dataTable.order-column.stripe tbody tr.even > .sorting_3 {
background-color: #fefefe;
}
table.dataTable.display tbody tr.even.selected > .sorting_1, table.dataTable.order-column.stripe tbody tr.even.selected > .sorting_1 {
background-color: #acbad5;
}
table.dataTable.display tbody tr.even.selected > .sorting_2, table.dataTable.order-column.stripe tbody tr.even.selected > .sorting_2 {
background-color: #aebcd6;
}
table.dataTable.display tbody tr.even.selected > .sorting_3, table.dataTable.order-column.stripe tbody tr.even.selected > .sorting_3 {
background-color: #afbdd8;
}
table.dataTable.display tbody tr:hover > .sorting_1, table.dataTable.order-column.hover tbody tr:hover > .sorting_1 {
background-color: #eaeaea;
}
table.dataTable.display tbody tr:hover > .sorting_2, table.dataTable.order-column.hover tbody tr:hover > .sorting_2 {
background-color: #ececec;
}
table.dataTable.display tbody tr:hover > .sorting_3, table.dataTable.order-column.hover tbody tr:hover > .sorting_3 {
background-color: #efefef;
}
table.dataTable.display tbody tr:hover.selected > .sorting_1, table.dataTable.order-column.hover tbody tr:hover.selected > .sorting_1 {
background-color: #a2aec7;
}
table.dataTable.display tbody tr:hover.selected > .sorting_2, table.dataTable.order-column.hover tbody tr:hover.selected > .sorting_2 {
background-color: #a3b0c9;
}
table.dataTable.display tbody tr:hover.selected > .sorting_3, table.dataTable.order-column.hover tbody tr:hover.selected > .sorting_3 {
background-color: #a5b2cb;
}
table.dataTable.no-footer {
border-bottom: 1px solid #111;
}
table.dataTable.nowrap th, table.dataTable.nowrap td {
white-space: nowrap;
}
table.dataTable.compact thead th,
table.dataTable.compact thead td {
padding: 4px 17px 4px 4px;
}
table.dataTable.compact tfoot th,
table.dataTable.compact tfoot td {
padding: 4px;
}
table.dataTable.compact tbody th,
table.dataTable.compact tbody td {
padding: 4px;
}
table.dataTable th.dt-left,
table.dataTable td.dt-left {
text-align: left;
}
table.dataTable th.dt-center,
table.dataTable td.dt-center,
table.dataTable td.dataTables_empty {
text-align: center;
}
table.dataTable th.dt-right,
table.dataTable td.dt-right {
text-align: right;
}
table.dataTable th.dt-justify,
table.dataTable td.dt-justify {
text-align: justify;
}
table.dataTable th.dt-nowrap,
table.dataTable td.dt-nowrap {
white-space: nowrap;
}
table.dataTable thead th.dt-head-left,
table.dataTable thead td.dt-head-left,
table.dataTable tfoot th.dt-head-left,
table.dataTable tfoot td.dt-head-left {
text-align: left;
}
table.dataTable thead th.dt-head-center,
table.dataTable thead td.dt-head-center,
table.dataTable tfoot th.dt-head-center,
table.dataTable tfoot td.dt-head-center {
text-align: center;
}
table.dataTable thead th.dt-head-right,
table.dataTable thead td.dt-head-right,
table.dataTable tfoot th.dt-head-right,
table.dataTable tfoot td.dt-head-right {
text-align: right;
}
table.dataTable thead th.dt-head-justify,
table.dataTable thead td.dt-head-justify,
table.dataTable tfoot th.dt-head-justify,
table.dataTable tfoot td.dt-head-justify {
text-align: justify;
}
table.dataTable thead th.dt-head-nowrap,
table.dataTable thead td.dt-head-nowrap,
table.dataTable tfoot th.dt-head-nowrap,
table.dataTable tfoot td.dt-head-nowrap {
white-space: nowrap;
}
table.dataTable tbody th.dt-body-left,
table.dataTable tbody td.dt-body-left {
text-align: left;
}
table.dataTable tbody th.dt-body-center,
table.dataTable tbody td.dt-body-center {
text-align: center;
}
table.dataTable tbody th.dt-body-right,
table.dataTable tbody td.dt-body-right {
text-align: right;
}
table.dataTable tbody th.dt-body-justify,
table.dataTable tbody td.dt-body-justify {
text-align: justify;
}
table.dataTable tbody th.dt-body-nowrap,
table.dataTable tbody td.dt-body-nowrap {
white-space: nowrap;
}
table.dataTable,
table.dataTable th,
table.dataTable td {
-webkit-box-sizing: content-box;
box-sizing: content-box;
}
/*
* Control feature layout
*/
.dataTables_wrapper {
position: relative;
clear: both;
*zoom: 1;
zoom: 1;
}
.dataTables_wrapper .dataTables_length {
float: left;
}
.dataTables_wrapper .dataTables_filter {
float: right;
text-align: right;
}
.dataTables_wrapper .dataTables_filter input {
margin-left: 0.5em;
}
.dataTables_wrapper .dataTables_info {
clear: both;
float: left;
padding-top: 0.755em;
}
.dataTables_wrapper .dataTables_paginate {
float: right;
text-align: right;
padding-top: 0.25em;
}
// .dataTables_wrapper .dataTables_paginate .paginate_button {
// box-sizing: border-box;
// display: inline-block;
// min-width: 1.5em;
// padding: 0.5em 1em;
// margin-left: 2px;
// text-align: center;
// text-decoration: none !important;
// cursor: pointer;
// *cursor: hand;
// color: #333 !important;
// border: 1px solid transparent;
// border-radius: 2px;
// }
// .dataTables_wrapper .dataTables_paginate .paginate_button.current, .dataTables_wrapper .dataTables_paginate .paginate_button.current:hover {
// color: #333 !important;
// border: 1px solid #979797;
// background-color: white;
// background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, white), color-stop(100%, #dcdcdc));
// /* Chrome,Safari4+ */
// background: -webkit-linear-gradient(top, white 0%, #dcdcdc 100%);
// /* Chrome10+,Safari5.1+ */
// background: -moz-linear-gradient(top, white 0%, #dcdcdc 100%);
// /* FF3.6+ */
// background: -ms-linear-gradient(top, white 0%, #dcdcdc 100%);
// /* IE10+ */
// background: -o-linear-gradient(top, white 0%, #dcdcdc 100%);
// /* Opera 11.10+ */
// background: linear-gradient(to bottom, white 0%, #dcdcdc 100%);
// /* W3C */
// }
// .dataTables_wrapper .dataTables_paginate .paginate_button.disabled, .dataTables_wrapper .dataTables_paginate .paginate_button.disabled:hover, .dataTables_wrapper .dataTables_paginate .paginate_button.disabled:active {
// cursor: default;
// color: #666 !important;
// border: 1px solid transparent;
// background: transparent;
// box-shadow: none;
// }
// .dataTables_wrapper .dataTables_paginate .paginate_button:hover {
// color: white !important;
// border: 1px solid #111;
// background-color: #585858;
// background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #585858), color-stop(100%, #111));
// /* Chrome,Safari4+ */
// background: -webkit-linear-gradient(top, #585858 0%, #111 100%);
// /* Chrome10+,Safari5.1+ */
// background: -moz-linear-gradient(top, #585858 0%, #111 100%);
// /* FF3.6+ */
// background: -ms-linear-gradient(top, #585858 0%, #111 100%);
// /* IE10+ */
// background: -o-linear-gradient(top, #585858 0%, #111 100%);
// /* Opera 11.10+ */
// background: linear-gradient(to bottom, #585858 0%, #111 100%);
// /* W3C */
// }
// .dataTables_wrapper .dataTables_paginate .paginate_button:active {
// outline: none;
// background-color: #2b2b2b;
// background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #2b2b2b), color-stop(100%, #0c0c0c));
// /* Chrome,Safari4+ */
// background: -webkit-linear-gradient(top, #2b2b2b 0%, #0c0c0c 100%);
// /* Chrome10+,Safari5.1+ */
// background: -moz-linear-gradient(top, #2b2b2b 0%, #0c0c0c 100%);
// /* FF3.6+ */
// background: -ms-linear-gradient(top, #2b2b2b 0%, #0c0c0c 100%);
// /* IE10+ */
// background: -o-linear-gradient(top, #2b2b2b 0%, #0c0c0c 100%);
// /* Opera 11.10+ */
// background: linear-gradient(to bottom, #2b2b2b 0%, #0c0c0c 100%);
// /* W3C */
// box-shadow: inset 0 0 3px #111;
// }
.dataTables_wrapper .dataTables_paginate .ellipsis {
padding: 0 1em;
}
.dataTables_wrapper .dataTables_processing {
position: absolute;
top: 50%;
left: 50%;
width: 100%;
height: 40px;
margin-left: -50%;
margin-top: -25px;
padding-top: 20px;
text-align: center;
font-size: 1.2em;
background-color: white;
background: -webkit-gradient(linear, left top, right top, color-stop(0%, rgba(255, 255, 255, 0)), color-stop(25%, rgba(255, 255, 255, 0.9)), color-stop(75%, rgba(255, 255, 255, 0.9)), color-stop(100%, rgba(255, 255, 255, 0)));
background: -webkit-linear-gradient(left, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.9) 25%, rgba(255, 255, 255, 0.9) 75%, rgba(255, 255, 255, 0) 100%);
background: -moz-linear-gradient(left, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.9) 25%, rgba(255, 255, 255, 0.9) 75%, rgba(255, 255, 255, 0) 100%);
background: -ms-linear-gradient(left, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.9) 25%, rgba(255, 255, 255, 0.9) 75%, rgba(255, 255, 255, 0) 100%);
background: -o-linear-gradient(left, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.9) 25%, rgba(255, 255, 255, 0.9) 75%, rgba(255, 255, 255, 0) 100%);
background: linear-gradient(to right, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.9) 25%, rgba(255, 255, 255, 0.9) 75%, rgba(255, 255, 255, 0) 100%);
}
.dataTables_wrapper .dataTables_length,
.dataTables_wrapper .dataTables_filter,
.dataTables_wrapper .dataTables_info,
.dataTables_wrapper .dataTables_processing,
.dataTables_wrapper .dataTables_paginate {
color: #333;
}
.dataTables_wrapper .dataTables_scroll {
clear: both;
}
.dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody {
*margin-top: -1px;
-webkit-overflow-scrolling: touch;
}
.dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody > table > thead > tr > th, .dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody > table > thead > tr > td, .dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody > table > tbody > tr > th, .dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody > table > tbody > tr > td {
vertical-align: middle;
}
.dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody > table > thead > tr > th > div.dataTables_sizing,
.dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody > table > thead > tr > td > div.dataTables_sizing, .dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody > table > tbody > tr > th > div.dataTables_sizing,
.dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody > table > tbody > tr > td > div.dataTables_sizing {
height: 0;
overflow: hidden;
margin: 0 !important;
padding: 0 !important;
}
.dataTables_wrapper.no-footer .dataTables_scrollBody {
border-bottom: 1px solid #111;
}
.dataTables_wrapper.no-footer div.dataTables_scrollHead > table,
.dataTables_wrapper.no-footer div.dataTables_scrollBody > table {
border-bottom: none;
}
.dataTables_wrapper:after {
visibility: hidden;
display: block;
content: "";
clear: both;
height: 0;
}
@media screen and (max-width: 767px) {
.dataTables_wrapper .dataTables_info,
.dataTables_wrapper .dataTables_paginate {
float: none;
text-align: center;
}
.dataTables_wrapper .dataTables_paginate {
margin-top: 0.5em;
}
}
@media screen and (max-width: 640px) {
.dataTables_wrapper .dataTables_length,
.dataTables_wrapper .dataTables_filter {
float: none;
text-align: center;
}
.dataTables_wrapper .dataTables_filter {
margin-top: 0.5em;
}
}

View file

@ -0,0 +1,122 @@
[data-field="indexfield"] table.dataTable {text-align: left;}
[data-field="indexfield"] table.dataTable thead th, [data-field="indexfield"] table.dataTable thead td,
[data-field="indexfield"] table.dataTable tfoot th, [data-field="indexfield"] table.dataTable tfoot td {padding: 8px 10px}
[data-field="indexfield"] table.dataTable tbody tr { cursor: pointer; }
[data-field="indexfield"] table.dataTable thead .sorting,
[data-field="indexfield"] table.dataTable thead .sorting_asc,
[data-field="indexfield"] table.dataTable thead .sorting_desc,
[data-field="indexfield"] table.dataTable thead .sorting_asc_disabled,
[data-field="indexfield"] table.dataTable thead .sorting_desc_disabled {
background-size: 10px;
background-position: right 10px center;
}
[data-field="indexfield"] table.dataTable thead .sorting {
background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 19'><defs><style>.cls-1{fill:none;}</style></defs><path d='M5,2.3,7.77,7.1H2.23L5,2.3m0-2L.5,8.1h9L5,.3Z'/><path transform='translate(0,2)' d='M7.77,9.9,5,14.7,2.23,9.9H7.77m1.73-1H.5L5,16.7,9.5,8.9Z'/><rect class='cls-1' width='10' height='19'/></svg>");
}
[data-field="indexfield"] table.dataTable thead .sorting_asc {
background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 19'><defs><style>.cls-1{fill:none;}</style></defs><polygon points='1.37 7.6 5 1.3 8.63 7.6 1.37 7.6'/><path d='M5,2.3,7.77,7.1H2.23L5,2.3m0-2L.5,8.1h9L5,.3Z'/><rect class='cls-1' width='10' height='19'/></svg>");
}
[data-field="indexfield"] table.dataTable thead .sorting_desc {
background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 19'><defs><style>.cls-1{fill:none;}</style></defs><polygon transform='translate(0,2)' points='1.37 9.4 8.63 9.4 5 15.7 1.37 9.4'/><path transform='translate(0,2)' d='M7.77,9.9,5,14.7,2.23,9.9H7.77m1.73-1H.5L5,16.7,9.5,8.9Z'/><rect class='cls-1' width='10' height='19'/></svg>");
}
[data-field="indexfield"] table.dataTable thead .sorting_asc_disabled {
background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 19'><defs><style>.cls-1{fill:none;}</style></defs><path d='M5,2.3,7.77,7.1H2.23L5,2.3m0-2L.5,8.1h9L5,.3Z'/><rect class='cls-1' width='10' height='19'/></svg>");
}
[data-field="indexfield"] table.dataTable thead .sorting_desc_disabled {
background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 19'><defs><style>.cls-1{fill:none;}</style></defs><path transform='translate(0,2)' d='M7.77,9.9,5,14.7,2.23,9.9H7.77m1.73-1H.5L5,16.7,9.5,8.9Z'/><rect class='cls-1' width='10' height='19'/></svg>");
}
[data-field="indexfield"] table.dataTable {
background-color: white;
border: 2px solid #ddd;
border-collapse: collapse;
}
[data-field="indexfield"] table.dataTable thead th, [data-field="indexfield"] table.dataTable thead td {
border-bottom: 2px solid #ddd;
border-right: 1px solid #ddd;
}
[data-field="indexfield"] table.dataTable tfoot th, [data-field="indexfield"] table.dataTable tfoot td {
border-top: 2px solid #ddd;
border-right: 1px solid #ddd;
}
[data-field="indexfield"] table.dataTable tbody td {
border-right: 1px solid #ddd;
}
[data-field="indexfield"] table.dataTable tbody td:last-child {
text-align: center;
}
[data-field="indexfield"] .dataTables_filter {
margin-bottom: 1em;
}
[data-field="indexfield"] .dataTables_wrapper .dataTables_info,
[data-field="indexfield"] .dataTables_wrapper .dataTables_paginate {
padding-top: 1em;
user-select: none;
}
[data-field="indexfield"] .dataTables_wrapper .dataTables_paginate .paginate_button {
font-size: 1em;
font-weight: 600;
margin-left: 1em;
cursor: pointer;
outline: 0;
}
[data-field="indexfield"] .dataTables_wrapper .dataTables_paginate .paginate_button:hover,
[data-field="indexfield"] .dataTables_wrapper .dataTables_paginate .paginate_button.current {
color: #8dae28;
}
[data-field="indexfield"] .dataTables_wrapper .dataTables_paginate .paginate_button.disabled {
text-decoration: line-through;
pointer-events: none;
color: #ddd;
}
[data-field="indexfield"] .dataTables_wrapper .dataTables_paginate .ellipsis {
padding-right: 0;
}
[data-field="indexfield"] .dataTables_length select,
[data-field="indexfield"] .dataTables_filter input[type="search"] {
padding: .25em;
font-size: 1em;
line-height: 1.5em;
font-weight: 400;
border: 2px solid #ddd;
background: #fff;
-ms-appearance: none;
appearance: none;
border-radius: 0;
min-height: 2em;
}
[data-field="indexfield"] .dataTables_length select:focus,
[data-field="indexfield"] .dataTables_filter input[type="search"]:focus {
outline: 0;
border-color: #8dae28;
}
[data-field="indexfield"] .dataTable .btn:hover {
color: #8dae28;
}
[data-field="indexfield"] td.no-padding-cell {
padding: 0;
}
[data-field="indexfield"] td.center-cell {
text-align: center;
}

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,152 @@
(function($) {
var Indexfield = function (el) {
var element = $(el);
var table = element.find('table')
var columns = table.data('indexfield-columns');
var entriesapi = table.data('indexfield-entries');
var rows = table.data('indexfield-rows');
var order = table.data('indexfield-order');
var headers = Object.keys(columns).map(function (key) {
if ($.isPlainObject(columns[key])) {
return $('<th>' + columns[key].label + '</th>')
} else {
return $('<th>' + columns[key] + '</th>')
}
})
table.append(tableHead(headers, $('<thead></thead>')))
table.append(tableHead(headers, $('<tfoot></tfoot>')))
var defs = columnDefs(columns)
var table = table.DataTable({
columnDefs: defs,
pageLength: rows,
order: [[ 0, order ]],
ajax: {
url: entriesapi,
dataSrc: function (json) {
var formatted = Object.keys(json).map(function (k) {
var i = json[k]
var result = []
Object.keys(columns).forEach(function (key) {
/**
* 1. Check for key under content object (page fields)
* 2. Check for key under meta object (file fields)
* 3. Use name as fallback for title on files
* 4. Check for key under top level object
* 5. Return empty string if no value
*/
var item = i.content && i.content[key]
? i.content[key]
: i.meta && i.meta[key]
? i.meta[key]
: key === 'title' && !i.title && i.name
? i.name
: i[key]
? i[key]
: ''
result.push(item)
})
return result.concat([editButton(i.panelurl)])
})
return formatted
}
}
});
// click row to edit
table.on('click', 'tbody tr', function (e) {
var $target = $(e.target)
if (!$target.is('i') && !$target.is('a')) {
var $edit = $(e.currentTarget).find('.structure-edit-button')
if ($edit.length) $edit.get(0).click()
}
})
function editButton (editurl) {
return ' \
<a class="btn structure-edit-button" href="' + editurl + '"> \
<i class="icon fa fa-pencil"></i> \
</a> \
'
}
function tableHead (headers, $element) {
var $row = $('<tr></tr>')
headers.forEach(function ($header) {
$row.append($header.clone())
})
// edit col
$row.append($('<th width="18"></th>'))
return $element.append($row);
}
function columnDefs () {
// column defs handle custom column widths and classnames
var colCount = Object.keys(columns).length
var defs = [
{ orderable: false, targets: [ colCount ] }
]
Object.keys(columns).forEach(function (key, i) {
if (columns[key].width) {
defs.push({
width: columns[key].width,
targets: i
})
}
if (columns[key].class) {
defs.push({
className: columns[key].class,
targets: i
})
}
if ($.isPlainObject(columns[key]) && columns[key].hasOwnProperty('visible')) {
defs.push({
visible: columns[key].visible,
targets: i
})
}
if ($.isPlainObject(columns[key]) && columns[key].hasOwnProperty('sort')) {
defs.push({
orderable: columns[key].sort,
targets: i
})
}
})
return defs
}
};
$.fn.indexfield = function () {
return this.each(function () {
if ($(this).data('indexfield')) {
return $(this);
} else {
var indexfield = new Indexfield(this);
$(this).data('indexfield', indexfield);
return $(this);
}
});
};
})(jQuery);

View file

@ -0,0 +1,17 @@
<?php
require __DIR__ . DS . 'options.php';
class IndexFieldController extends Kirby\Panel\Controllers\Field {
// get entries for the current table
public function list_entries () {
$field = $this->field();
$data = Kirby\Panel\Form\IndexFieldOptions::build($field);
if ($field->filter()) {
$data = call_user_func($field->filter(), $data);
}
return response::json($data);
}
}

View file

@ -0,0 +1,87 @@
<?php
class IndexField extends BaseField {
static public $assets = [
'css' => [
'datatables.min.css',
'main.css'
],
'js' => [
'datatables.min.js',
'main.js'
]
];
public function __construct () {
$this->rows = 10;
$this->order = 'asc';
$this->type = 'index';
$this->options = [];
$this->icon = false;
}
public function routes () {
return array(
array(
'pattern' => 'list',
'method' => 'get',
'action' => 'list_entries'
)
);
}
public function subpagelinks () {
if (in_array($this->options, ['children', 'visibleChildren', 'invisibleChildren'])) {
return <<<HTML
<span class="hgroup-options shiv shiv-dark shiv-left">
<span class="hgroup-option-right">
<a href="{$this->page->url('subpages')}" title="Edit">
<i class="icon icon-left fa fa-pencil"></i><span>Edit</span>
</a>
<a href="{$this->page->url('add')}" title="+" shortcut="+" data-modal="true">
<i class="icon icon-left fa fa-plus-circle"></i><span>Add</span>
</a>
</span>
</span>
HTML;
}
}
public function label () {
if (!$this->label) return null;
$subpagelinks = '';
if (isset($this->options) && $subpagelinks = $this->subpagelinks()) {
if (!(isset($this->addedit) && !$this->addedit)) {
$subpagelinks = $subpagelinks;
}
}
return <<<HTML
<label class="label" for="{$this->id()}">
<h2 class="hgroup hgroup-single-line hgroup-compressed cf">
<span class="hgroup-title">{$this->i18n($this->label)}</span>
{$subpagelinks}
</h2>
</label>
HTML;
}
public function columns () {
return !empty($this->columns) ? $this->columns : [ 'title' => 'Title' ];
}
public function content () {
return tpl::load(__DIR__ . DS . 'template.php', array('field' => $this));
}
public function url ($action) {
return purl($this->model(), 'field/' . $this->name() . '/index/' . $action);
}
public function validate () {
return true;
}
}

View file

@ -0,0 +1,198 @@
<?php
namespace Kirby\Panel\Form;
use Collection;
use Str;
use Remote;
use V;
/**
* Largely based on Kirby\Panel\Form\FieldOptions
* Modified to only support query/method, and return collection object as array
* Also add panel edit urls to the resulting array
*/
class IndexFieldOptions {
public $field;
public $activepage;
public $options = array();
static public function build($field) {
$obj = new static($field);
return $obj->format();
}
public function __construct($field) {
$this->field = $field;
if($this->field->options == 'query') {
$this->options = $this->optionsFromQuery($this->field->query);
} else {
$this->options = $this->optionsFromPageMethod($this->field->page, $this->field->options);
}
}
public function optionsFromPageMethod($page, $method) {
// set active page (for use within format)
$this->activepage = $page;
if($page && $items = $this->items($page, $method)) {
return $items;
} else {
return array();
}
}
public function optionsFromQuery($query) {
// default query parameters
$defaults = array(
'page' => $this->field->page ? ($this->field->page->isSite() ? '/' : $this->field->page->id()) : '',
'fetch' => 'children',
'template' => false
);
// sanitize the query
if(!is_array($query)) {
$query = array();
}
// merge the default parameters with the actual query
$query = array_merge($defaults, $query);
// dynamic page option
// ../
// ../../ etc.
$page = $this->page($query['page']);
$items = $this->items($page, $query['fetch']);
if($query['template']) {
$items = $items->filter(function($item) use($query) {
return in_array(str::lower($item->intendedTemplate()), array_map('str::lower', (array)$query['template']));
});
}
// set active page (for use within format)
$this->activepage = $page;
return $items;
}
public function page($uri) {
if(str::startsWith($uri, '../')) {
if($currentPage = $this->field->page) {
$path = $uri;
while(str::startsWith($path, '../')) {
if($parent = $currentPage->parent()) {
$currentPage = $parent;
} else {
$currentPage = site();
}
$path = str::substr($path, 3);
}
if(!empty($path)) {
$currentPage = $currentPage->find($path);
}
$page = $currentPage;
} else {
$page = null;
}
} else if($uri == '/') {
$page = site();
} else {
$page = page($uri);
}
return $page;
}
public function sort($options, $sort) {
if(empty($sort)) return $options;
switch(strtolower($sort)) {
case 'asc':
asort($options);
break;
case 'desc':
arsort($options);
break;
}
return $options;
}
public function items($page, $method) {
if(!$page) return new Collection();
switch($method) {
case 'visibleChildren':
$items = $page->children()->published();
break;
case 'invisibleChildren':
$items = $page->children()->invisible();
break;
case 'visibleGrandchildren':
$items = $page->grandChildren()->published();
break;
case 'invisibleGrandchildren':
$items = $page->grandChildren()->invisible();
break;
case 'siblings':
$items = $page->siblings()->not($page);
break;
case 'visibleSiblings':
$items = $page->siblings()->not($page)->published();
break;
case 'invisibleSiblings':
$items = $page->siblings()->not($page)->invisible();
break;
case 'pages':
$items = site()->index();
$items = $items->sortBy('title', 'asc');
break;
case 'index':
$items = $page->index();
$items = $items->sortBy('title', 'asc');
break;
case 'children':
case 'grandchildren':
case 'files':
case 'images':
case 'documents':
case 'videos':
case 'audio':
case 'code':
case 'archives':
$items = $page->{$method}();
break;
default:
$items = new Collection();
}
return $items;
}
public function format () {
// add panel edit url to each item
return array_map(function ($item) {
if (isset($item['filename'])) {
$item['panelurl'] = panel()->urls()->index() . '/pages/' . $this->activepage->uri() . '/file/' . $item['filename'] . '/edit';
} else {
$item['panelurl'] = panel()->urls()->index() . '/pages/' . $item['id'] . '/edit';
}
return $item;
}, $this->options->toArray());
}
}

View file

@ -0,0 +1,12 @@
<div
data-field="indexfield"
>
<table
class="display"
width="100%"
data-indexfield-columns="<?php __(json_encode($field->columns())) ?>"
data-indexfield-entries="<?php __($field->url('list')) ?>"
data-indexfield-rows="<?php __($field->rows) ?>"
data-indexfield-order="<?php __($field->order) ?>"
></table>
</div>

View file

@ -0,0 +1,2 @@
<?php
$kirby->set('field', 'index', __DIR__ . '/fields/index');

View file

@ -0,0 +1,12 @@
{
"name": "kirby-index-field",
"description": "Kirby field for displaying pages as a datalist",
"author": "Jon Gacnik <https://github.com/jongacnik>",
"repository": {
"type": "git",
"url": "https://github.com/jongacnik/kirby-index-field"
},
"version": "2.1.0",
"type": "kirby-plugin",
"license": "MIT"
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 271 KiB

View file

@ -0,0 +1,189 @@
# Kirby Index Field
Kirby field which displays pages (or files) as a [datatable](https://datatables.net/).
This is useful for navigating large-ish sets of items with filtering and sorting. Enables Kirby to be used a little more like a database. Pairs nicely with [kirby-hidebar-field](https://github.com/jongacnik/kirby-hidebar-field).
![Preview](https://github.com/jongacnik/kirby-index-field/blob/master/preview.png?raw=true)
## Examples
Show an index of pages children:
```yaml
pageindex:
label: Items
type: index
options: children
```
Show an index of pages files:
```yaml
pageindex:
label: Items
type: index
options: files
```
## Options
Similar to Kirby's [Select Field](https://getkirby.com/docs/cheatsheet/panel-fields/select), you use the `options` parameter to specify what the index should be populated with. All Dynamic Options from the Select Field can be used:
Option | Description
--- | ---
children | Index of all children
visibleChildren | Index of all visible children
invisibleChildren | Index of all invisible children
grandchildren | Index of all grandchildren
visibleGrandchildren | Index of all visible grandchildren
invisibleGrandchildren | Index of all invisible grandchildren
siblings | Index of all siblings
visibleSiblings | Index of all visible siblings
invisibleSiblings | Index of all invisible siblings
index | Index of all descendants
pages | Index of all pages of the site
files | Index of all files of the page
images | Index of all images of the page
documents | Index of all documents of the page
videos | Index of all videos of the page
audio | Index of all audio files of the page
code | Index of all code files of the page
archives | Index of all archives of the page
## Query
The Index Field also supports a version of the Select Field `query` parameter to generate more complex indexes of pages/files:
```yaml
pageindex:
label: Items
type: index
options: query
query:
page: blog
fetch: children
template: article
```
Where `page` is the [uid](https://getkirby.com/docs/cheatsheet/page/uid) of the desired page, and `fetch` is one of the [`options`](#options) above.
## Columns
By default, only a Title column (showing a page `title` or file `filename`) will be shown. You specify what columns should appear using the `columns` parameter. The first column determines the initial sort.
```yaml
pageindex:
label: Items
type: index
options: children
columns:
title: Title
date: Date
uid: Slug
```
The key specifies which property of the [page/file json](https://getkirby.com/docs/cheatsheet/page/to-json) should be fetched. The value specifies the title of the column. The following example will show a column labeled **Title** and the property `title` from each item's json representation:
```yaml
title: Title
```
### Column Options:
You can set a few options on a per column basis.
#### Column Width
```yaml
columns:
title:
label: Title
width: 100
uid: Slug
```
#### Column Class
```yaml
columns:
title:
label: Title
class: classname
uid: Slug
```
#### Column Sort-ability
```yaml
columns:
title:
label: Title
sort: false
uid: Slug
```
#### Column Visibility
```yaml
columns:
title:
label: Title
visible: false
uid: Slug
```
## Filter Data
A custom filter can be applied to the data before it is put out as a json response. This is perfect if you need to modify some of the data for presentation, change columns, etc.
Create a simple plugin `site/plugins/mydatafilters/mydatafilters.php`:
```php
<?php
class MyDataFilters {
static function myfilterfunc($data) {
// filter data here
return $data;
}
}
```
Update field definition:
```yaml
pageindex:
label: Items
type: index
options: children
filter: MyDataFilters::myfilterfunc
columns:
title: Title
date: Date
uid: Slug
```
## Rows
Set the initial number of rows in the datatable:
```yaml
rows: 25
```
## Order
Set the initial sort order of the first column:
```yaml
order: desc
```
## Add/Edit Links
When showing an index of subpages (`children`, `visibleChildren` or `invisibleChildren`), Edit/Add links will appear next to the field label. You can disable these links using the `addedit` parameter:
```yaml
addedit: false
```
These links appear on an index of subpages so you are able to [hide the subpage](https://getkirby.com/docs/panel/blueprints/subpages-settings#hide-subpages) list in the left column of the panel, or [remove the left column](https://github.com/jongacnik/kirby-hidebar-field) entirely.