Tweak the ui/ux
Default implementation looks ok, but I'm sure you'll want to tweak it to your liking.
In the Overview I mentioned where bulk actions' html gets added, let's take a look at what actually gets added.
View
DragonFly\Lists
has a view called actions.blade.php
and looks like this:
<div class="row" style="margin: 0; margin-bottom: 15px;">
<div class="col-md-6">
<form class="form form-inline">
<select name="perform_action" class="form-control input-sm block lists-action-select">
<option value="">{!!trans('lists::actions.menu_initial')!!}</option>
@foreach($actions as $action)
<option value="{{$action['slug']}}" data-url="{{$action['url']}}"
data-status="{!!trans($action['status'], ['slug' => $action['slug']])!!}">
{{$action['title']}}
</option>
@endforeach
</select>
<button class="btn btn-sm btn-primary lists-action-perform">{!!trans('lists::actions.apply')!!}</button>
</form>
</div>
<div class="col-md-6 text-right">
<div class="pull-left lists-indicator hide"><i class="fa fa-circle-o-notch fa-spin"></i></div>
<span class="lists-action-indicator">
</span>
</div>
</div>
Aside from the layout there 4 important points here:
- An empty option is added with the
lists::actions.menu_initial
translation as value. - Actions get rendered as options with 2 data attributes
- url: so the js knows where to send the data to
- status: the message that's displayed as long as the request hasn't finished
- A button is added with the
lists::actions.apply
translation - A span called
lists-action-indicator
is there to display a message about the status of the request
If you're changing the view, those first 3 points you should keep in mind. The list-action-indicator
can be overwritten, next to that you can format it however you'd like.
Change the js plugin's behaviour
Changing the view is ok for esthetics, but changing behaviour is more fun.
There are 2 ways you can do this:
- Minimal by listening to events
- Overwriting key handlers
1. Events
Events are the quickest and easiest way tweak the user experience.
Most of the arguments they get passed are the same.
- container: the dataTable's wrapper element (containing the dataTable & the bulk actions)
- action: The title of the action that will be/was performed
- option: The element of the action that will be/was performed (containing the data attributes)
- items: An array containing ids of the records that this action will be/was performed on.
Don't forget to
return false
on your events to prevent the default events from happening.
You can register your event listeners in your view after you have rendered the dataTable js definition
<!-- Render the javascript definition for the table -->
<script type="text/javascript">
{!! $table->definition() !!}
$(#{{$table->html_id}}).on('lists.spinner_start', function(e, container, action, option, items){
// Your own event handler
return false;
});
$(#{{$table->html_id}}).on('lists.spinner_stop', function(e, container, action, option, data){
// Your own event handler
return false;
});
$(#{{$table->html_id}}).on('lists.complete', function(e, container, data, action, option, items){
// Your own event handler
return false;
});
</script>
lists.spinner_start (e, container, action, option, items)
This event gets called right before the request is initialised.
By default it starts the spinner object and shows the action's default status.
lists.spinner_stop (e, container, action, option, data)
This is event is triggered when the request completed.
As you can see a data attribute is available at the end that contains that request's data return which consists of 4 possible keys:
status
('success','error')type
('complete', 'empty')message
error
The error
key only gets sent if an exception was thrown when performing the action.
By default it hides the spinner, updates the action's status message and gives it a class(text-success or text-warning) and sets a timer that hides the action's status message after 7 seconds.
lists.complete (e, container, data, action, option, items)
This is event is triggered when the request completed.
As you can see a data attribute is available that contains that request's data return which consists of 4 possible keys:
status
('success','error')type
('complete', 'empty')message
error
The error
key only gets sent if an exception was thrown when performing the action.
By default it does nothing since the spinner takes care of the status message.
2. Handlers
Next to events you can overwrite the default handlers, there are 3:
initTool
, a function which places the bulk actions tools & adds the actions to itspinner
, an object that handles the spinnercomplete
, a callback function that handles request completion
All these are defined on $.fn.dataTableLists
It's best to define these after you've loaded the
assets/js/happydemon.lists.js
file.
initTool (actions, container)
As mentioned before, this function is called to place the table's bulk actions (which by default are added above the table), however, you are free to place it in any html element you'd like.
It takes 2 arguments:
- actions: this argument holds the actions' HTML (rendered from our view)
- container: this one's the table's wrapper element.
$.fn.dataTableLists.initTool = function (actions, container) {
// Places actions above table
container.prepend('<div class="row-list-tools"></div>');
container.find('.row-list-tools').prepend(actions);
};
spinner {}
The spinner object needs an init method that takes
settings
as an argument, you're free to fill the object with any methods you'd like
By default the spinner object's init method registers the lists.spinner_start
and lists.spinner_stop
event and describes their callbacks.
$.fn.dataTableLists.spinner = {
init: function (settings) {
settings.container.data('currentClass', 'text-muted');
settings.dataTable.on('lists.spinner_start', this.start);
settings.dataTable.on('lists.spinner_stop', this.stop);
},
start: function (e, container, action, option, items) {
container.find('.lists-indicator').removeClass('hide');
container.find('.lists-action-indicator').addClass('text-muted').text(option.data('status')).slideDown();
container.find('.lists-indicator').show();
},
stop: function (e, container, action, option, data) {
container.find('.lists-indicator').addClass('hide');
var indicator = container.find('.lists-action-indicator');
var addClass = '';
var text = '';
switch (data.status) {
case 'success':
if (data.type != 'empty')
addClass = 'text-success';
else
addClass = 'text-warning';
text = data.message;
break;
case 'error':
addClass = 'text-warning';
text = data.message;
break;
}
indicator.text(text);
indicator.removeClass(container.data('currentClass')).addClass(addClass);
container.data('currentClass', addClass);
// Hide after 7 seconds
setTimeout(function () {
indicator.slideUp().removeClass(settings.container.data('currentClass')).addClass('text-muted').text('');
container.data('currentClass', 'text-muted');
}, 7000);
}
};
complete (e, container, data, action, option, items)
This is the default request completion callback. By default it does nothing.
If you'd rather overwrite instead of registering a different event callback, be my guest.
$.fn.dataTableLists.complete = function (e, container, data, action, option, items) {
};
Updated less than a minute ago