Skip to content

Commit

Permalink
🎉 Initial version
Browse files Browse the repository at this point in the history
  • Loading branch information
olach committed Aug 11, 2017
0 parents commit c1c7954
Show file tree
Hide file tree
Showing 7 changed files with 439 additions and 0 deletions.
112 changes: 112 additions & 0 deletions assets/css/relationship.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
/* Field wrapper: */
.relationship-field {
display: flex;
flex-wrap: wrap;
border: 1px solid #ddd;
background-color: white;
}

/* Default styling for both lists: */
.relationship-list {
flex: 1 0 200px;
overflow-x: hidden;
overflow-y: scroll;
-webkit-overflow-scrolling: touch;
height: 13em;
margin: 0;
padding: 0.5em;
border: 1px solid #ddd;
background-color: white;
list-style: none;
}

/* The list with all unselected items should be hidden: */
.relationship-list--unselected {
display: none;
}

/* Reset native button styles: */
.relationship-list button {
border: none;
background: none;
margin: 0;
padding: 0;
color: inherit;
}

.relationship-list button:not([disabled]) {
cursor: pointer;
}

/* Default styling for all list items: */
.relationship-list--available button,
.relationship-list--selected li {
position: relative;
padding: 5px 2em 5px 7px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}

/* List with available items: */
.relationship-list--available {
background-color: #f7f7f7;
}

.relationship-list--available button {
display: block;
width: 100%;
text-align: left;
}

.relationship-list--available button:not([disabled]):hover,
.relationship-list--available button:not([disabled]):focus {
background-color: rgba(0, 0, 0, 0.075);
}

.relationship-list--available button[disabled] {
color: #777;
}

.relationship-list--available .icon-add {
position: absolute;
right: 0.5em;
}

.relationship-list--available button[disabled] .icon-add {
display: none;
}

/* Selected list items: */
.relationship-list--selected li {
padding-right: 2em;
cursor: move;
}

.relationship-list--selected li input[type="checkbox"] {
display: none;
}

/* List item during sorting: */
.relationship-list--selected li.ui-sortable-helper {
background-color: white;
border-radius: 2px;
box-shadow: 0px 5px 20px rgba(0, 0, 0, 0.1);
transition: box-shadow 150ms ease-out;
}

/* Placeholder item when sorting: */
.relationship-list--selected li.ui-sortable-placeholder {
background-color: rgba(0, 0, 0, 0.025);
}

/* Delete icon: */
.relationship-list--selected li .icon-delete {
position: absolute;
right: 0.5em;
}

/* Sort icon: */
.relationship-list--selected li .icon-left {
color: #ccc;
}
97 changes: 97 additions & 0 deletions assets/js/relationship.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
(function($) {

var Relationship = function(field) {

// Get references to the item lists:
var $list_available = $(field).find('.relationship-list--available');
var $list_selected = $(field).find('.relationship-list--selected');
var $list_unselected = $(field).find('.relationship-list--unselected');

/**
* Add an item to the selection on click:
*/
$list_available.on('click', 'button:not([disabled])', function(event) {
event.preventDefault();

// Clicked item should be disabled:
$(this).prop('disabled', true);

// Get key of clicked item:
var key = $(this).data('key');

// Find item in unselected list:
var $selected_item = $list_unselected.find('li[data-key="' + key + '"]');

// Move the selected item to the end of the selected list:
$selected_item.appendTo($list_selected);

// Set the checkbox as checked:
$selected_item.find('input').prop('checked', true);

// Notify Kirby that some changes are made:
$selected_item.find('input').trigger('change');

// Scroll to bottom of the list to show the new item:
$list_selected.stop().delay(20).animate({
scrollTop: $list_selected[0].scrollHeight
}, {
duration: 600
});
});

/**
* Remove a selected item on click:
*/
$list_selected.on('click', 'button', function(event) {
event.preventDefault();

// Get a reference of the item to be removed from the selection:
var $selected_item = $(this).closest('li');

// Move the selected item to the unselected list:
$selected_item.appendTo($list_unselected);

// Set the checkbox as unchecked:
$selected_item.find('input').prop('checked', false);

// Notify Kirby that some changes are made:
$selected_item.find('input').trigger('change');

// Get the key of the selected item:
var key = $selected_item.data('key');

// Make the selected item available again in the available list:
$list_available.find('button[data-key="' + key + '"]').prop('disabled', false);
});

/**
* Make the list sortable using jQuery Sortable library
* Docs: http://api.jqueryui.com/sortable
*/
$list_selected.sortable({
revert: 100,
placeholder: 'ui-sortable-placeholder',
forcePlaceholderSize: true,
update: function(event, ui) {
// Notify Kirby that some changes are made:
ui.item.find('input').trigger('change');
}
});
};

/**
* Initialize the field:
*/
$.fn.relationship = function() {
return this.each(function() {
if ($(this).data('relationship')) {
return $(this);
} else {
var relationship = new Relationship(this);
$(this).data('relationship', relationship);
return $(this);
}
});
};

})(jQuery);
4 changes: 4 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Changelog

## 1.0.0 (2017-08-11)
- Initial version
12 changes: 12 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"name": "relationship",
"description": "Sortable multiselect field for Kirby 2 CMS",
"author": "Ola Christensson <ola.christensson@grandpublic.se>",
"version": "1.0.0",
"type": "kirby-field",
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/olach/kirby-relationship"
}
}
123 changes: 123 additions & 0 deletions readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
# Kirby Relationship field

The Relationship field allows you to select and sort multiple items from a list. Think of it as a sortable multiselect field or a sortable checkboxes field.

![relationship-field-demo](https://user-images.githubusercontent.com/1300644/29208814-e1f92692-7e8b-11e7-857f-b646853d3ed8.gif)

## Requirements
This field has been tested with Kirby 2.5+, but it should probably work with earlier versions too.

## Installation
### Manually
[Download the files](https://github.com/olach/kirby-relationship/archive/master.zip) and place them inside `site/fields/relationship/`.

### With Kirby CLI
Kirby's [command line interface](https://github.com/getkirby/cli) makes the installation really simple:

$ kirby plugin:install olach/kirby-relationship

Updating is also easy:

$ kirby plugin:update olach/kirby-relationship

## Usage
The field is an extension of the [Checkboxes field](https://getkirby.com/docs/cheatsheet/panel-fields/checkboxes). All options of that field apply to this field too. The data is saved as a comma separated string, which means that this field is interchangeable with the Checkboxes field.

### Example with predefined options
#### Blueprint

```yaml
countries:
label: Countries
type: relationship
options:
sweden: Sweden
norway: Norway
denmark: Denmark
finland: Finland
iceland: Iceland
germany: Germany
france: France
spain: Spain
portugal: Portugal
```
#### Template
```php
<ul>
<?php foreach ($page->countries()->split() as $country): ?>
<li><?= $country ?></li>
<?php endforeach ?>
</ul>
```

### Example with related pages
#### Blueprint

```yaml
related:
label: Related articles
type: relationship
options: query
query:
fetch: siblings
```
#### Template
```php
<h2>Related articles</h2>
<ul>
<?php foreach ($page->related()->pages(',') as $related): ?>
<li>
<a href="<?php echo $related->url() ?>">
<?= $related->title() ?>
</a>
</li>
<?php endforeach ?>
</ul>
```

## Extra features

### Controller:
This field is extended with an option to use a user specified function to have even more control of the options that will be loaded. The idea is taken from the [Controlled List plugin](https://github.com/rasteiner/controlledlist).

#### Example
Create a simple plugin that lets you choose from the panel users.

`site/plugins/myplugin/myplugin.php`:

```php
class MyPlugin {
static function userlist($field) {
$kirby = kirby();
$site = $kirby->site();
$users = $site->users();

$result = array();

foreach ($users as $user) {
$result[$user->username] = $user->firstName() . ' ' . $user->lastName();
}

return $result;
}
}
```

In your blueprint:

```yaml
users:
label: Users
type: relationship
controller: MyPlugin::userlist
```
## Version history
You can find the version history in the [changelog](changelog.md).
## License
[MIT License](http://www.opensource.org/licenses/mit-license.php)
34 changes: 34 additions & 0 deletions relationship.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php

class RelationshipField extends CheckboxesField {

public $controller;

static public $assets = array(
'js' => array(
'relationship.js'
),
'css' => array(
'relationship.css'
)
);

/**
* This field can load a user specified function if set in the blueprint.
*/
public function options() {
if ($this->controller()) {
return call_user_func($this->controller(), $this);
} else {
return parent::options();
}
}

/**
* Use a template file to build all html.
*/
public function content() {
return tpl::load(__DIR__ . DS . 'template.php', array('field' => $this));
}

}
Loading

0 comments on commit c1c7954

Please sign in to comment.