<link href="//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css" rel="stylesheet" id="bootstrap-css">
<script src="//netdna.bootstrapcdn.com/bootstrap/3.0.0/js/bootstrap.min.js"></script>
<script src="//code.jquery.com/jquery-1.11.1.min.js"></script>
<!------ Include the above in your HEAD tag ---------->
<!DOCTYPE html>
<html>
<head>
<!-- Standard Meta -->
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">
<!-- Site Properties -->
<title>vuetable - Semantic</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.2.2/semantic.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/sweetalert/1.1.3/sweetalert.min.css">
<style type="text/css">
.ui.vertical.stripe h3 {
font-size: 2em;
}
.secondary.pointing.menu .toc.item {
display: none;
}
.vuetable {
margin-top: 1em !important;
}
.vuetable-wrapper.ui.basic.segment {
padding: 0em;
}
.vuetable button.ui.button {
padding: .5em .5em;
font-weight: 400;
}
.vuetable button.ui.button i.icon {
margin: 0;
}
.vuetable th.sortable:hover {
color: #2185d0;
cursor: pointer;
}
.vuetable-actions, .custom-action {
width: 15%;
padding: 12px 0px;
text-align: center;
}
.vuetable-pagination {
background: #f9fafb !important;
}
.vuetable-pagination-info {
margin-top: auto;
margin-bottom: auto;
}
[v-cloak] {
display: none;
}
.highlight {
background-color: yellow;
}
.vuetable-detail-row {
height: 200px;
}
.detail-row {
margin-left: 40px;
}
.expand-transition {
transition: all .5s ease;
}
.expand-enter, .expand-leave {
height: 0;
opacity: 0;
}
tr.odd {
background-color: #e6f5ff;
}
body {
overflow-y: scroll;
}
</style>
</head>
<body>
<!-- Page Contents -->
<div class="ui inverted vertical masthead center aligned segment">
<div class="ui container">
<div class="ui large secondary inverted pointing menu">
<a class="toc item">
<i class="sidebar icon"></i>
</a>
<a class="active item">Home</a>
<a class="item">Work</a>
<a class="item">Company</a>
<a class="item">Careers</a>
<div class="right item">
<a class="ui inverted button">Log in</a>
<a class="ui inverted button">Sign Up</a>
</div>
</div>
</div>
</div>
<div id="app" class="ui vertical stripe segment">
<div class="ui container">
<div id="content" class="ui basic segment">
<h3 class="ui header">List of Users</h3>
<div class="ui grid">
<div class="ui left aligned nine wide column">
<div class="ui labeled icon input">
<div class="ui label">Search:</div>
<input v-model="searchFor" class="ui input" @keyup.enter="setFilter">
<i class="search icon"></i>
</div>
<button class="ui button primary" @click="setFilter">Go</button>
<button class="ui button" @click="resetFilter">Reset</button>
</div>
<div class="ui right aligned seven wide column">
<button class="ui basic button" id="settingsBtn">
<i class="setting icon"></i>
Settings
</button>
</div>
</div>
<div class="ui small modal" id="settingsModal">
<div class="header">Settings</div>
<div class="content ui form">
<div class="field">
<div class="ui checkbox">
<input type="checkbox" v-model="multiSort">
<label>Multisort (use Alt+Click)</label>
</div>
</div>
<div class="ui divider"></div>
<div class="field">
<label>Pagination:</label>
<select class="ui simple dropdown" v-model="paginationComponent">
<option value="vuetable-pagination">vuetable-pagination</option>
<option value="vuetable-pagination-dropdown">vuetable-pagination-dropdown</option>
</select>
</div>
<div class="field">
<label>Per Page:</label>
<select class="ui simple dropdown" v-model="perPage">
<option value=10>10</option>
<option value=15>15</option>
<option value=20>20</option>
<option value=25>25</option>
</select>
</div>
<div class="ui fluid card">
<div class="content">
<div class="header">Visible fields</div>
</div>
<div class="content">
<div v-for="field in fields" class="field">
<div class="ui checkbox">
<input type="checkbox" v-model="field.visible">
<label>{{ field.title == '' ? field.name.replace('__', '') : field.title | capitalize}}</label>
</div>
</div>
</div>
</div>
</div>
<div class="actions">
<div class="ui cancel button">Close</div>
</div>
</div>
<vuetable v-ref:vuetable
api-url="http://vuetable.ratiw.net/api/users"
pagination-path=""
:pagination-component="paginationComponent"
wrapper-class="vuetable-wrapper ui basic segment"
table-wrapper=".vuetable-wrapper"
:fields="fields"
:sort-order="sortOrder"
:multi-sort="multiSort"
:item-actions="itemActions"
:per-page="perPage"
:append-params="moreParams"
detail-row-component="my-detail-row"
detail-row-id="id"
detail-row-transition="expand"
row-class-callback="rowClassCB"
></vuetable>
</div>
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.2/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.2.2/semantic.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.12.0/moment-with-locales.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/sweetalert/1.1.3/sweetalert.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/1.0.26/vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue-resource/0.7.0/vue-resource.min.js"></script>
<script src="/js/vue-table.js"></script>
<script>
$('#settingsModal').modal({
detachable: false,
onVisible: function() {
$('.ui.checkbox').checkbox()
}
}).modal('attach events', '#settingsBtn', 'show')
var tableColumns = [
{
name: 'id',
title: '',
dataClass: 'center aligned',
callback: 'showDetailRow'
},
{
name: 'name',
title: 'Full Name',
sortField: 'name'
},
{
name: 'email',
sortField: 'email',
visible: true
},
{
name: 'nickname',
sortField: 'nickname',
callback: 'allCap'
},
{
name: 'birthdate',
sortField: 'birthdate',
callback: 'formatDate|D/MM/Y'
},
{
name: 'gender',
sortField: 'gender',
titleClass: 'center aligned',
dataClass: 'center aligned',
callback: 'gender'
},
{
name: '__component:custom-action',
title: "Component",
titleClass: 'center aligned',
dataClass: 'custom-action center aligned',
},
{
name: '__actions',
dataClass: 'center aligned',
}
]
Vue.config.debug = true
var E_SERVER_ERROR = 'Error communicating with the server'
Vue.component('custom-action', {
template: [
'<div>',
'<button class="ui red button" @click="itemAction(\'view-item\', rowData)"><i class="zoom icon"></i></button>',
'<button class="ui blue button" @click="itemAction(\'edit-item\', rowData)"><i class="edit icon"></i></button>',
'<button class="ui green button" @click="itemAction(\'delete-item\', rowData)"><i class="delete icon"></i></button>',
'</div>'
].join(''),
props: {
rowData: {
type: Object,
required: true
}
},
methods: {
itemAction: function(action, data) {
sweetAlert('custom-action: ' + action, data.name)
},
onClick: function(event) {
console.log('custom-action: on-click', event.target)
},
onDoubleClick: function(event) {
console.log('custom-action: on-dblclick', event.target)
}
}
})
Vue.component('my-detail-row', {
template: [
'<div class="detail-row ui form" @click="onClick($event)">',
'<div class="inline field">',
'<label>Name: </label>',
'<span>{{rowData.name}}</span>',
'</div>',
'<div class="inline field">',
'<label>Email: </label>',
'<span>{{rowData.email}}</span>',
'</div>',
'<div class="inline field">',
'<label>Nickname: </label>',
'<span>{{rowData.nickname}}</span>',
'</div>',
'<div class="inline field">',
'<label>Birthdate: </label>',
'<span>{{rowData.birthdate}}</span>',
'</div>',
'<div class="inline field">',
'<label>Gender: </label>',
'<span>{{rowData.gender}}</span>',
'</div>',
'</div>',
].join(''),
props: {
rowData: {
type: Object,
required: true
}
},
methods: {
onClick: function(event) {
console.log('my-detail-row: on-click')
}
},
})
new Vue({
el: '#app',
data: {
searchFor: '',
moreParams: [],
fields: tableColumns,
sortOrder: [{
field: 'name',
direction: 'asc',
}],
multiSort: true,
paginationComponent: 'vuetable-pagination',
perPage: 10,
// paginationInfoTemplate: 'แสดง {from} ถึง {to} จากทั้งหมด {total} รายการ',
itemActions: [
{ name: 'view-item', label: '', icon: 'zoom icon', class: 'ui teal button' },
{ name: 'edit-item', label: '', icon: 'edit icon', class: 'ui orange button'},
{ name: 'delete-item', label: '', icon: 'delete icon', class: 'ui red button' }
]
},
watch: {
'perPage': function(val, oldVal) {
this.$broadcast('vuetable:refresh')
},
'paginationComponent': function(val, oldVal) {
this.$broadcast('vuetable:load-success', this.$refs.vuetable.tablePagination)
}
},
methods: {
/**
* Callback functions
*/
allCap: function(value) {
return value.toUpperCase()
},
gender: function(value) {
return value == 'M'
? '<span class="ui teal label"><i class="male icon"></i>Male</span>'
: '<span class="ui pink label"><i class="female icon"></i>Female</span>'
},
formatDate: function(value, fmt) {
if (value == null) return ''
fmt = (typeof fmt == 'undefined') ? 'D MMM YYYY' : fmt
return moment(value, 'YYYY-MM-DD').format(fmt)
},
showDetailRow: function(value) {
var icon = this.$refs.vuetable.isVisibleDetailRow(value) ? 'down' : 'right'
return [
'<a class="show-detail-row">',
'<i class="chevron circle ' + icon + ' icon"></i>',
'</a>'
].join('')
},
setFilter: function() {
this.moreParams = [
'filter=' + this.searchFor
]
this.$nextTick(function() {
this.$broadcast('vuetable:refresh')
})
},
resetFilter: function() {
this.searchFor = ''
this.setFilter()
},
changePaginationComponent: function() {
this.$broadcast('vuetable:load-success', this.$refs.vuetable.tablePagination)
},
preg_quote: function( str ) {
// http://kevin.vanzonneveld.net
// + original by: booeyOH
// + improved by: Ates Goral (http://magnetiq.com)
// + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
// + bugfixed by: Onno Marsman
// * example 1: preg_quote("$40");
// * returns 1: '\$40'
// * example 2: preg_quote("*RRRING* Hello?");
// * returns 2: '\*RRRING\* Hello\?'
// * example 3: preg_quote("\\.+*?[^]$(){}=!<>|:");
// * returns 3: '\\\.\+\*\?\[\^\]\$\(\)\{\}\=\!\<\>\|\:'
return (str+'').replace(/([\\\.\+\*\?\[\^\]\$\(\)\{\}\=\!\<\>\|\:])/g, "\\$1");
},
highlight: function(needle, haystack) {
return haystack.replace(
new RegExp('(' + this.preg_quote(needle) + ')', 'ig'),
'<span class="highlight">$1</span>'
)
},
rowClassCB: function(data, index) {
return (index % 2) === 0 ? 'odd' : 'even'
},
// -------------------------------------------------------------------------------------------
// You can change how sort params string is constructed by overriding getSortParam() like this
// -------------------------------------------------------------------------------------------
// getSortParam: function(sortOrder) {
// console.log('parent getSortParam:', JSON.stringify(sortOrder))
// return sortOrder.map(function(sort) {
// return (sort.direction === 'desc' ? '+' : '') + sort.field
// }).join(',')
// }
},
events: {
'vuetable:row-changed': function(data) {
console.log('row-changed:', data.name)
},
'vuetable:row-clicked': function(data, event) {
console.log('row-clicked:', data.name)
},
'vuetable:cell-clicked': function(data, field, event) {
console.log('cell-clicked:', field.name)
if (field.name !== '__actions') {
this.$broadcast('vuetable:toggle-detail', data.id)
}
},
'vuetable:action': function(action, data) {
console.log('vuetable:action', action, data)
if (action == 'view-item') {
sweetAlert(action, data.name)
} else if (action == 'edit-item') {
sweetAlert(action, data.name)
} else if (action == 'delete-item') {
sweetAlert(action, data.name)
}
},
'vuetable:load-success': function(response) {
var data = response.data.data
if (this.searchFor !== '') {
for (n in data) {
data[n].name = this.highlight(this.searchFor, data[n].name)
data[n].email = this.highlight(this.searchFor, data[n].email)
}
}
},
'vuetable:load-error': function(response) {
if (response.status == 400) {
sweetAlert('Something\'s Wrong!', response.data.message, 'error')
} else {
sweetAlert('Oops', E_SERVER_ERROR, 'error')
}
}
}
})
</script>
</body>
</html>