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,50 @@
# Kirby Images <a href="https://www.paypal.me/medienbaecker"><img width="99" src="http://www.medienbaecker.com/beer.png" alt="Buy me a beer" align="right"></a>
The `images` field can be used to edit groups of images very easily by drag-and-drop. Simply take an image from the sidebar and drop it on the field. You can also reorder images inside the field, not linked to the regular order.
## Installation
Put the `kirby-images` folder into your `site/plugins` folder and rename it to `images`.
## Example
![Preview](https://user-images.githubusercontent.com/7975568/29234770-9f686324-7ef9-11e7-8c37-f53e2848c846.gif)
```yaml
slideshow:
label: Slideshow
type: images
```
## Template
To display an image slideshow with the selected images you can use a code like this:
```php
<div class="slider">
<?php foreach($page->slideshow()->yaml() as $image): ?>
<?php if($image = $page->image($image)): ?>
<?= $image->crop(1200,500)->html(); ?>
<?php endif ?>
<?php endforeach; ?>
</div>
```
## Drag between multiple instances
You can even move images between multiple instances of the `images` field like this:
![Drag](https://cloud.githubusercontent.com/assets/11269635/25747374/940bc790-31a7-11e7-8dcd-e70038dac2cc.gif)
## Options
### Limit the number of images
As of Images 1.0.4 you can limit the number of images:
```yaml
slideshow:
label: Slideshow
type: images
limit: 4
```

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

View file

@ -0,0 +1,227 @@
.field-with-images .images-add-button {
cursor: pointer; }
.field-with-images .images-add-button.open {
color: black; }
.field-with-images.limit-reached .images-add-button {
display: none; }
.field-with-images .images-limit {
font-weight: 400;
color: #777; }
.field-with-images .images-dropdown {
display: none;
background: white;
box-shadow: rgba(0, 0, 0, 0.2) 0 2px 10px;
position: absolute;
right: 0;
margin-top: 8px;
width: 280px;
max-height: 261px;
overflow-y: auto;
z-index: 200;
border-top: 2px solid black; }
.field-with-images .images-dropdown:after {
display: none; }
.field-with-images .images-dropdown.open {
display: block; }
.field-with-images .images-dropdown .filter-wrap {
position: relative; }
.field-with-images .images-dropdown .filter-wrap .icon {
position: absolute;
left: 20px;
top: 50%;
transform: translateY(-50%);
color: #777; }
.field-with-images .images-dropdown input.filter {
box-sizing: border-box;
border: none;
border-bottom: 1px solid #efefef;
width: 100%;
padding: 1em;
padding-left: 55px; }
.field-with-images .images-dropdown input.filter:focus {
outline: none; }
.field-with-images .images-dropdown a {
display: block;
padding: .5em 1em .5em .5em;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
font-weight: normal;
border-bottom: 1px solid #efefef; }
.field-with-images .images-dropdown a:last-child {
border-bottom: none; }
.field-with-images .images-dropdown a:hover {
color: #777;
cursor: pointer; }
.field-with-images .images-dropdown a.focused {
background-color: #efefef; }
.field-with-images .images-dropdown a.disabled, .field-with-images .images-dropdown a.filtered {
display: none; }
.field-with-images .images-dropdown a img {
width: 40px;
display: inline-block;
vertical-align: middle;
margin-right: .5em; }
.field-with-images .images-dropdown a span.image {
vertical-align: middle; }
.field-with-images .images-dropdown span.no-more-images, .field-with-images .images-dropdown span.no-images-found {
padding: 0 1em;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
font-weight: normal;
display: none;
height: 56px;
line-height: 56px; }
.field-with-images .images-dropdown span.no-more-images.da, .field-with-images .images-dropdown span.no-images-found.da {
display: block; }
.field-with-images .images-dropdown span.no-more-images, .field-with-images .images-dropdown span.no-images-found {
padding: 0 1em;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
font-weight: normal;
display: none;
height: 56px;
line-height: 56px; }
.field-with-images .images-dropdown span.no-more-images.da, .field-with-images .images-dropdown span.no-images-found.da {
display: block; }
.field-with-images .images-dropdown span.add-all {
padding: 0 1em;
display: block;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
font-weight: normal;
height: 35px;
line-height: 35px;
background: black;
color: white;
text-align: center;
cursor: pointer; }
.field-with-images .images-dropdown span.add-all i.icon {
padding-right: .5em; }
.field-with-images .images-dropdown span.add-all:hover {
color: rgba(255, 255, 255, 0.75); }
.field-with-images .imagesgrid .empty {
box-sizing: border-box;
padding: 1.5em;
padding-right: 210px;
padding-right: calc(162px + 3em);
background: #ddd;
overflow: hidden;
position: relative;
min-height: 111px; }
.field-with-images .imagesgrid .empty .no-images {
display: block;
margin-bottom: 1em; }
.field-with-images .imagesgrid .empty .tutorial {
display: block;
width: 162px;
position: absolute;
right: 1.5em;
top: 1.5em; }
.field-with-images .imagesgrid .empty .help-link {
border-bottom: 2px solid #aaa; }
.field-with-images .imagesgrid .empty .help-link:hover {
border-color: #000; }
.field-with-images .imagesgrid.filled {
margin-bottom: -1.5em; }
.field-with-images .imagesgrid.filled .empty {
display: none; }
.field-with-images .imagesgrid .imagesgrid-inner {
display: block;
display: grid;
grid-gap: 0 1.5em;
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
overflow: hidden; }
.field-with-images .imagesgrid .images-item {
display: none;
margin-bottom: 1.5em;
min-width: 0;
overflow: hidden; }
.field-with-images .imagesgrid .images-item.selected {
display: block; }
.field-with-images .imagesgrid .images-item figure {
background: white; }
.field-with-images .imagesgrid .images-item .images-preview {
display: block;
width: 100%;
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyFpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNS1jMDE0IDc5LjE1MTQ4MSwgMjAxMy8wMy8xMy0xMjowOToxNSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIE1hY2ludG9zaCIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDpCOTdEOEI3OUE3MDMxMUUzOEIxNEZERTM0N0EzRjlGMSIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDpCOTdEOEI3QUE3MDMxMUUzOEIxNEZERTM0N0EzRjlGMSI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOkI5N0Q4Qjc3QTcwMzExRTM4QjE0RkRFMzQ3QTNGOUYxIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOkI5N0Q4Qjc4QTcwMzExRTM4QjE0RkRFMzQ3QTNGOUYxIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+jGcG/wAAAAlQTFRF////zMzMzc3NCvMx6wAAACJJREFUeNpiYGRkYgQBBhgYIAGEBCO6SpIFmKCADDMAAgwATVgAkU8MrdIAAAAASUVORK5CYII=);
text-align: center; }
.field-with-images .imagesgrid .images-item .images-preview img {
display: inline-block;
vertical-align: top; }
.field-with-images .imagesgrid .images-item .images-info {
line-height: 1.5em;
border-bottom: 1px solid #ddd; }
.field-with-images .imagesgrid .images-item .images-info a {
display: block;
padding: 1em 1.5em; }
.field-with-images .imagesgrid .images-item .images-info span {
display: block; }
.field-with-images .imagesgrid .images-item .images-options .btn {
width: 50%;
display: inline-block;
vertical-align: top;
box-sizing: border-box;
padding: .75em 1.5em;
text-align: center; }
.field-with-images .imagesgrid .images-item .images-options .btn:first-child {
border-right: 1px solid #ddd; }
.field-with-images .imagesgrid .images-item.over figure {
outline: 2px solid black;
outline-offset: -2px;
position: relative; }
.field-with-images .imagesgrid .images-item.over figure .images-preview, .field-with-images .imagesgrid .images-item.over figure .images-info, .field-with-images .imagesgrid .images-item.over figure .images-options {
opacity: .25; }
.field-with-images .imagesgrid .images-item.over figure:after {
content: '\f0a9';
font-family: FontAwesome;
font-size: 1.5em;
display: block;
position: absolute;
top: 50%;
left: 50%;
transform: translateY(-50%) translateX(-50%); }
.field-with-images .imagesgrid .add {
box-sizing: border-box;
display: none;
text-align: center;
margin-bottom: 1.5em; }
.field-with-images .imagesgrid .add.over {
display: block; }
.field-with-images .imagesgrid .add .inner {
color: black;
box-sizing: border-box;
position: relative;
border: 2px solid black; }
.field-with-images .imagesgrid .add .inner:after {
content: '\f055';
font-family: FontAwesome;
font-size: 1.5em;
display: block;
position: absolute;
top: 50%;
left: 50%;
transform: translateY(-50%) translateX(-50%); }
@media screen and (max-width: 800px) {
.field-with-images .imagesgrid .empty {
min-height: 0;
padding: 1.5em; }
.field-with-images .imagesgrid .empty .no-images {
margin: 0;
font-weight: normal; }
.field-with-images .imagesgrid .empty .tutorial {
display: none; }
.field-with-images .imagesgrid .empty .dragdrop-help {
display: none; } }

View file

@ -0,0 +1,7 @@
{
"version": 3,
"mappings": "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",
"sources": ["style.scss"],
"names": [],
"file": "style.css"
}

View file

@ -0,0 +1,310 @@
.field-with-images {
.images-add-button {
cursor: pointer;
&.open {
color: black;
}
}
&.limit-reached .images-add-button {
display: none;
}
.images-limit {
font-weight: 400;
color: #777;
}
.images-dropdown {
display: none;
background: white;
box-shadow: rgba(0,0,0,.2) 0 2px 10px;
position: absolute;
right: 0;
margin-top: 8px;
width: 280px;
max-height: 261px;
overflow-y: auto;
z-index: 200;
border-top: 2px solid black;
&:after {
display: none;
}
&.open {
display: block;
}
.filter-wrap {
position: relative;
.icon {
position: absolute;
left: 20px;
top: 50%;
transform: translateY(-50%);
color: #777;
}
}
input.filter {
box-sizing: border-box;
border: none;
border-bottom: 1px solid #efefef;
width: 100%;
padding: 1em;
padding-left: 55px;
&:focus {
outline: none;
}
}
a {
display: block;
padding: .5em 1em .5em .5em;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
font-weight: normal;
border-bottom: 1px solid #efefef;
&:last-child {
border-bottom: none;
}
&:hover {
color: #777;
cursor: pointer;
}
&.focused {
background-color: #efefef;
}
&.disabled, &.filtered {
display: none;
}
img {
width: 40px;
display: inline-block;
vertical-align: middle;
margin-right: .5em;
}
span.image {
vertical-align: middle;
}
}
span.no-more-images, span.no-images-found {
padding: 0 1em;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
font-weight: normal;
display: none;
height: 56px;
line-height: 56px;
&.da {
display: block;
}
}
span.no-more-images, span.no-images-found {
padding: 0 1em;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
font-weight: normal;
display: none;
height: 56px;
line-height: 56px;
&.da {
display: block;
}
}
span.add-all {
padding: 0 1em;
display: block;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
font-weight: normal;
height: 35px;
line-height: 35px;
background: black;
color: white;
text-align: center;
cursor: pointer;
i.icon {
padding-right: .5em;
}
&:hover {
color: rgba(255,255,255,.75);
}
}
}
.imagesgrid {
.empty {
box-sizing: border-box;
padding: 1.5em;
padding-right: 210px;
padding-right: calc(162px + 3em);
background: #ddd;
overflow: hidden;
position: relative;
min-height: 111px;
.no-images {
display: block;
margin-bottom: 1em;
}
.tutorial {
display: block;
width: 162px;
position: absolute;
right: 1.5em;
top: 1.5em;
}
.help-link {
border-bottom: 2px solid #aaa;
&:hover {
border-color: #000;
}
}
}
&.filled {
margin-bottom: -1.5em;
.empty {
display: none;
}
}
.imagesgrid-inner {
display: block;
display: grid;
grid-gap: 0 1.5em;
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr) );
overflow: hidden;
}
.images-item {
display: none;
margin-bottom: 1.5em;
min-width: 0;
overflow: hidden;
&.selected {
display: block;
}
figure {
background: white;
}
.images-preview {
display: block;
width: 100%;
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyFpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNS1jMDE0IDc5LjE1MTQ4MSwgMjAxMy8wMy8xMy0xMjowOToxNSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIE1hY2ludG9zaCIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDpCOTdEOEI3OUE3MDMxMUUzOEIxNEZERTM0N0EzRjlGMSIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDpCOTdEOEI3QUE3MDMxMUUzOEIxNEZERTM0N0EzRjlGMSI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOkI5N0Q4Qjc3QTcwMzExRTM4QjE0RkRFMzQ3QTNGOUYxIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOkI5N0Q4Qjc4QTcwMzExRTM4QjE0RkRFMzQ3QTNGOUYxIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+jGcG/wAAAAlQTFRF////zMzMzc3NCvMx6wAAACJJREFUeNpiYGRkYgQBBhgYIAGEBCO6SpIFmKCADDMAAgwATVgAkU8MrdIAAAAASUVORK5CYII=);
text-align: center;
img {
display: inline-block;
vertical-align: top;
}
}
.images-info {
line-height: 1.5em;
border-bottom: 1px solid #ddd;
a {
display: block;
padding: 1em 1.5em;
}
span {
display: block;
}
}
.images-options {
.btn {
width: 50%;
display: inline-block;
vertical-align: top;
box-sizing: border-box;
padding: .75em 1.5em;
text-align: center;
&:first-child {
border-right: 1px solid #ddd;
}
}
}
&.over {
figure {
outline: 2px solid black;
outline-offset: -2px;
position: relative;
.images-preview, .images-info, .images-options {
opacity: .25;
}
&:after {
content: '\f0a9';
font-family: FontAwesome;
font-size: 1.5em;
display: block;
position: absolute;
top: 50%;
left: 50%;
transform: translateY(-50%) translateX(-50%);
}
}
}
}
.add {
box-sizing: border-box;
display: none;
text-align: center;
margin-bottom: 1.5em;
&.over {
display: block;
}
.inner {
color: black;
box-sizing: border-box;
position: relative;
border: 2px solid black;
&:after {
content: '\f055';
font-family: FontAwesome;
font-size: 1.5em;
display: block;
position: absolute;
top: 50%;
left: 50%;
transform: translateY(-50%) translateX(-50%);
}
}
}
}
}
@media screen and (max-width: 800px) {
.field-with-images .imagesgrid .empty {
min-height: 0;
padding: 1.5em;
.no-images {
margin: 0;
font-weight: normal;
}
.tutorial {
display: none;
}
.dragdrop-help {
display: none;
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

View file

@ -0,0 +1,306 @@
(function($) {
$.fn.images = function() {
return this.each(function() {
var field = $(this);
var fieldname = 'images';
if(field.data( fieldname )) {
return true;
} else {
field.data( fieldname, true );
}
field.find("input.filter").on('input change', function() {
filter = $(this).val();
field.find(".images-dropdown .no-images-found").removeClass("da");
if(filter != "") {
$.expr[':'].Contains = function(a, i, m) {
return $(a).text().toUpperCase()
.indexOf(m[3].toUpperCase()) >= 0;
};
field.find(".images-dropdown a").addClass("filtered");
field.find(".images-dropdown a .image:Contains('" + filter + "')").not("disabled").closest("a").removeClass("filtered");
if (field.find(".images-dropdown a").not(".filtered").length === 0) {
field.find(".images-dropdown .no-images-found").addClass("da");
}
}
else {
field.find(".images-dropdown a").removeClass("filtered");
}
});
field.find("input.filter").keydown(function(e){
// UP
if (e.keyCode == 38) {
if (field.find(".images-dropdown a.focused").length) {
field.find(".images-dropdown a.focused").removeClass("focused").prevAll("a").not(".filtered").not(".disabled").first().addClass("focused");
}
else {
field.find(".images-dropdown a").removeClass("focused");
field.find(".images-dropdown a").not(".filtered").not(".disabled").last().addClass("focused");
}
}
// DOWN
if (e.keyCode == 40) {
if (field.find(".images-dropdown a.focused").length) {
field.find(".images-dropdown a.focused").removeClass("focused").nextAll("a").not(".filtered").not(".disabled").first().addClass("focused");
}
else {
field.find(".images-dropdown a").removeClass("focused");
field.find(".images-dropdown a").not(".filtered").not(".disabled").first().addClass("focused");
}
}
// ENTER
if (e.keyCode == 13) {
field.find(".images-dropdown a.focused").click();
field.find(".images-dropdown a").removeClass("focused");
return false;
}
});
function checkLimit() {
if (field.data("limit")) {
var imagesLimit = field.data("limit");
var imagesCount = field.find(".images-item.selected").length;
field.find(".images-limit").html("(" + imagesCount + "/" + imagesLimit + ")");
if (imagesCount >= imagesLimit) {
field.addClass("limit-reached");
}
else {
field.removeClass("limit-reached");
}
}
}
checkLimit();
function noover() {
field.find(".add").removeClass("over");
field.find(".images-item").removeClass("over");
}
function reset() {
if (field.find(".images-item.selected").length) {
field.find(".imagesgrid").addClass("filled");
}
else {
field.find(".imagesgrid").removeClass("filled");
}
field.find(".images-dropdown").removeClass("open");
field.find(".images-add-button").removeClass("open");
if (field.find('.images-dropdown a').not(".disabled").length > 0) {
field.find('.images-dropdown .no-more-images').removeClass("da");
field.find('.filter-wrap').show();
field.find('span.add-all').show();
}
else {
field.find('.images-dropdown .no-more-images').addClass("da");
field.find('.filter-wrap').hide();
field.find('span.add-all').hide();
}
checkLimit();
};
reset();
function write() {
field.find("input.images").val("").trigger('change');
if (field.find(".images-item.selected").length > 1) {
filenames = new Array();
field.find(".images-item.selected").each(function() {
filenames.push($(this).data("image"));
});
filenames = "- " + filenames.join("\n- ");
field.find("input.images").val(filenames).trigger('change');
}
else {
field.find("input.images").val(field.find(".images-item.selected").data("image")).trigger('change');
}
field.closest('form').trigger('keep');
}
function select(filename) {
var file = field.find(".images-item[data-image='" + filename + "']");
file.insertBefore(field.find(".add")).addClass("selected");
field.find(".images-dropdown a[data-filename='" + filename + "']").addClass("disabled");
reset();
write();
noover();
};
function selectAll() {
var file = field.find(".images-item");
file.insertBefore(field.find(".add")).addClass("selected");
field.find(".images-dropdown a").addClass("disabled");
reset();
write();
noover();
};
function remove(filename) {
field.find(".images-item[data-image='" + filename + "']").removeClass("selected");
field.find(".images-dropdown a[data-filename='" + filename + "']").removeClass("disabled");
reset();
noover();
write();
};
field.find(".images-item .btn.remove").on("click", function () {
if (!$(this).is(".ui-sortable-helper .btn")) {
var filename = $(this).closest(".images-item").data("image");
remove(filename);
}
return false;
});
field.find(".images-add-button").on("click", function(e) {
e.stopPropagation();
field.find(".images-dropdown").toggleClass("open");
field.find(".images-add-button").toggleClass("open");
field.find("input.filter").focus();
$(document).click(function(e) {
if ($(e.target).closest('.images-dropdown').length === 0) {
field.find("input.filter").val("");
field.find("input.filter").trigger("change");
field.find("input.filter").blur();
field.find(".images-dropdown").removeClass("open");
field.find(".images-add-button").removeClass("open");
}
});
});
field.find(".help-link").on("click", function(e) {
field.find(".images-add-button").click();
return false;
});
field.find(".images-dropdown a").on("click", function(e) {
if (!field.hasClass("limit-reached")) {
field.find("input.filter").val("");
field.find("input.filter").trigger("change");
select($(this).find(".image").text());
field.find(".images-dropdown").removeClass("open");
field.find(".images-add-button").removeClass("open");
}
});
field.find(".images-dropdown .add-all").on("click", function(e) {
if (!field.hasClass("limit-reached") && !(field.find(".images-item.selected").length + field.find(".images-dropdown a").not(".disabled").length > field.data("limit"))) {
field.find("input.filter").val("");
field.find("input.filter").trigger("change");
selectAll();
field.find(".images-dropdown").removeClass("open");
field.find(".images-add-button").removeClass("open");
}
});
var files = field.find('.imagesgrid');
var sortable = files.find('.sortable');
var items = files.find('.images-item');
var api = files.data('api');
if(sortable.find('.images-item').length > 1) {
sortable.sortable({
tolerance: "pointer",
revert: 100,
handle: "figure",
items: ".selected",
update: function() {
write();
}
}).disableSelection();
}
field.find('.field-content').droppable({
tolerance: "pointer",
hoverClass: 'over',
accept:
function (elem) {
if ($('.sidebar').has(elem).length) {
return true;
}
else if (!$(this).has(elem).length && elem.hasClass("images-item")) {
return true
}
},
drop: function(e, ui) {
field.find(".add").removeClass("over");
field.find(".images-item").removeClass("over");
var droppedImage = ui.draggable.data('helper');
if (!field.hasClass("limit-reached")) {
if (ui.draggable.hasClass("images-item")) {
otherField = ui.draggable.closest(".field-with-images");
otherField.find(".images-dropdown a[data-filename='" + droppedImage + "']").removeClass("disabled");
if (otherField.find(".selected").length <= 2) {
otherField.find(".imagesgrid").removeClass("filled");
}
ui.draggable.removeClass("selected");
otherField.find("input.images").val("");
if (otherField.find(".images-item.selected").length > 1) {
filenames = new Array();
otherField.find(".images-item.selected").each(function() {
filenames.push($(this).data("image"));
});
filenames = "- " + filenames.join("\n- ");
otherField.find("input.images").val(filenames);
}
else {
otherField.find("input.images").val(otherField.find(".images-item.selected").data("image"));
}
otherField.closest('form').trigger('keep');
}
select(droppedImage);
}
},
over: function(e, ui) {
var droppableImage = field.find(".images-item[data-image='" + ui.draggable.data('helper') + "']");
if (field.hasClass("limit-reached")) {
}
else if (droppableImage.hasClass("selected")) {
droppableImage.addClass("over");
}
else {
var visibleItem = field.find(".images-item.selected figure");
if (visibleItem.length) {
var height = visibleItem.height() - 4;
}
else {
var invisibleItem = field.find(".images-item").first();
invisibleItem.addClass("selected");
var height = invisibleItem.find("figure").height() - 4;
invisibleItem.removeClass("selected");
}
field.find(".add .inner").height(height);
field.find(".add").addClass("over");
}
field.find(".imagesgrid").addClass("filled");
},
out: function(e, ui) {
noover();
reset();
}
});
});
};
})(jQuery);

View file

@ -0,0 +1,16 @@
<?php
function imagesTranslation($string) {
$imagesTranslations = require __DIR__ . DS . 'translations.php';
$language = substr( site()->user()->language(), 0, 2 );
if (!array_key_exists($language, $imagesTranslations)) {
$language = 'en';
}
$imagesTranslation = $imagesTranslations[$language];
if(array_key_exists($string, $imagesTranslation)) {
$string = $imagesTranslation[$string];
}
return $string;
}

View file

@ -0,0 +1,91 @@
<?php
require_once(__DIR__.DS.'helper.php');
class imagesField extends BaseField {
static public $fieldname = 'images';
static public $assets = array(
'js' => array(
'script.js'
),
'css' => array(
'style.css'
)
);
public function input() {
$html = tpl::load( __DIR__ . DS . 'template.php', $data = array(
'field' => $this,
'page' => $this->page()
));
return $html;
}
public function element() {
$element = parent::element();
$element->data('field', self::$fieldname);
$element->data('limit', $this->limit());
$element->addClass('field-with-images');
return $element;
}
public function value() {
$value = parent::value();
return yaml::decode($value);
}
public function label() {
return null;
}
public function headline() {
$select = '<div class="images-dropdown">';
if ($this->page()->hasImages()) {
$select .= '<div class="filter-wrap">';
$select .= '<i class="icon fa fa-search"></i>';
$select .= '<input type="text" class="filter" placeholder="' . imagesTranslation('search') . '"/>';
$select .= '</div>';
$select .= '<span class="no-images-found">' . imagesTranslation('noImagesFound') . '</span>';
$select .= '<span class="no-more-images">' . imagesTranslation('noMoreImages') . '</span>';
}
else {
$select .= '<span class="no-more-images no-images">' . imagesTranslation('noImages') . '</span>';
}
foreach ($this->page()->images() as $image) {
$disabled = "";
if (in_array($image->filename(), $this->value())) $disabled = "disabled";
$select .= '<a class="' . $disabled . '" data-filename="' . $image->filename() . '">';
$select .= $image->crop(75,75)->html();
$select .= '<span class="image">' . $image->filename() . '</span>';
$select .= '</a>';
}
$select .= '<span class="add-all">';
$select .= '<i class="icon fa fa-plus-square"></i>';
$select .= imagesTranslation('addAll') . '</span>';
$select .= "</div>";
$add = new Brick('div');
$add->html('<i class="icon icon-left fa fa-plus-circle"></i>' . imagesTranslation('select'));
$add->addClass('images-add-button label-option');
if(!$this->label) {
$this->label = '&nbsp;';
}
if (isset($this->limit)) {
$this->label = $this->label . ' <span class="images-limit">' . '(1/3)' . '</span>';
}
$label = parent::label();
$label->addClass('images-label');
$label->append($add);
$label->append($select);
return $label;
}
}

View file

@ -0,0 +1,93 @@
<?php require_once(__DIR__.DS.'helper.php'); ?>
<?php echo $field->headline() ?>
<?php
if ($field->value()) {
$fieldImages = $field->value();
}
else {
$fieldImages = array();
}
$pageImages = array();
foreach ($page->images() as $image) {
$pageImages[] = $image->filename();
}
foreach ($pageImages as $pageImage) {
if (in_array($pageImage, $fieldImages)) {
continue;
}
$fieldImages[] = $pageImage;
}
?>
<div class="imagesgrid" data-api="<?php __($page->url('files')) ?>">
<div class="empty">
<span class="no-images"><a href="#" class="help-link"><?= imagesTranslation('nothingAdded') ?></a></span>
<span class="dragdrop-help"><?= imagesTranslation('help') ?></span>
<img class="tutorial" src="<?= url('assets/plugins/images/images/images.gif') ?>" />
</div>
<div class="imagesgrid-inner sortable">
<?php
$valueImages = array();
foreach($fieldImages as $f):
$file = $page->image($f);
if (!$file) continue;
if(in_array($f, $field->value())) $valueImages[] = $f;
?>
<div class="images-item <?php e(in_array($file->filename(), $field->value()), 'selected') ?>" data-image="<?php __($file->filename()) ?>" data-helper="<?php __($file->filename()) ?>">
<figure title="<?php __($file->filename()) ?>" class="images-figure">
<a class="images-preview images-preview-is-<?php __($file->type()) ?>" href="<?php __($file->url('edit')) ?>">
<img src="<?php __($file->crop(400, 266)->url()) ?>" alt="<?php __($file->filename()) ?>">
</a>
<figcaption class="images-info">
<a href="<?php __($file->url('edit')) ?>">
<span class="images-name cut"><?php __($file->filename()) ?></span>
<span class="images-meta marginalia cut"><?php __($file->niceSize()) ?></span>
</a>
</figcaption>
<nav class="images-options">
<a class="btn btn-with-icon" href="<?php __($file->url('edit')) ?>">
<?php i('pencil', 'left') ?>
</a><a data-modal class="btn btn-with-icon remove" href="#remove">
<?php i('minus-circle', 'left') ?>
</a>
</nav>
</figure>
</div>
<?php endforeach ?>
<div class="add">
<div class="inner">
</div>
</div>
</div>
</div>
<?php
if (count($valueImages) > 1) {
$valueImages = "- " . implode("\n- ", $valueImages);
}
elseif (count($valueImages) == 0) {
$valueImages = "";
}
else {
$valueImages = $valueImages[0];
}
?>
<input class="images" type="hidden" name="<?= $field->name() ?>" value="<?= $valueImages ?>">

View file

@ -0,0 +1,70 @@
<?php
return [
'en' => [
'noImages' => 'This page has no images',
'noMoreImages' => 'This page has no more images',
'nothingAdded' => 'No images selected',
'help' => 'Select an image or use drag and drop',
'select' => 'Select image',
'search' => 'Filter images...',
'noImagesFound' => 'No images found',
'addAll' => 'Add all images'
],
'de' => [
'noImages' => 'Diese Seite hat keine Bilder',
'noMoreImages' => 'Diese Seite hat keine weiteren Bilder',
'nothingAdded' => 'Keine Bilder ausgewählt',
'help' => 'Bild auswählen oder via Drag &amp; Drop ablegen',
'select' => 'Bild auswählen',
'search' => 'Bilder filtern...',
'noImagesFound' => 'Keine Bilder gefunden',
'addAll' => 'Alle Bilder hinzufügen'
],
'fr' => [
'noImages' => 'Cette page na pas dimage',
'noMoreImages' => 'Cette page na pas dautre image',
'nothingAdded' => 'Aucune image sélectionnée',
'help' => 'Sélectionner une image ou lajouter par glisser-déposer',
'select' => 'Sélectionner une image',
'search' => 'Filtrer les images…',
'noImagesFound' => 'Aucune image trouvée'
],
'nl' => [
'noImages' => 'Deze pagina heeft geen afbeeldingen',
'noMoreImages' => 'Deze pagina heeft geen afbeeldingen meer',
'nothingAdded' => 'Geen afbeelding geselecteerd',
'help' => 'Selecteer een afbeelding of gebruik drag &amp; drop',
'select' => 'Selecteer afbeelding',
'search' => 'Filter afbeeldingen...',
'noImagesFound' => 'Geen afbeeldingen gevonden'
],
'pt' => [
'noImages' => 'Esta página não possui imagens',
'noMoreImages' => 'Esta página não possui mais imagens',
'nothingAdded' => 'Nenhuma imagem selecionada',
'help' => 'Selecione uma imagem ou arraste e solte a partir da barra lateral',
'select' => 'Selecionar imagem',
'search' => 'Filtrar imagens...',
'noImagesFound' => 'Nenhuma imagem encontrada',
'addAll' => 'Adicionar todas as imagens'
],
'sv' => [
'noImages' => 'Denna sida har inga bilder',
'noMoreImages' => 'Denna sida har inga ytterligare bilder',
'nothingAdded' => 'Inga bilder valda',
'help' => 'Välj en bild eller använd dra och släpp',
'select' => 'Välj bild',
'search' => 'Filtrera bilder...',
'noImagesFound' => 'Inga bilder hittades'
],
'it' => [
'noImages' => 'Questa pagina non ha immagini',
'noMoreImages' => 'Questa pagina non ha altre immagini',
'nothingAdded' => 'Nessuna immagine selezionata',
'help' => 'Seleziona un\'immagine o trascinala dal pannello laterale',
'select' => 'Seleziona immagine',
'search' => 'Filtra immagini...',
'noImagesFound' => 'Nessuna immagine trovata',
'addAll' => 'Aggiungi tutte le immagini'
]
];

View file

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

View file

@ -0,0 +1,8 @@
{
"name": "images",
"description": "Images Field",
"author": "Thomas Günther <mail@medienbaecker.com>",
"version": "1.0.11",
"type": "kirby-plugin",
"license": "MIT"
}