Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature: Add mouse events and custom buttons support #213

Open
wants to merge 5 commits into
base: 3.x
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 66 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@
- [Creating events on day selection](#creating-events-on-day-selection)
- [Creating events with additional data](#creating-events-with-additional-data)
- [Event tooltip on hover](#event-tooltip-on-hover)
- [Event Mouse Enter and Mouse Leave](#event-mouse-enter-and-mouse-leave)
- [Adding custom buttons](#adding-custom-buttons)
- [Adding the widget to a Blade view](#adding-the-widget-to-a-blade-view)
- [Share your tricks](#share-your-tricks)
- [Changelog](#changelog)
Expand Down Expand Up @@ -500,6 +502,70 @@ public function eventDidMount(): string

The JavaScript code returned by `eventDidMount()` will be added to [the FullCalendar's `eventDidMount` event render hook](https://fullcalendar.io/docs/event-render-hooks).

## Event Mouse Enter and Mouse Leave

You can add some custom behavior when the user hovers over the event via JavaScript on the `eventMouseEnter` and `eventMouseLeave` methods:

```php
public function eventMouseEnter(): string
{
return <<<JS
function({ event, el, jsEvent, view }){
// Write your custom implementation here
// Will be triggered when the user hovers over the event
}
JS;
}

public function eventMouseLeave(): string
{
return <<<JS
function({ event, el, jsEvent, view }){
// Write your custom implementation here
// Will be triggered when the user leaves the event
}
JS;
}
```

The JavaScript code returned by `eventMouseEnter()` and `eventMouseLeave()` will be added to [the FullCalendar's `eventMouseEnter` and `eventMouseLeave` event hovering hook](https://fullcalendar.io/docs/event-clicking-hovering).


## Adding custom buttons

You can add [custom buttons](https://fullcalendar.io/docs/customButtons) to the calendar.

```php
public function customButtons(): array
{
return [
'myCustomButton' => [
'text' => 'My Custom Button',
'click' => <<<JS
function() {
alert('Hello, World!');
}
JS
]
];
}
```

Then you can use the custom button in the `headerToolbar` configuration:

```php
public function config(): array
{
return [
'headerToolbar' => [
'left' => 'prev,next today myCustomButton',
'center' => 'title',
'right' => 'dayGridMonth,timeGridWeek,timeGridDay'
],
];
}
```

## Adding the widget to a Blade view

Follow the [Filament Docs](https://filamentphp.com/docs/3.x/widgets/adding-a-widget-to-a-blade-view) to know how to add the widget to a Blade view.
Expand Down
12 changes: 6 additions & 6 deletions dist/filament-fullcalendar.js

Large diffs are not rendered by default.

8 changes: 7 additions & 1 deletion resources/js/filament-fullcalendar.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,13 @@ export default function fullcalendar({
config,
editable,
selectable,
customButtons,
eventClassNames,
eventContent,
eventDidMount,
eventWillUnmount,
eventMouseEnter,
eventMouseLeave,
}) {
return {
init() {
Expand All @@ -46,10 +49,13 @@ export default function fullcalendar({
selectable,
...config,
locales,
customButtons,
eventClassNames,
eventContent,
eventDidMount,
eventWillUnmount,
eventMouseEnter,
eventMouseLeave,
events: (info, successCallback, failureCallback) => {
this.$wire.fetchEvents({ start: info.startStr, end: info.endStr, timezone: info.timeZone })
.then(successCallback)
Expand Down Expand Up @@ -91,7 +97,7 @@ export default function fullcalendar({

calendar.render()

window.addEventListener('filament-fullcalendar--refresh', () => calendar.refetchEvents())
window.addEventListener('filament-fullcalendar--refresh', () => calendar.refetchResources() || calendar.refetchEvents())
window.addEventListener('filament-fullcalendar--prev', () => calendar.prev())
window.addEventListener('filament-fullcalendar--next', () => calendar.next())
window.addEventListener('filament-fullcalendar--today', () => calendar.today())
Expand Down
12 changes: 12 additions & 0 deletions resources/views/fullcalendar.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,15 @@
<x-filament-actions::actions :actions="$this->getCachedHeaderActions()" class="shrink-0" />
</div>

<!-- This script tag is added to define custom buttons. The "click" property a function that calls the custom button function. -->
<script>
var customButtons = @json($this->customButtons());

@php foreach($this->customButtons() as $customButtonKey => $customButton) { @endphp
customButtons['{{ $customButtonKey }}']['click'] = {!! htmlspecialchars($this->getCustomButtonJsFunction($customButtonKey), ENT_COMPAT) !!}
@php } @endphp
</script>

<div class="filament-fullcalendar" wire:ignore ax-load
ax-load-src="{{ \Filament\Support\Facades\FilamentAsset::getAlpineComponentSrc('filament-fullcalendar-alpine', 'saade/filament-fullcalendar') }}"
ax-load-css="{{ \Filament\Support\Facades\FilamentAsset::getStyleHref('filament-fullcalendar-styles', 'saade/filament-fullcalendar') }}"
Expand All @@ -19,10 +28,13 @@
config: @js($this->getConfig()),
editable: @json($plugin->isEditable()),
selectable: @json($plugin->isSelectable()),
customButtons: customButtons,
eventClassNames: {!! htmlspecialchars($this->eventClassNames(), ENT_COMPAT) !!},
eventContent: {!! htmlspecialchars($this->eventContent(), ENT_COMPAT) !!},
eventDidMount: {!! htmlspecialchars($this->eventDidMount(), ENT_COMPAT) !!},
eventWillUnmount: {!! htmlspecialchars($this->eventWillUnmount(), ENT_COMPAT) !!},
eventMouseEnter: {!! htmlspecialchars($this->eventMouseEnter(), ENT_COMPAT) !!},
eventMouseLeave: {!! htmlspecialchars($this->eventMouseLeave(), ENT_COMPAT) !!},
})">
</div>
</x-filament::section>
Expand Down
29 changes: 29 additions & 0 deletions src/Widgets/Concerns/InteractsWithCustomButtons.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php

namespace Saade\FilamentFullCalendar\Widgets\Concerns;

trait InteractsWithCustomButtons
{
/**
* Add custom buttons to the calendar.
* https://fullcalendar.io/docs/customButtons
*
* @return array
*/
public function customButtons(): array
{
return [];
}

/**
* Get button action function by key.
*
* @param string $key
*
* @return string
*/
public function getCustomButtonJsFunction(string $key): string
{
return $this->customButtons()[$key]['click'] ?? '';
}
}
28 changes: 28 additions & 0 deletions src/Widgets/Concerns/InteractsWithRawJS.php
Original file line number Diff line number Diff line change
Expand Up @@ -61,4 +61,32 @@ public function eventWillUnmount(): string
null
JS;
}

/**
* Triggered when the user mouses over an event. Similar to the native mouseenter.
*
* @see https://fullcalendar.io/docs/eventMouseEnter
*
* @return string
*/
public function eventMouseEnter(): string
{
return <<<JS
null
JS;
}

/**
* Triggered when the user mouses out of an event. Similar to the native mouseleave.
*
* @see https://fullcalendar.io/docs/eventMouseLeave
*
* @return string
*/
public function eventMouseLeave(): string
{
return <<<JS
null
JS;
}
}
10 changes: 10 additions & 0 deletions src/Widgets/Contracts/HasCustomButtons.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

namespace Saade\FilamentFullCalendar\Widgets\Contracts;

interface HasCustomButtons
{
public function customButtons(): array;

public function getCustomButtonJsFunction(string $key): string;
}
5 changes: 4 additions & 1 deletion src/Widgets/FullCalendarWidget.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,14 @@
use Filament\Forms\Contracts\HasForms;
use Filament\Widgets\Widget;
use Saade\FilamentFullCalendar\Actions;
use Saade\FilamentFullCalendar\Widgets\Concerns\InteractsWithCustomButtons;
use Saade\FilamentFullCalendar\Widgets\Contracts\HasCustomButtons;

class FullCalendarWidget extends Widget implements HasForms, HasActions
class FullCalendarWidget extends Widget implements HasForms, HasActions, HasCustomButtons
{
use InteractsWithForms;
use InteractsWithActions;
use InteractsWithCustomButtons;
use Concerns\InteractsWithEvents;
use Concerns\InteractsWithRecords;
use Concerns\InteractsWithHeaderActions;
Expand Down