From e1eb2da5f36d79bdcd9bc05c69e04220997b8b94 Mon Sep 17 00:00:00 2001 From: snipe Date: Thu, 9 Jul 2015 13:32:26 -0700 Subject: [PATCH 001/120] Create book.json --- book.json | 1 + 1 file changed, 1 insertion(+) create mode 100644 book.json diff --git a/book.json b/book.json new file mode 100644 index 0000000000..9e26dfeeb6 --- /dev/null +++ b/book.json @@ -0,0 +1 @@ +{} \ No newline at end of file From dacbdd9aa5ce0c5df85ec0ceecfa08d73232b16b Mon Sep 17 00:00:00 2001 From: snipe Date: Fri, 10 Jul 2015 19:46:17 -0700 Subject: [PATCH 002/120] Delete book.json --- book.json | 1 - 1 file changed, 1 deletion(-) delete mode 100644 book.json diff --git a/book.json b/book.json deleted file mode 100644 index 9e26dfeeb6..0000000000 --- a/book.json +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file From ae91f829e1983c4c4e907fbf95b54f57c69ad396 Mon Sep 17 00:00:00 2001 From: madd15 Date: Tue, 28 Jul 2015 13:50:10 +0930 Subject: [PATCH 003/120] Change to bootstrap table compatable method --- app/controllers/admin/AssetsController.php | 143 ++++++--------------- 1 file changed, 36 insertions(+), 107 deletions(-) diff --git a/app/controllers/admin/AssetsController.php b/app/controllers/admin/AssetsController.php index 3e74143715..5a1b7b0c12 100755 --- a/app/controllers/admin/AssetsController.php +++ b/app/controllers/admin/AssetsController.php @@ -1070,117 +1070,46 @@ class AssetsController extends AdminController $assets = $assets->orderBy('asset_tag', 'ASC')->get(); + $rows = array(); + $i=0; + foreach ($assets as $asset) { + if ($asset->deleted_at=='') { + $actions = '
'; + } elseif ($asset->model->deleted_at=='') { + $actions = ''; + } - $actions = new \Chumper\Datatable\Columns\FunctionColumn('actions', function ($assets) - { - if ($assets->deleted_at=='') { - return '
'; - } elseif ($assets->model->deleted_at=='') { - return ''; - } - - }); - - $inout = new \Chumper\Datatable\Columns\FunctionColumn('inout', function ($assets) - { - - if ($assets->assetstatus) { - - if ($assets->assetstatus->deployable != 0) { - if (($assets->assigned_to !='') && ($assets->assigned_to > 0)) { - return ''.Lang::get('general.checkin').''; - } else { - return ''.Lang::get('general.checkout').''; - } + if ($asset->assetstatus) { + if ($asset->assetstatus->deployable != 0) { + if (($asset->assigned_to !='') && ($asset->assigned_to > 0)) { + $inout = ''.Lang::get('general.checkin').''; + } else { + $inout = ''.Lang::get('general.checkout').''; } } - }); + } + $rows[] = array( + 'checkbox' =>'
', + 'name' => ''.$asset->name.'', + 'asset_tag' => ''.$asset->asset_tag.'', + 'serial' => $asset->serial, + 'model' => ($asset->model) ? $asset->model->name : 'No model', + 'status' => ($asset->assigned_to!='') ? link_to('../admin/users/'.$asset->assigned_to.'/view', $asset->assigneduser->fullName()) : (($asset->assetstatus) ? $asset->assetstatus->name : ''), + 'location' => (($asset->assigned_to)&&($asset->assigneduser->userloc!='')) ? link_to('admin/settings/locations/'.$asset->assigneduser->userloc->id.'/edit', $asset->assigneduser->userloc->name) : (($asset->defaultLoc!='') ? link_to('admin/settings/locations/'.$asset->defaultLoc->id.'/edit', $asset->defaultLoc->name) : ''), + 'category' => ($asset->model->category) ? $asset->model->category->name : 'No category', + 'eol' => $asset->eol_date(), + 'notes' => $asset->notes, + 'order' => ($asset->order_number) ? ''.$asset->order_number.'' : '', + 'checkout_date' => (($asset->assigned_to!='')&&($asset->assetlog->first())) ? $asset->assetlog->first()->created_at->format('Y-m-d') : '', + 'change' => $inout, + 'actions' => $actions + ); + $i++; + } + $data = array('total'=>$i, 'rows'=>$rows); - return Datatable::collection($assets) - ->addColumn('',function($assets) - { - return '
'; - }) - ->addColumn('name',function($assets) - { - return ''.$assets->name.''; - }) - ->addColumn('asset_tag',function($assets) - { - return ''.$assets->asset_tag.''; - }) - - ->showColumns('serial') - - ->addColumn('model',function($assets) - { - if ($assets->model) { - return $assets->model->name; - } else { - return 'No model'; - } - }) - - ->addColumn('status',function($assets) - { - if ($assets->assigned_to!='') { - return link_to(Config::get('app.url').'/admin/users/'.$assets->assigned_to.'/view', $assets->assigneduser->fullName()); - } else { - if ($assets->assetstatus) { - return $assets->assetstatus->name; - } - - } - - }) - ->addColumn('location',function($assets) - { - if ($assets->assigned_to && ($assets->assigneduser->userloc!='')) { - return link_to('admin/settings/locations/'.$assets->assigneduser->userloc->id.'/edit', $assets->assigneduser->userloc->name); - } elseif ($assets->defaultLoc){ - return link_to('admin/settings/locations/'.$assets->defaultLoc->id.'/edit', $assets->defaultLoc->name); - } - }) - ->addColumn('category',function($assets) - { - if (isset($assets->model->category)) { - return $assets->model->category->name; - } else { - return 'No category'; - } - - }) - - ->addColumn('eol',function($assets) - { - return $assets->eol_date(); - }) - - ->addColumn('notes',function($assets) - { - return $assets->notes; - }) - - ->addColumn('order_number',function($assets) - { - return ''.$assets->order_number.''; - }) - - - ->addColumn('checkout_date',function($assets) - { - if (($assets->assigned_to!='') && ($assets->assetlog->first())) { - return $assets->assetlog->first()->created_at->format('Y-m-d'); - } - - }) - ->addColumn($inout) - ->addColumn($actions) - ->searchColumns('name', 'asset_tag', 'serial', 'model', 'status','location','eol','checkout_date', 'inout','category','notes','order_number') - ->orderColumns('name', 'asset_tag', 'serial', 'model', 'status','location','eol','notes','order_number','checkout_date', 'inout') - ->make(); - - } + return $rows; + } } From 0dc2a0ffacb5917c43e6ade86908f042612b2a6d Mon Sep 17 00:00:00 2001 From: madd15 Date: Tue, 28 Jul 2015 13:50:48 +0930 Subject: [PATCH 004/120] Change to bootstrap table compatable method --- app/views/backend/hardware/index.blade.php | 149 +++++++++++---------- 1 file changed, 78 insertions(+), 71 deletions(-) diff --git a/app/views/backend/hardware/index.blade.php b/app/views/backend/hardware/index.blade.php index c1b58d314a..876cfd8b77 100755 --- a/app/views/backend/hardware/index.blade.php +++ b/app/views/backend/hardware/index.blade.php @@ -47,86 +47,93 @@
- - {{ Form::open([ 'method' => 'POST', 'route' => ['hardware/bulkedit'], 'class' => 'form-horizontal' ]) }} - - -{{ Datatable::table() - ->addColumn('
',Lang::get('admin/hardware/form.name'), - Lang::get('admin/hardware/table.asset_tag'), - Lang::get('admin/hardware/table.serial'), - Lang::get('admin/hardware/form.model'), - Lang::get('admin/hardware/table.status'), - Lang::get('admin/hardware/table.location'), - Lang::get('general.category'), - Lang::get('admin/hardware/table.eol'), - Lang::get('general.notes'), - Lang::get('admin/hardware/form.order'), - Lang::get('admin/hardware/table.checkout_date'), - Lang::get('admin/hardware/table.change'), - Lang::get('table.actions')) - ->setOptions( - array( - 'language' => array( - 'search' => Lang::get('general.search'), - 'lengthMenu' => Lang::get('general.page_menu'), - 'loadingRecords' => Lang::get('general.loading'), - 'zeroRecords' => Lang::get('general.no_results'), - 'info' => Lang::get('general.pagination_info'), - 'processing' => ' '.Lang::get('general.processing'), - 'paginate'=> array( - 'first'=>Lang::get('general.first'), - 'previous'=>Lang::get('general.previous'), - 'next'=>Lang::get('general.next'), - 'last'=>Lang::get('general.last'), - ), - ), - 'sAjaxSource'=> route('api.hardware.list', array(''=>Input::get('status'),'order_number'=>Input::get('order_number'))), - 'dom' =>'CT<"clear">lfrtip', - 'colVis'=> array('showAll'=>'Show All','restore'=>'Restore','exclude'=>array(0,12,13),'activate'=>'mouseover'), - 'columnDefs'=> array(array('visible'=>false,'targets'=>array(7,8,9)),array('orderable'=>false,'targets'=>array(0,12,13))), - 'order'=>array(array(1,'asc')), - ) - ) - ->render('backend/hardware/datatable') }} + + + + + + + + + + + + + + + + + + + + + + + + +
{{Lang::get('admin/hardware/form.name')}}{{Lang::get('admin/hardware/table.asset_tag')}}{{Lang::get('admin/hardware/table.serial')}}{{Lang::get('admin/hardware/form.model')}}{{Lang::get('admin/hardware/table.status')}}{{Lang::get('admin/hardware/table.location')}}{{Lang::get('general.category')}}{{Lang::get('general.eol')}}{{Lang::get('general.notes')}}{{Lang::get('admin/hardware/form.order')}}{{Lang::get('admin/hardware/table.checkout_date')}}{{Lang::get('admin/hardware/table.change')}}{{Lang::get('table.actions')}}
+ + +
{{ Form::close() }} -
- - + - + @stop From fc22c3884b4c41397282e1fc963144f98925f0c1 Mon Sep 17 00:00:00 2001 From: madd15 Date: Tue, 28 Jul 2015 13:51:53 +0930 Subject: [PATCH 005/120] Add bootstrap table js and css --- app/views/backend/layouts/default.blade.php | 29 ++++++++------------- 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/app/views/backend/layouts/default.blade.php b/app/views/backend/layouts/default.blade.php index 3f3bdea3a7..97e4270752 100644 --- a/app/views/backend/layouts/default.blade.php +++ b/app/views/backend/layouts/default.blade.php @@ -5,7 +5,7 @@ - + @section('title') @@ -36,17 +36,21 @@ <link rel="stylesheet" href="{{ asset('assets/css/compiled/user-list.css') }}" type="text/css" media="screen" /> <link rel="stylesheet" href="{{ asset('assets/css/compiled/user-profile.css') }}" type="text/css" media="screen" /> - <link rel="stylesheet" href="{{ asset('assets/css/lib/jquery.dataTables.css') }}" type="text/css" media="screen" /> - <link rel="stylesheet" href="{{ asset('assets/css/compiled/dataTables.colVis.css') }}" type="text/css" media="screen" /> - <link rel="stylesheet" href="{{ asset('assets/css/compiled/dataTables.tableTools.css') }}" type="text/css" media="screen" /> + <link rel="stylesheet" href="{{ asset('assets/css/bootstrap/bootstrap-table.css') }}" type="text/css" media="screen" /> + <link rel="stylesheet" type="text/css" href="{{ asset('assets/css/compiled/print.css') }}" media="print" /> <!-- global header javascripts --> <script src="{{ asset('assets/js/jquery-latest.js') }}"></script> - <script src="{{ asset('assets/js/jquery.dataTables.min.js') }}"></script> - <script src="{{ asset('assets/js/dataTables.colVis.js') }}"></script> - <script src="{{ asset('assets/js/dataTables.tableTools.js') }}"></script> + <script src="{{ asset('assets/js/bootstrap-table.js') }}"></script> + <script src="{{ asset('assets/js/extensions/export/bootstrap-table-export.js') }}"></script> + <script src="{{ asset('assets/js/extensions/cookie/bootstrap-table-cookie.js') }}"></script> + <script src="{{ asset('assets/js/extensions/mobile/bootstrap-table-mobile.js') }}"></script> + <script src="{{ asset('assets/js/libs/FileSaver/FileSaver.min.js') }}"></script> + <script src="{{ asset('assets/js/libs/html2canvas/html2canvas.min.js') }}"></script> + <script src="{{ asset('assets/js/libs/jsPDF/jspdf.min.js') }}"></script> + <script src="{{ asset('assets/js/libs/jsPDF-AutoTable/jspdf.plugin.autotable.js') }}"></script> <script> window.snipeit = { @@ -81,8 +85,6 @@ background-color: {{{ Setting::getSettings()->header_color }}}; background: -webkit-linear-gradient(top, {{{ Setting::getSettings()->header_color }}} 0%,{{{ Setting::getSettings()->header_color }}} 100%); border-color: {{{ Setting::getSettings()->header_color }}}; - background-image: -moz-linear-gradient(top, {{{ Setting::getSettings()->header_color }}}, {{{ Setting::getSettings()->header_color }}}); - } @endif @@ -460,14 +462,5 @@ <script src="{{ asset('assets/js/bootstrap.datepicker.js') }}"></script> <script src="{{ asset('assets/js/theme.js') }}"></script> <script src="{{ asset('assets/js/snipeit.js') }}"></script> - <script> - $(function(){ - $( ".ColVis" ).prepend('<button class="ColVis_Button">Reset Defaults</button>').click(function(e){ - e.preventDefault(); - oTable.api().state.clear(); - window.location.reload(); - }); - }); - </script> </body> </html> From 1ba798a35deaf8967d72267e03a3dce6ec11ade9 Mon Sep 17 00:00:00 2001 From: madd15 <joshdeakin@adam.com.au> Date: Tue, 28 Jul 2015 13:53:29 +0930 Subject: [PATCH 006/120] Add bootstrap-table.css --- .../assets/css/bootstrap/bootstrap-table.css | 284 ++++++++++++++++++ 1 file changed, 284 insertions(+) create mode 100644 public/assets/css/bootstrap/bootstrap-table.css diff --git a/public/assets/css/bootstrap/bootstrap-table.css b/public/assets/css/bootstrap/bootstrap-table.css new file mode 100644 index 0000000000..981f80d72f --- /dev/null +++ b/public/assets/css/bootstrap/bootstrap-table.css @@ -0,0 +1,284 @@ +/** + * @author zhixin wen <wenzhixin2010@gmail.com> + * version: 1.8.1 + * https://github.com/wenzhixin/bootstrap-table/ + */ + +.bootstrap-table .table { + margin-bottom: 0 !important; + border-bottom: 1px solid #dddddd; + border-collapse: collapse !important; + border-radius: 1px; +} + +.bootstrap-table .table, +.bootstrap-table .table > tbody > tr > th, +.bootstrap-table .table > tfoot > tr > th, +.bootstrap-table .table > thead > tr > td, +.bootstrap-table .table > tbody > tr > td, +.bootstrap-table .table > tfoot > tr > td { + padding: 8px !important; +} + +.bootstrap-table .table.table-no-bordered > thead > tr > th, +.bootstrap-table .table.table-no-bordered > tbody > tr > td { + border-right: 2px solid transparent; +} + +.fixed-table-container { + position: relative; + clear: both; + border: 1px solid #dddddd; + border-radius: 4px; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; +} + +.fixed-table-container.table-no-bordered { + border: 1px solid transparent; +} + +.fixed-table-footer, +.fixed-table-header { + height: 37px; /*cellHeight*/ + overflow: hidden; + border-radius: 4px 4px 0 0; + -webkit-border-radius: 4px 4px 0 0; + -moz-border-radius: 4px 4px 0 0; +} + +.fixed-table-header { + border-bottom: 1px solid #dddddd; +} + +.fixed-table-footer { + border-top: 1px solid #dddddd; +} + +.fixed-table-body { + overflow-x: auto; + overflow-y: auto; + height: 100%; +} + +.fixed-table-container table { + width: 100%; +} + +.fixed-table-container thead th { + height: 0; + padding: 0; + margin: 0; + border-left: 1px solid #dddddd; +} + +.fixed-table-container thead th:first-child { + border-left: none; + border-top-left-radius: 4px; + -webkit-border-top-left-radius: 4px; + -moz-border-radius-topleft: 4px; +} + +.fixed-table-container thead th .th-inner { + padding: 8px; + line-height: 24px; + vertical-align: top; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.fixed-table-container thead th .sortable { + cursor: pointer; + background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAATCAQAAADYWf5HAAAAkElEQVQoz7X QMQ5AQBCF4dWQSJxC5wwax1Cq1e7BAdxD5SL+Tq/QCM1oNiJidwox0355mXnG/DrEtIQ6azioNZQxI0ykPhTQIwhCR+BmBYtlK7kLJYwWCcJA9M4qdrZrd8pPjZWPtOqdRQy320YSV17OatFC4euts6z39GYMKRPCTKY9UnPQ6P+GtMRfGtPnBCiqhAeJPmkqAAAAAElFTkSuQmCC'); + background-position: right; + background-repeat: no-repeat; + padding-right: 30px; +} + +.fixed-table-container th.detail { + width: 30px; +} + +.fixed-table-container tbody td { + border-left: 1px solid #dddddd; +} + +.fixed-table-container tbody tr:first-child td { + border-top: none; +} + +.fixed-table-container tbody td:first-child { + border-left: none; +} + +/* the same color with .active */ +.fixed-table-container tbody .selected td { + background-color: #f5f5f5; +} + +.fixed-table-container .bs-checkbox { + text-align: center; +} + +.fixed-table-container .bs-checkbox .th-inner { + padding: 8px 0; +} + +.fixed-table-container input[type="radio"], +.fixed-table-container input[type="checkbox"] { + margin: 0 auto !important; +} + +.fixed-table-container .no-records-found { + text-align: center; +} + +.fixed-table-pagination div.pagination, +.fixed-table-pagination .pagination-detail { + margin-top: 10px; + margin-bottom: 10px; +} + +.fixed-table-pagination div.pagination .pagination { + margin: 0; +} + +.fixed-table-pagination .pagination a { + padding: 6px 12px; + line-height: 1.428571429; +} + +.fixed-table-pagination .pagination-info { + line-height: 34px; + margin-right: 5px; +} + +.fixed-table-pagination .btn-group { + position: relative; + display: inline-block; + vertical-align: middle; +} + +.fixed-table-pagination .dropup .dropdown-menu { + margin-bottom: 0; +} + +.fixed-table-pagination .page-list { + display: inline-block; +} + +.fixed-table-toolbar .columns-left { + margin-right: 5px; +} + +.fixed-table-toolbar .columns-right { + margin-left: 5px; +} + +.fixed-table-toolbar .columns label { + display: block; + padding: 3px 20px; + clear: both; + font-weight: normal; + line-height: 1.428571429; +} + +.fixed-table-toolbar .bars, +.fixed-table-toolbar .search, +.fixed-table-toolbar .columns { + position: relative; + margin-top: 10px; + margin-bottom: 10px; + line-height: 34px; +} + +.fixed-table-pagination li.disabled a { + pointer-events: none; + cursor: default; +} + +.fixed-table-loading { + display: none; + position: absolute; + top: 42px; + right: 0; + bottom: 0; + left: 0; + z-index: 99; + background-color: #fff; + text-align: center; +} + +.fixed-table-body .card-view .title { + font-weight: bold; + display: inline-block; + min-width: 30%; + text-align: left !important; +} + +/* support bootstrap 2 */ +.fixed-table-body thead th .th-inner { + box-sizing: border-box; +} + +.table th, .table td { + vertical-align: middle; + box-sizing: border-box; +} + +.fixed-table-toolbar .dropdown-menu { + text-align: left; + max-height: 300px; + overflow: auto; +} + +.fixed-table-toolbar .btn-group > .btn-group { + display: inline-block; + margin-left: -1px !important; +} + +.fixed-table-toolbar .btn-group > .btn-group > .btn { + border-radius: 0; +} + +.fixed-table-toolbar .btn-group > .btn-group:first-child > .btn { + border-top-left-radius: 4px; + border-bottom-left-radius: 4px; +} + +.fixed-table-toolbar .btn-group > .btn-group:last-child > .btn { + border-top-right-radius: 4px; + border-bottom-right-radius: 4px; +} + +.bootstrap-table .table > thead > tr > th { + vertical-align: bottom; + border-bottom: 2px solid #ddd; +} + +/* support bootstrap 3 */ +.bootstrap-table .table thead > tr > th { + padding: 0; + margin: 0; +} + +.pull-right .dropdown-menu { + right: 0; + left: auto; +} + +/* calculate scrollbar width */ +p.fixed-table-scroll-inner { + width: 100%; + height: 200px; +} + +div.fixed-table-scroll-outer { + top: 0; + left: 0; + visibility: hidden; + width: 200px; + height: 150px; + overflow: hidden; +} From 5eedd7810f007862b72914f78cd9680d99baa43d Mon Sep 17 00:00:00 2001 From: madd15 <joshdeakin@adam.com.au> Date: Tue, 28 Jul 2015 13:55:06 +0930 Subject: [PATCH 007/120] Create bootstrap-table.js --- public/assets/js/bootstrap-table.js | 2301 +++++++++++++++++++++++++++ 1 file changed, 2301 insertions(+) create mode 100644 public/assets/js/bootstrap-table.js diff --git a/public/assets/js/bootstrap-table.js b/public/assets/js/bootstrap-table.js new file mode 100644 index 0000000000..918045e4bb --- /dev/null +++ b/public/assets/js/bootstrap-table.js @@ -0,0 +1,2301 @@ +/** + * @author zhixin wen <wenzhixin2010@gmail.com> + * version: 1.8.1 + * https://github.com/wenzhixin/bootstrap-table/ + */ + +!function ($) { + 'use strict'; + + // TOOLS DEFINITION + // ====================== + + var cellHeight = 37, // update css if changed + cachedWidth = null, + arrowAsc = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAATCAYAAAByUDbMAAAAZ' + + '0lEQVQ4y2NgGLKgquEuFxBPAGI2ahhWCsS/gDibUoO0gPgxEP8H4ttArEyuQYxAPBd' + + 'qEAxPBImTY5gjEL9DM+wTENuQahAvEO9DMwiGdwAxOymGJQLxTyD+jgWDxCMZRsEoGAVo' + + 'AADeemwtPcZI2wAAAABJRU5ErkJggg==', + arrowBoth = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAATCAQAAADYWf5HAAAAkElEQVQoz7X' + + 'QMQ5AQBCF4dWQSJxC5wwax1Cq1e7BAdxD5SL+Tq/QCM1oNiJidwox0355mXnG/DrEtIQ6azio' + + 'NZQxI0ykPhTQIwhCR+BmBYtlK7kLJYwWCcJA9M4qdrZrd8pPjZWPtOqdRQy320YSV17OatFC4eut' + + 's6z39GYMKRPCTKY9UnPQ6P+GtMRfGtPnBCiqhAeJPmkqAAAAAElFTkSuQmCC', + arrowDesc = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAATCAYAAAByUDbMAAAAZUlEQVQ4y2NgGAWj' + + 'YBSggaqGu5FA/BOIv2PBIPFEUgxjB+IdQPwfC94HxLykus4GiD+hGfQOiB3J8SojEE9EM2wuSJ' + + 'zcsFMG4ttQgx4DsRalkZENxL+AuJQaMcsGxBOAmGvopk8AVz1sLZgg0bsAAAAASUVORK5CYII= '; + + // it only does '%s', and return '' when arguments are undefined + var sprintf = function (str) { + var args = arguments, + flag = true, + i = 1; + + str = str.replace(/%s/g, function () { + var arg = args[i++]; + + if (typeof arg === 'undefined') { + flag = false; + return ''; + } + return arg; + }); + return flag ? str : ''; + }; + + var getPropertyFromOther = function (list, from, to, value) { + var result = ''; + $.each(list, function (i, item) { + if (item[from] === value) { + result = item[to]; + return false; + } + return true; + }); + return result; + }; + + var getFieldIndex = function (columns, field) { + var index = -1; + + $.each(columns, function (i, column) { + if (column.field === field) { + index = i; + return false; + } + return true; + }); + return index; + }; + + var getScrollBarWidth = function () { + if (cachedWidth === null) { + var inner = $('<p/>').addClass('fixed-table-scroll-inner'), + outer = $('<div/>').addClass('fixed-table-scroll-outer'), + w1, w2; + + outer.append(inner); + $('body').append(outer); + + w1 = inner[0].offsetWidth; + outer.css('overflow', 'scroll'); + w2 = inner[0].offsetWidth; + + if (w1 === w2) { + w2 = outer[0].clientWidth; + } + + outer.remove(); + cachedWidth = w1 - w2; + } + return cachedWidth; + }; + + var calculateObjectValue = function (self, name, args, defaultValue) { + var func = name; + + if (typeof name === 'string') { + // support obj.func1.func2 + var names = name.split('.'); + + if (names.length > 1) { + func = window; + $.each(names, function (i, f) { + func = func[f]; + }); + } else { + func = window[name]; + } + } + if (typeof func === 'object') { + return func; + } + if (typeof func === 'function') { + return func.apply(self, args); + } + if (!func && typeof name === 'string' && sprintf.apply(this, [name].concat(args))) { + return sprintf.apply(this, [name].concat(args)); + } + return defaultValue; + }; + + var escapeHTML = function (text) { + if (typeof text === 'string') { + return text + .replace(/&/g, "&") + .replace(/</g, "<") + .replace(/>/g, ">") + .replace(/"/g, """) + .replace(/'/g, "'"); + } + return text; + }; + + var getRealHeight = function ($el) { + var height = 0; + $el.children().each(function () { + if (height < $(this).outerHeight(true)) { + height = $(this).outerHeight(true); + } + }); + return height; + }; + + var getRealDataAttr = function (dataAttr) { + for (var attr in dataAttr) { + var auxAttr = attr.split(/(?=[A-Z])/).join('-').toLowerCase(); + if (auxAttr !== attr) { + dataAttr[auxAttr] = dataAttr[attr]; + delete dataAttr[attr]; + } + } + + return dataAttr; + }; + + // BOOTSTRAP TABLE CLASS DEFINITION + // ====================== + + var BootstrapTable = function (el, options) { + this.options = options; + this.$el = $(el); + this.$el_ = this.$el.clone(); + this.timeoutId_ = 0; + this.timeoutFooter_ = 0; + + this.init(); + }; + + BootstrapTable.DEFAULTS = { + classes: 'table table-hover', + height: undefined, + undefinedText: '-', + sortName: undefined, + sortOrder: 'asc', + striped: false, + columns: [], + data: [], + method: 'get', + url: undefined, + ajax: undefined, + cache: true, + contentType: 'application/json', + dataType: 'json', + ajaxOptions: {}, + queryParams: function (params) { + return params; + }, + queryParamsType: 'limit', // undefined + responseHandler: function (res) { + return res; + }, + pagination: false, + sidePagination: 'client', // client or server + totalRows: 0, // server side need to set + pageNumber: 1, + pageSize: 10, + pageList: [10, 25, 50, 100], + paginationHAlign: 'right', //right, left + paginationVAlign: 'bottom', //bottom, top, both + paginationDetailHAlign: 'left', //right, left + paginationFirstText: '«', + paginationPreText: '‹', + paginationNextText: '›', + paginationLastText: '»', + search: false, + searchAlign: 'right', + selectItemName: 'btSelectItem', + showHeader: true, + showFooter: false, + showColumns: false, + showPaginationSwitch: false, + showRefresh: false, + showToggle: false, + buttonsAlign: 'right', + smartDisplay: true, + minimumCountColumns: 1, + idField: undefined, + uniqueId: undefined, + cardView: false, + detailView: false, + detailFormatter: function (index, row) { + return ''; + }, + trimOnSearch: true, + clickToSelect: false, + singleSelect: false, + toolbar: undefined, + toolbarAlign: 'left', + checkboxHeader: true, + sortable: true, + maintainSelected: false, + searchTimeOut: 500, + searchText: '', + iconSize: undefined, + iconsPrefix: 'glyphicon', // glyphicon of fa (font awesome) + icons: { + paginationSwitchDown: 'glyphicon-collapse-down icon-chevron-down', + paginationSwitchUp: 'glyphicon-collapse-up icon-chevron-up', + refresh: 'glyphicon-refresh icon-refresh', + toggle: 'glyphicon-list-alt icon-list-alt', + columns: 'glyphicon-th icon-th' + }, + + rowStyle: function (row, index) { + return {}; + }, + + rowAttributes: function (row, index) { + return {}; + }, + + onAll: function (name, args) { + return false; + }, + onClickCell: function (field, value, row, $element) { + return false; + }, + onDblClickCell: function (field, value, row, $element) { + return false; + }, + onClickRow: function (item, $element) { + return false; + }, + onDblClickRow: function (item, $element) { + return false; + }, + onSort: function (name, order) { + return false; + }, + onCheck: function (row) { + return false; + }, + onUncheck: function (row) { + return false; + }, + onCheckAll: function (rows) { + return false; + }, + onUncheckAll: function (rows) { + return false; + }, + onCheckSome: function(rows){ + return false; + }, + onUncheckSome: function(rows){ + return false; + }, + onLoadSuccess: function (data) { + return false; + }, + onLoadError: function (status) { + return false; + }, + onColumnSwitch: function (field, checked) { + return false; + }, + onPageChange: function (number, size) { + return false; + }, + onSearch: function (text) { + return false; + }, + onToggle: function (cardView) { + return false; + }, + onPreBody: function (data) { + return false; + }, + onPostBody: function () { + return false; + }, + onPostHeader: function () { + return false; + }, + onExpandRow: function (index, row, $detail) { + return false; + }, + onCollapseRow: function (index, row) { + return false; + } + }; + + BootstrapTable.LOCALES = []; + + BootstrapTable.LOCALES['en-US'] = { + formatLoadingMessage: function () { + return 'Loading, please wait...'; + }, + formatRecordsPerPage: function (pageNumber) { + return sprintf('%s records per page', pageNumber); + }, + formatShowingRows: function (pageFrom, pageTo, totalRows) { + return sprintf('Showing %s to %s of %s rows', pageFrom, pageTo, totalRows); + }, + formatSearch: function () { + return 'Search'; + }, + formatNoMatches: function () { + return 'No matching records found'; + }, + formatPaginationSwitch: function () { + return 'Hide/Show pagination'; + }, + formatRefresh: function () { + return 'Refresh'; + }, + formatToggle: function () { + return 'Toggle'; + }, + formatColumns: function () { + return 'Columns'; + }, + formatAllRows: function () { + return 'All'; + } + }; + + $.extend(BootstrapTable.DEFAULTS, BootstrapTable.LOCALES['en-US']); + + BootstrapTable.COLUMN_DEFAULTS = { + radio: false, + checkbox: false, + checkboxEnabled: true, + field: undefined, + title: undefined, + 'class': undefined, + align: undefined, // left, right, center + halign: undefined, // left, right, center + falign: undefined, // left, right, center + valign: undefined, // top, middle, bottom + width: undefined, + sortable: false, + order: 'asc', // asc, desc + visible: true, + switchable: true, + clickToSelect: true, + formatter: undefined, + footerFormatter: undefined, + events: undefined, + sorter: undefined, + sortName: undefined, + cellStyle: undefined, + searchable: true, + cardVisible: true + }; + + BootstrapTable.EVENTS = { + 'all.bs.table': 'onAll', + 'click-cell.bs.table': 'onClickCell', + 'dbl-click-cell.bs.table': 'onDblClickCell', + 'click-row.bs.table': 'onClickRow', + 'dbl-click-row.bs.table': 'onDblClickRow', + 'sort.bs.table': 'onSort', + 'check.bs.table': 'onCheck', + 'uncheck.bs.table': 'onUncheck', + 'check-all.bs.table': 'onCheckAll', + 'uncheck-all.bs.table': 'onUncheckAll', + 'check-some.bs.table': 'onCheckSome', + 'uncheck-some.bs.table': 'onUncheckSome', + 'load-success.bs.table': 'onLoadSuccess', + 'load-error.bs.table': 'onLoadError', + 'column-switch.bs.table': 'onColumnSwitch', + 'page-change.bs.table': 'onPageChange', + 'search.bs.table': 'onSearch', + 'toggle.bs.table': 'onToggle', + 'pre-body.bs.table': 'onPreBody', + 'post-body.bs.table': 'onPostBody', + 'post-header.bs.table': 'onPostHeader', + 'expand-row.bs.table': 'onExpandRow', + 'collapse-row.bs.table': 'onCollapseRow' + }; + + BootstrapTable.prototype.init = function () { + this.initContainer(); + this.initTable(); + this.initHeader(); + this.initData(); + this.initFooter(); + this.initToolbar(); + this.initPagination(); + this.initBody(); + this.initServer(); + }; + + BootstrapTable.prototype.initContainer = function () { + this.$container = $([ + '<div class="bootstrap-table">', + '<div class="fixed-table-toolbar"></div>', + this.options.paginationVAlign === 'top' || this.options.paginationVAlign === 'both' ? + '<div class="fixed-table-pagination" style="clear: both;"></div>' : + '', + '<div class="fixed-table-container">', + '<div class="fixed-table-header"><table></table></div>', + '<div class="fixed-table-body">', + '<div class="fixed-table-loading">', + this.options.formatLoadingMessage(), + '</div>', + '</div>', + '<div class="fixed-table-footer"><table><tr></tr></table></div>', + this.options.paginationVAlign === 'bottom' || this.options.paginationVAlign === 'both' ? + '<div class="fixed-table-pagination"></div>' : + '', + '</div>', + '</div>'].join('')); + + this.$container.insertAfter(this.$el); + this.$tableContainer = this.$container.find('.fixed-table-container'); + this.$tableHeader = this.$container.find('.fixed-table-header'); + this.$tableBody = this.$container.find('.fixed-table-body'); + this.$tableLoading = this.$container.find('.fixed-table-loading'); + this.$tableFooter = this.$container.find('.fixed-table-footer'); + this.$toolbar = this.$container.find('.fixed-table-toolbar'); + this.$pagination = this.$container.find('.fixed-table-pagination'); + + this.$tableBody.append(this.$el); + this.$container.after('<div class="clearfix"></div>'); + + this.$el.addClass(this.options.classes); + if (this.options.striped) { + this.$el.addClass('table-striped'); + } + if ($.inArray('table-no-bordered', this.options.classes.split(' ')) !== -1) { + this.$tableContainer.addClass('table-no-bordered'); + } + }; + + BootstrapTable.prototype.initTable = function () { + var that = this, + columns = [], + data = []; + + this.$header = this.$el.find('thead'); + if (!this.$header.length) { + this.$header = $('<thead></thead>').appendTo(this.$el); + } + if (!this.$header.find('tr').length) { + this.$header.append('<tr></tr>'); + } + this.$header.find('th').each(function () { + var column = $.extend({}, { + title: $(this).html(), + 'class': $(this).attr('class') + }, $(this).data()); + + columns.push(column); + }); + this.options.columns = $.extend(true, [], columns, this.options.columns); + $.each(this.options.columns, function (i, column) { + that.options.columns[i] = $.extend({}, BootstrapTable.COLUMN_DEFAULTS, + {field: i}, column); // when field is undefined, use index instead + }); + + // if options.data is setting, do not process tbody data + if (this.options.data.length) { + return; + } + + this.$el.find('tbody tr').each(function () { + var row = {}; + + // save tr's id, class and data-* attributes + row._id = $(this).attr('id'); + row._class = $(this).attr('class'); + row._data = getRealDataAttr($(this).data()); + + $(this).find('td').each(function (i) { + var field = that.options.columns[i].field; + + row[field] = $(this).html(); + // save td's id, class and data-* attributes + row['_' + field + '_id'] = $(this).attr('id'); + row['_' + field + '_class'] = $(this).attr('class'); + row['_' + field + '_rowspan'] = $(this).attr('rowspan'); + row['_' + field + '_data'] = getRealDataAttr($(this).data()); + }); + data.push(row); + }); + this.options.data = data; + }; + + BootstrapTable.prototype.initHeader = function () { + var that = this, + visibleColumns = [], + html = [], + timeoutId = 0; + + this.header = { + fields: [], + styles: [], + classes: [], + formatters: [], + events: [], + sorters: [], + sortNames: [], + cellStyles: [], + clickToSelects: [], + searchables: [] + }; + + if (!this.options.cardView && this.options.detailView) { + html.push('<th class="detail"><div class="fht-cell"></div></th>'); + visibleColumns.push({}); + } + + $.each(this.options.columns, function (i, column) { + var text = '', + halign = '', // header align style + align = '', // body align style + style = '', + class_ = sprintf(' class="%s"', column['class']), + order = that.options.sortOrder || column.order, + unitWidth = 'px', + width = column.width; + + if (!column.visible) { + // Fix #229. Default Sort order is wrong + // if data-visible="false" is set on the field referenced by data-sort-name. + if (column.field === that.options.sortName) { + that.header.fields.push(column.field); + } + return; + } + + if (that.options.cardView && (!column.cardVisible)) { + return; + } + + if (column.width !== undefined && (!that.options.cardView)) { + if (typeof column.width === 'string') { + if (column.width.indexOf('%') !== -1) { + unitWidth = '%'; + } + } + } + if (column.width && typeof column.width === 'string') { + width = column.width.replace('%', '').replace('px', ''); + } + + halign = sprintf('text-align: %s; ', column.halign ? column.halign : column.align); + align = sprintf('text-align: %s; ', column.align); + style = sprintf('vertical-align: %s; ', column.valign); + style += sprintf('width: %s%s; ', column.checkbox || column.radio ? 36 : width, unitWidth); + + visibleColumns.push(column); + that.header.fields.push(column.field); + that.header.styles.push(align + style); + that.header.classes.push(class_); + that.header.formatters.push(column.formatter); + that.header.events.push(column.events); + that.header.sorters.push(column.sorter); + that.header.sortNames.push(column.sortName); + that.header.cellStyles.push(column.cellStyle); + that.header.clickToSelects.push(column.clickToSelect); + that.header.searchables.push(column.searchable); + + html.push('<th', + column.checkbox || column.radio ? + sprintf(' class="bs-checkbox %s"', column['class'] || '') : + class_, + sprintf(' style="%s"', halign + style), + '>'); + + html.push(sprintf('<div class="th-inner %s">', that.options.sortable && column.sortable ? + 'sortable' : '')); + + text = column.title; + + if (column.checkbox) { + if (!that.options.singleSelect && that.options.checkboxHeader) { + text = '<input name="btSelectAll" type="checkbox" />'; + } + that.header.stateField = column.field; + } + if (column.radio) { + text = ''; + that.header.stateField = column.field; + that.options.singleSelect = true; + } + + html.push(text); + html.push('</div>'); + html.push('<div class="fht-cell"></div>'); + html.push('</div>'); + html.push('</th>'); + }); + + this.$header.find('tr').html(html.join('')); + this.$header.find('th').each(function (i) { + $(this).data(visibleColumns[i]); + }); + this.$container.off('click', '.th-inner').on('click', '.th-inner', function (event) { + if (that.options.sortable && $(this).parent().data().sortable) { + that.onSort(event); + } + }); + + if (!this.options.showHeader || this.options.cardView) { + this.$header.hide(); + this.$tableHeader.hide(); + this.$tableLoading.css('top', 0); + } else { + this.$header.show(); + this.$tableHeader.show(); + this.$tableLoading.css('top', cellHeight + 'px'); + // Assign the correct sortable arrow + this.getCaretHtml(); + } + + this.$selectAll = this.$header.find('[name="btSelectAll"]'); + this.$container.off('click', '[name="btSelectAll"]') + .on('click', '[name="btSelectAll"]', function () { + var checked = $(this).prop('checked'); + that[checked ? 'checkAll' : 'uncheckAll'](); + }); + }; + + BootstrapTable.prototype.initFooter = function () { + if (!this.options.showFooter || this.options.cardView) { + this.$tableFooter.hide(); + } else { + this.$tableFooter.show(); + } + }; + + /** + * @param data + * @param type: append / prepend + */ + BootstrapTable.prototype.initData = function (data, type) { + if (type === 'append') { + this.data = this.data.concat(data); + } else if (type === 'prepend') { + this.data = [].concat(data).concat(this.data); + } else { + this.data = data || this.options.data; + } + + // Fix #839 Records deleted when adding new row on filtered table + if (type === 'append') { + this.options.data = this.options.data.concat(data); + } else if (type === 'prepend') { + this.options.data = [].concat(data).concat(this.options.data); + } else { + this.options.data = this.data; + } + + if (this.options.sidePagination === 'server') { + return; + } + this.initSort(); + }; + + BootstrapTable.prototype.initSort = function () { + var that = this, + name = this.options.sortName, + order = this.options.sortOrder === 'desc' ? -1 : 1, + index = $.inArray(this.options.sortName, this.header.fields); + + if (index !== -1) { + this.data.sort(function (a, b) { + if (that.header.sortNames[index]) { + name = that.header.sortNames[index]; + } + var aa = a[name], + bb = b[name], + value = calculateObjectValue(that.header, that.header.sorters[index], [aa, bb]); + + if (value !== undefined) { + return order * value; + } + + // Fix #161: undefined or null string sort bug. + if (aa === undefined || aa === null) { + aa = ''; + } + if (bb === undefined || bb === null) { + bb = ''; + } + + // IF both values are numeric, do a numeric comparison + if ($.isNumeric(aa) && $.isNumeric(bb)) { + // Convert numerical values form string to float. + aa = parseFloat(aa); + bb = parseFloat(bb); + if (aa < bb) { + return order * -1; + } + return order; + } + + if (aa === bb) { + return 0; + } + + // If value is not a string, convert to string + if (typeof aa !== 'string') { + aa = aa.toString(); + } + + if (aa.localeCompare(bb) === -1) { + return order * -1; + } + + return order; + }); + } + }; + + BootstrapTable.prototype.onSort = function (event) { + var $this = $(event.currentTarget).parent(), + $this_ = this.$header.find('th').eq($this.index()); + + this.$header.add(this.$header_).find('span.order').remove(); + + if (this.options.sortName === $this.data('field')) { + this.options.sortOrder = this.options.sortOrder === 'asc' ? 'desc' : 'asc'; + } else { + this.options.sortName = $this.data('field'); + this.options.sortOrder = $this.data('order') === 'asc' ? 'desc' : 'asc'; + } + this.trigger('sort', this.options.sortName, this.options.sortOrder); + + $this.add($this_).data('order', this.options.sortOrder); + + // Assign the correct sortable arrow + this.getCaretHtml(); + + if (this.options.sidePagination === 'server') { + this.initServer(); + return; + } + + this.initSort(); + this.initBody(); + }; + + BootstrapTable.prototype.initToolbar = function () { + var that = this, + html = [], + timeoutId = 0, + $keepOpen, + $search, + switchableCount = 0; + + this.$toolbar.html(''); + + if (typeof this.options.toolbar === 'string') { + $(sprintf('<div class="bars pull-%s"></div>', this.options.toolbarAlign)) + .appendTo(this.$toolbar) + .append($(this.options.toolbar)); + } + + // showColumns, showToggle, showRefresh + html = [sprintf('<div class="columns columns-%s btn-group pull-%s">', + this.options.buttonsAlign, this.options.buttonsAlign)]; + + if (typeof this.options.icons === 'string') { + this.options.icons = calculateObjectValue(null, this.options.icons); + } + + if (this.options.showPaginationSwitch) { + html.push(sprintf('<button class="btn btn-default" type="button" name="paginationSwitch" title="%s">', + this.options.formatPaginationSwitch()), + sprintf('<i class="%s %s"></i>', this.options.iconsPrefix, this.options.icons.paginationSwitchDown), + '</button>'); + } + + if (this.options.showRefresh) { + html.push(sprintf('<button class="btn btn-default' + (this.options.iconSize === undefined ? '' : ' btn-' + this.options.iconSize) + '" type="button" name="refresh" title="%s">', + this.options.formatRefresh()), + sprintf('<i class="%s %s"></i>', this.options.iconsPrefix, this.options.icons.refresh), + '</button>'); + } + + if (this.options.showToggle) { + html.push(sprintf('<button class="btn btn-default' + (this.options.iconSize === undefined ? '' : ' btn-' + this.options.iconSize) + '" type="button" name="toggle" title="%s">', + this.options.formatToggle()), + sprintf('<i class="%s %s"></i>', this.options.iconsPrefix, this.options.icons.toggle), + '</button>'); + } + + if (this.options.showColumns) { + html.push(sprintf('<div class="keep-open btn-group" title="%s">', + this.options.formatColumns()), + '<button type="button" class="btn btn-default' + (this.options.iconSize == undefined ? '' : ' btn-' + this.options.iconSize) + ' dropdown-toggle" data-toggle="dropdown">', + sprintf('<i class="%s %s"></i>', this.options.iconsPrefix, this.options.icons.columns), + ' <span class="caret"></span>', + '</button>', + '<ul class="dropdown-menu" role="menu">'); + + $.each(this.options.columns, function (i, column) { + if (column.radio || column.checkbox) { + return; + } + + if (that.options.cardView && (!column.cardVisible)) { + return; + } + + var checked = column.visible ? ' checked="checked"' : ''; + + if (column.switchable) { + html.push(sprintf('<li>' + + '<label><input type="checkbox" data-field="%s" value="%s"%s> %s</label>' + + '</li>', column.field, i, checked, column.title)); + switchableCount++; + } + }); + html.push('</ul>', + '</div>'); + } + + html.push('</div>'); + + // Fix #188: this.showToolbar is for extentions + if (this.showToolbar || html.length > 2) { + this.$toolbar.append(html.join('')); + } + + if (this.options.showPaginationSwitch) { + this.$toolbar.find('button[name="paginationSwitch"]') + .off('click').on('click', $.proxy(this.togglePagination, this)); + } + + if (this.options.showRefresh) { + this.$toolbar.find('button[name="refresh"]') + .off('click').on('click', $.proxy(this.refresh, this)); + } + + if (this.options.showToggle) { + this.$toolbar.find('button[name="toggle"]') + .off('click').on('click', function () { + that.toggleView(); + }); + } + + if (this.options.showColumns) { + $keepOpen = this.$toolbar.find('.keep-open'); + + if (switchableCount <= this.options.minimumCountColumns) { + $keepOpen.find('input').prop('disabled', true); + } + + $keepOpen.find('li').off('click').on('click', function (event) { + event.stopImmediatePropagation(); + }); + $keepOpen.find('input').off('click').on('click', function () { + var $this = $(this); + + that.toggleColumn(getFieldIndex(that.options.columns, $(this).data('field')), $this.prop('checked'), false); + that.trigger('column-switch', $(this).data('field'), $this.prop('checked')); + }); + } + + if (this.options.search) { + html = []; + html.push( + '<div class="pull-' + this.options.searchAlign + ' search">', + sprintf('<input class="form-control' + (this.options.iconSize === undefined ? '' : ' input-' + this.options.iconSize) + '" type="text" placeholder="%s">', + this.options.formatSearch()), + '</div>'); + + this.$toolbar.append(html.join('')); + $search = this.$toolbar.find('.search input'); + $search.off('keyup drop').on('keyup drop', function (event) { + clearTimeout(timeoutId); // doesn't matter if it's 0 + timeoutId = setTimeout(function () { + that.onSearch(event); + }, that.options.searchTimeOut); + }); + + if (this.options.searchText !== '') { + $search.val(this.options.searchText); + clearTimeout(timeoutId); // doesn't matter if it's 0 + timeoutId = setTimeout(function () { + $search.trigger('keyup'); + }, that.options.searchTimeOut); + } + } + }; + + BootstrapTable.prototype.onSearch = function (event) { + var text = $.trim($(event.currentTarget).val()); + + // trim search input + if (this.options.trimOnSearch && $(event.currentTarget).val() !== text) { + $(event.currentTarget).val(text); + } + + if (text === this.searchText) { + return; + } + this.searchText = text; + + this.options.pageNumber = 1; + this.initSearch(); + this.updatePagination(); + this.trigger('search', text); + }; + + BootstrapTable.prototype.initSearch = function () { + var that = this; + + if (this.options.sidePagination !== 'server') { + var s = this.searchText && this.searchText.toLowerCase(); + var f = $.isEmptyObject(this.filterColumns) ? null : this.filterColumns; + + // Check filter + this.data = f ? $.grep(this.options.data, function (item, i) { + for (var key in f) { + if (item[key] !== f[key]) { + return false; + } + } + return true; + }) : this.options.data; + + this.data = s ? $.grep(this.data, function (item, i) { + for (var key in item) { + key = $.isNumeric(key) ? parseInt(key, 10) : key; + var value = item[key], + column = that.options.columns[getFieldIndex(that.options.columns, key)], + j = $.inArray(key, that.header.fields); + + // Fix #142: search use formated data + value = calculateObjectValue(column, + that.header.formatters[j], + [value, item, i], value); + + var index = $.inArray(key, that.header.fields); + if (index !== -1 && that.header.searchables[index] && + (typeof value === 'string' || + typeof value === 'number') && + (value + '').toLowerCase().indexOf(s) !== -1) { + return true; + } + } + return false; + }) : this.data; + } + }; + + BootstrapTable.prototype.initPagination = function () { + if (!this.options.pagination) { + this.$pagination.hide(); + return; + } else { + this.$pagination.show(); + } + + var that = this, + html = [], + $allSelected = false, + i, from, to, + $pageList, + $first, $pre, + $next, $last, + $number, + data = this.getData(); + + if (this.options.sidePagination !== 'server') { + this.options.totalRows = data.length; + } + + this.totalPages = 0; + if (this.options.totalRows) { + if (this.options.pageSize === this.options.formatAllRows()) { + this.options.pageSize = this.options.totalRows; + $allSelected = true; + } else if (this.options.pageSize === this.options.totalRows) { + // Fix #667 Table with pagination, multiple pages and a search that matches to one page throws exception + var pageLst = typeof this.options.pageList === 'string' ? + this.options.pageList.replace('[', '').replace(']', '').replace(/ /g, '').toLowerCase().split(',') : + this.options.pageList; + if (pageLst.indexOf(this.options.formatAllRows().toLowerCase()) > -1) { + $allSelected = true; + } + } + + this.totalPages = ~~((this.options.totalRows - 1) / this.options.pageSize) + 1; + + this.options.totalPages = this.totalPages; + } + if (this.totalPages > 0 && this.options.pageNumber > this.totalPages) { + this.options.pageNumber = this.totalPages; + } + + this.pageFrom = (this.options.pageNumber - 1) * this.options.pageSize + 1; + this.pageTo = this.options.pageNumber * this.options.pageSize; + if (this.pageTo > this.options.totalRows) { + this.pageTo = this.options.totalRows; + } + + html.push( + '<div class="pull-' + this.options.paginationDetailHAlign + ' pagination-detail">', + '<span class="pagination-info">', + this.options.formatShowingRows(this.pageFrom, this.pageTo, this.options.totalRows), + '</span>'); + + html.push('<span class="page-list">'); + + var pageNumber = [ + sprintf('<span class="btn-group %s">', this.options.paginationVAlign === 'top' || this.options.paginationVAlign === 'both' ? + 'dropdown' : 'dropup'), + '<button type="button" class="btn btn-default ' + (this.options.iconSize === undefined ? '' : ' btn-' + this.options.iconSize) + ' dropdown-toggle" data-toggle="dropdown">', + '<span class="page-size">', + $allSelected ? this.options.formatAllRows() : this.options.pageSize, + '</span>', + ' <span class="caret"></span>', + '</button>', + '<ul class="dropdown-menu" role="menu">'], + pageList = this.options.pageList; + + if (typeof this.options.pageList === 'string') { + var list = this.options.pageList.replace('[', '').replace(']', '').replace(/ /g, '').split(','); + + pageList = []; + $.each(list, function (i, value) { + pageList.push(value.toUpperCase() === that.options.formatAllRows().toUpperCase() ? + that.options.formatAllRows() : +value); + }); + } + + $.each(pageList, function (i, page) { + if (!that.options.smartDisplay || i === 0 || pageList[i - 1] <= that.options.totalRows) { + var active; + if ($allSelected) { + active = page === that.options.formatAllRows() ? ' class="active"' : ''; + } else { + active = page === that.options.pageSize ? ' class="active"' : ''; + } + pageNumber.push(sprintf('<li%s><a href="javascript:void(0)">%s</a></li>', active, page)); + } + }); + pageNumber.push('</ul></span>'); + + html.push(this.options.formatRecordsPerPage(pageNumber.join(''))); + html.push('</span>'); + + html.push('</div>', + '<div class="pull-' + this.options.paginationHAlign + ' pagination">', + '<ul class="pagination' + (this.options.iconSize === undefined ? '' : ' pagination-' + this.options.iconSize) + '">', + '<li class="page-first"><a href="javascript:void(0)">' + this.options.paginationFirstText + '</a></li>', + '<li class="page-pre"><a href="javascript:void(0)">' + this.options.paginationPreText + '</a></li>'); + + if (this.totalPages < 5) { + from = 1; + to = this.totalPages; + } else { + from = this.options.pageNumber - 2; + to = from + 4; + if (from < 1) { + from = 1; + to = 5; + } + if (to > this.totalPages) { + to = this.totalPages; + from = to - 4; + } + } + for (i = from; i <= to; i++) { + html.push('<li class="page-number' + (i === this.options.pageNumber ? ' active' : '') + '">', + '<a href="javascript:void(0)">', i, '</a>', + '</li>'); + } + + html.push( + '<li class="page-next"><a href="javascript:void(0)">' + this.options.paginationNextText + '</a></li>', + '<li class="page-last"><a href="javascript:void(0)">' + this.options.paginationLastText + '</a></li>', + '</ul>', + '</div>'); + + this.$pagination.html(html.join('')); + + $pageList = this.$pagination.find('.page-list a'); + $first = this.$pagination.find('.page-first'); + $pre = this.$pagination.find('.page-pre'); + $next = this.$pagination.find('.page-next'); + $last = this.$pagination.find('.page-last'); + $number = this.$pagination.find('.page-number'); + + if (this.options.pageNumber <= 1) { + $first.addClass('disabled'); + $pre.addClass('disabled'); + } + if (this.options.pageNumber >= this.totalPages) { + $next.addClass('disabled'); + $last.addClass('disabled'); + } + if (this.options.smartDisplay) { + if (this.totalPages <= 1) { + this.$pagination.find('div.pagination').hide(); + } + if (pageList.length < 2 || this.options.totalRows <= pageList[0]) { + this.$pagination.find('span.page-list').hide(); + } + + // when data is empty, hide the pagination + this.$pagination[this.getData().length ? 'show' : 'hide'](); + } + if ($allSelected) { + this.options.pageSize = this.options.formatAllRows(); + } + $pageList.off('click').on('click', $.proxy(this.onPageListChange, this)); + $first.off('click').on('click', $.proxy(this.onPageFirst, this)); + $pre.off('click').on('click', $.proxy(this.onPagePre, this)); + $next.off('click').on('click', $.proxy(this.onPageNext, this)); + $last.off('click').on('click', $.proxy(this.onPageLast, this)); + $number.off('click').on('click', $.proxy(this.onPageNumber, this)); + }; + + BootstrapTable.prototype.updatePagination = function (event) { + // Fix #171: IE disabled button can be clicked bug. + if (event && $(event.currentTarget).hasClass('disabled')) { + return; + } + + if (!this.options.maintainSelected) { + this.resetRows(); + } + + this.initPagination(); + if (this.options.sidePagination === 'server') { + this.initServer(); + } else { + this.initBody(); + } + + this.trigger('page-change', this.options.pageNumber, this.options.pageSize); + }; + + BootstrapTable.prototype.onPageListChange = function (event) { + var $this = $(event.currentTarget); + + $this.parent().addClass('active').siblings().removeClass('active'); + this.options.pageSize = $this.text().toUpperCase() === this.options.formatAllRows().toUpperCase() ? + this.options.formatAllRows() : +$this.text(); + this.$toolbar.find('.page-size').text(this.options.pageSize); + + this.updatePagination(event); + }; + + BootstrapTable.prototype.onPageFirst = function (event) { + this.options.pageNumber = 1; + this.updatePagination(event); + }; + + BootstrapTable.prototype.onPagePre = function (event) { + this.options.pageNumber--; + this.updatePagination(event); + }; + + BootstrapTable.prototype.onPageNext = function (event) { + this.options.pageNumber++; + this.updatePagination(event); + }; + + BootstrapTable.prototype.onPageLast = function (event) { + this.options.pageNumber = this.totalPages; + this.updatePagination(event); + }; + + BootstrapTable.prototype.onPageNumber = function (event) { + if (this.options.pageNumber === +$(event.currentTarget).text()) { + return; + } + this.options.pageNumber = +$(event.currentTarget).text(); + this.updatePagination(event); + }; + + BootstrapTable.prototype.initBody = function (fixedScroll) { + var that = this, + html = [], + data = this.getData(); + + this.trigger('pre-body', data); + + this.$body = this.$el.find('tbody'); + if (!this.$body.length) { + this.$body = $('<tbody></tbody>').appendTo(this.$el); + } + + //Fix #389 Bootstrap-table-flatJSON is not working + + if (!this.options.pagination || this.options.sidePagination === 'server') { + this.pageFrom = 1; + this.pageTo = data.length; + } + + for (var i = this.pageFrom - 1; i < this.pageTo; i++) { + var key, + item = data[i], + style = {}, + csses = [], + data_ = '', + attributes = {}, + htmlAttributes = []; + + style = calculateObjectValue(this.options, this.options.rowStyle, [item, i], style); + + if (style && style.css) { + for (key in style.css) { + csses.push(key + ': ' + style.css[key]); + } + } + + attributes = calculateObjectValue(this.options, + this.options.rowAttributes, [item, i], attributes); + + if (attributes) { + for (key in attributes) { + htmlAttributes.push(sprintf('%s="%s"', key, escapeHTML(attributes[key]))); + } + } + + if (item._data && !$.isEmptyObject(item._data)) { + $.each(item._data, function (k, v) { + // ignore data-index + if (k === 'index') { + return; + } + data_ += sprintf(' data-%s="%s"', k, v); + }); + } + + html.push('<tr', + sprintf(' %s', htmlAttributes.join(' ')), + sprintf(' id="%s"', $.isArray(item) ? undefined : item._id), + sprintf(' class="%s"', style.classes || ($.isArray(item) ? undefined : item._class)), + sprintf(' data-index="%s"', i), + sprintf(' data-uniqueid="%s"', item[this.options.uniqueId]), + sprintf('%s', data_), + '>' + ); + + if (this.options.cardView) { + html.push(sprintf('<td colspan="%s">', this.header.fields.length)); + } + + if (!this.options.cardView && this.options.detailView) { + html.push('<td>', + '<a class="detail-icon" href="javascript:">', + '<i class="glyphicon glyphicon-plus icon-plus"></i>', + '</a>', + '</td>'); + } + + $.each(this.header.fields, function (j, field) { + var text = '', + value = item[field], + type = '', + cellStyle = {}, + id_ = '', + class_ = that.header.classes[j], + data_ = '', + rowspan_ = '', + column = that.options.columns[getFieldIndex(that.options.columns, field)]; + + style = sprintf('style="%s"', csses.concat(that.header.styles[j]).join('; ')); + + value = calculateObjectValue(column, + that.header.formatters[j], [value, item, i], value); + + // handle td's id and class + if (item['_' + field + '_id']) { + id_ = sprintf(' id="%s"', item['_' + field + '_id']); + } + if (item['_' + field + '_class']) { + class_ = sprintf(' class="%s"', item['_' + field + '_class']); + } + if (item['_' + field + '_rowspan']) { + rowspan_ = sprintf(' rowspan="%s"', item['_' + field + '_rowspan']); + } + cellStyle = calculateObjectValue(that.header, + that.header.cellStyles[j], [value, item, i], cellStyle); + if (cellStyle.classes) { + class_ = sprintf(' class="%s"', cellStyle.classes); + } + if (cellStyle.css) { + var csses_ = []; + for (var key in cellStyle.css) { + csses_.push(key + ': ' + cellStyle.css[key]); + } + style = sprintf('style="%s"', csses_.concat(that.header.styles[j]).join('; ')); + } + + if (item['_' + field + '_data'] && !$.isEmptyObject(item['_' + field + '_data'])) { + $.each(item['_' + field + '_data'], function (k, v) { + // ignore data-index + if (k === 'index') { + return; + } + data_ += sprintf(' data-%s="%s"', k, v); + }); + } + + if (column.checkbox || column.radio) { + type = column.checkbox ? 'checkbox' : type; + type = column.radio ? 'radio' : type; + + text = [that.options.cardView ? + '<div class="card-view">' : '<td class="bs-checkbox">', + '<input' + + sprintf(' data-index="%s"', i) + + sprintf(' name="%s"', that.options.selectItemName) + + sprintf(' type="%s"', type) + + sprintf(' value="%s"', item[that.options.idField]) + + sprintf(' checked="%s"', value === true || + (value && value.checked) ? 'checked' : undefined) + + sprintf(' disabled="%s"', !column.checkboxEnabled || + (value && value.disabled) ? 'disabled' : undefined) + + ' />', + that.options.cardView ? '</div>' : '</td>'].join(''); + + item[that.header.stateField] = value === true || (value && value.checked); + } else { + value = typeof value === 'undefined' || value === null ? + that.options.undefinedText : value; + + text = that.options.cardView ? + ['<div class="card-view">', + that.options.showHeader ? sprintf('<span class="title" %s>%s</span>', style, + getPropertyFromOther(that.options.columns, 'field', 'title', field)) : '', + sprintf('<span class="value">%s</span>', value), + '</div>'].join('') : + [sprintf('<td%s %s %s %s %s>', id_, class_, style, data_, rowspan_), + value, + '</td>'].join(''); + + // Hide empty data on Card view when smartDisplay is set to true. + if (that.options.cardView && that.options.smartDisplay && value === '') { + text = ''; + } + } + + html.push(text); + }); + + if (this.options.cardView) { + html.push('</td>'); + } + + html.push('</tr>'); + } + + // show no records + if (!html.length) { + html.push('<tr class="no-records-found">', + sprintf('<td colspan="%s">%s</td>', + this.$header.find('th').length, this.options.formatNoMatches()), + '</tr>'); + } + + this.$body.html(html.join('')); + + if (!fixedScroll) { + this.scrollTo(0); + } + + // click to select by column + this.$body.find('> tr > td').off('click').on('click', function () { + var $td = $(this), + $tr = $td.parent(), + item = that.data[$tr.data('index')], + cellIndex = $td[0].cellIndex, + $headerCell = that.$header.find('th:eq(' + cellIndex + ')'), + field = $headerCell.data('field'), + value = item[field]; + that.trigger('click-cell', field, value, item, $td); + that.trigger('click-row', item, $tr); + // if click to select - then trigger the checkbox/radio click + if (that.options.clickToSelect) { + if (that.header.clickToSelects[$tr.children().index($(this))]) { + $tr.find(sprintf('[name="%s"]', + that.options.selectItemName))[0].click(); // #144: .trigger('click') bug + } + } + }); + this.$body.find('> tr > td').off('dblclick').on('dblclick', function () { + var $td = $(this), + $tr = $td.parent(), + item = that.data[$tr.data('index')], + cellIndex = $td[0].cellIndex, + $headerCell = that.$header.find('th:eq(' + cellIndex + ')'), + field = $headerCell.data('field'), + value = item[field]; + that.trigger('dbl-click-cell', field, value, item, $td); + that.trigger('dbl-click-row', item, $tr); + }); + + this.$body.find('> tr > td > .detail-icon').off('click').on('click', function () { + var $this = $(this), + $tr = $this.parent().parent(), + index = $tr.data('index'), + row = that.options.data[index]; + + // remove and update + if ($tr.next().is('tr.detail-view')) { + $this.find('i').attr('class', 'glyphicon glyphicon-plus icon-plus'); + $tr.next().remove(); + that.trigger('collapse-row', index, row); + } else { + $this.find('i').attr('class', 'glyphicon glyphicon-minus icon-minus'); + $tr.after(sprintf('<tr class="detail-view"><td colspan="%s">%s</td></tr>', + $tr.find('td').length, calculateObjectValue(that.options, + that.options.detailFormatter, [index, row], ''))); + that.trigger('expand-row', index, row, $tr.next().find('td')); + } + that.resetView(); + }); + + this.$selectItem = this.$body.find(sprintf('[name="%s"]', this.options.selectItemName)); + this.$selectItem.off('click').on('click', function (event) { + event.stopImmediatePropagation(); + + var checked = $(this).prop('checked'), + row = that.data[$(this).data('index')]; + + row[that.header.stateField] = checked; + + if (that.options.singleSelect) { + that.$selectItem.not(this).each(function () { + that.data[$(this).data('index')][that.header.stateField] = false; + }); + that.$selectItem.filter(':checked').not(this).prop('checked', false); + } + + that.updateSelected(); + that.trigger(checked ? 'check' : 'uncheck', row); + }); + + $.each(this.header.events, function (i, events) { + if (!events) { + return; + } + // fix bug, if events is defined with namespace + if (typeof events === 'string') { + events = calculateObjectValue(null, events); + } + if (!that.options.cardView && that.options.detailView) { + i += 1; + } + for (var key in events) { + that.$body.find('tr').each(function () { + var $tr = $(this), + $td = $tr.find(that.options.cardView ? '.card-view' : 'td').eq(i), + index = key.indexOf(' '), + name = key.substring(0, index), + el = key.substring(index + 1), + func = events[key]; + + $td.find(el).off(name).on(name, function (e) { + var index = $tr.data('index'), + row = that.data[index], + value = row[that.header.fields[i]]; + + func.apply(this, [e, value, row, index]); + }); + }); + } + }); + + this.updateSelected(); + this.resetView(); + + this.trigger('post-body'); + }; + + BootstrapTable.prototype.initServer = function (silent, query) { + var that = this, + data = {}, + params = { + pageSize: this.options.pageSize === this.options.formatAllRows() ? + this.options.totalRows : this.options.pageSize, + pageNumber: this.options.pageNumber, + searchText: this.searchText, + sortName: this.options.sortName, + sortOrder: this.options.sortOrder + }, + request; + + if (!this.options.url && !this.options.ajax) { + return; + } + + if (this.options.queryParamsType === 'limit') { + params = { + search: params.searchText, + sort: params.sortName, + order: params.sortOrder + }; + if (this.options.pagination) { + params.limit = this.options.pageSize === this.options.formatAllRows() ? + this.options.totalRows : this.options.pageSize; + params.offset = this.options.pageSize === this.options.formatAllRows() ? + 0 : this.options.pageSize * (this.options.pageNumber - 1); + } + } + + if (!($.isEmptyObject(this.filterColumnsPartial))) { + params['filter'] = JSON.stringify(this.filterColumnsPartial, null); + } + + data = calculateObjectValue(this.options, this.options.queryParams, [params], data); + + $.extend(data, query || {}); + + // false to stop request + if (data === false) { + return; + } + + if (!silent) { + this.$tableLoading.show(); + } + request = $.extend({}, calculateObjectValue(null, this.options.ajaxOptions), { + type: this.options.method, + url: this.options.url, + data: this.options.contentType === 'application/json' && this.options.method === 'post' ? + JSON.stringify(data) : data, + cache: this.options.cache, + contentType: this.options.contentType, + dataType: this.options.dataType, + success: function (res) { + res = calculateObjectValue(that.options, that.options.responseHandler, [res], res); + + that.load(res); + that.trigger('load-success', res); + }, + error: function (res) { + that.trigger('load-error', res.status); + }, + complete: function () { + if (!silent) { + that.$tableLoading.hide(); + } + } + }); + + if (this.options.ajax) { + calculateObjectValue(this, this.options.ajax, [request], null); + } else { + $.ajax(request); + } + }; + + BootstrapTable.prototype.getCaretHtml = function () { + var that = this; + + $.each(this.$header.find('th'), function (i, th) { + if ($(th).data('field') === that.options.sortName) { + $(th).find('.sortable').css('background-image', 'url(' + (that.options.sortOrder === 'desc' ? arrowDesc : arrowAsc) + ')'); + } else { + $(th).find('.sortable').css('background-image', 'url(' + arrowBoth +')'); + } + }); + }; + + BootstrapTable.prototype.updateSelected = function () { + var checkAll = this.$selectItem.filter(':enabled').length === + this.$selectItem.filter(':enabled').filter(':checked').length; + + this.$selectAll.add(this.$selectAll_).prop('checked', checkAll); + + this.$selectItem.each(function () { + $(this).parents('tr')[$(this).prop('checked') ? 'addClass' : 'removeClass']('selected'); + }); + }; + + BootstrapTable.prototype.updateRows = function () { + var that = this; + + this.$selectItem.each(function () { + that.data[$(this).data('index')][that.header.stateField] = $(this).prop('checked'); + }); + }; + + BootstrapTable.prototype.resetRows = function () { + var that = this; + + $.each(this.data, function (i, row) { + that.$selectAll.prop('checked', false); + that.$selectItem.prop('checked', false); + row[that.header.stateField] = false; + }); + }; + + BootstrapTable.prototype.trigger = function (name) { + var args = Array.prototype.slice.call(arguments, 1); + + name += '.bs.table'; + this.options[BootstrapTable.EVENTS[name]].apply(this.options, args); + this.$el.trigger($.Event(name), args); + + this.options.onAll(name, args); + this.$el.trigger($.Event('all.bs.table'), [name, args]); + }; + + BootstrapTable.prototype.resetHeader = function () { + // fix #61: the hidden table reset header bug. + // fix bug: get $el.css('width') error sometime (height = 500) + clearTimeout(this.timeoutId_); + this.timeoutId_ = setTimeout($.proxy(this.fitHeader, this), this.$el.is(':hidden') ? 100 : 0); + }; + + BootstrapTable.prototype.fitHeader = function () { + var that = this, + fixedBody, + scrollWidth; + + if (that.$el.is(':hidden')) { + that.timeoutFooter_ = setTimeout($.proxy(that.fitHeader, that), 100); + return; + } + fixedBody = this.$tableBody.get(0); + + scrollWidth = fixedBody.scrollWidth > fixedBody.clientWidth && + fixedBody.scrollHeight > fixedBody.clientHeight + this.$header.height() ? + getScrollBarWidth() : 0; + + this.$el.css('margin-top', -this.$header.height()); + this.$header_ = this.$header.clone(true, true); + this.$selectAll_ = this.$header_.find('[name="btSelectAll"]'); + this.$tableHeader.css({ + 'margin-right': scrollWidth + }).find('table').css('width', this.$el.css('width')) + .html('').attr('class', this.$el.attr('class')) + .append(this.$header_); + + // fix bug: $.data() is not working as expected after $.append() + this.$header.find('th').each(function (i) { + that.$header_.find('th').eq(i).data($(this).data()); + }); + + this.$body.find('tr:first-child:not(.no-records-found) > *').each(function (i) { + that.$header_.find('div.fht-cell').eq(i).width($(this).innerWidth()); + }); + // horizontal scroll event + // TODO: it's probably better improving the layout than binding to scroll event + this.$tableBody.off('scroll').on('scroll', function () { + that.$tableHeader.scrollLeft($(this).scrollLeft()); + }); + that.trigger('post-header'); + }; + + BootstrapTable.prototype.resetFooter = function () { + var that = this, + data = that.getData(), + html = []; + + if (!this.options.showFooter || this.options.cardView) { //do nothing + return; + } + + if (!this.options.cardView && this.options.detailView) { + html.push('<td></td>'); + } + + $.each(this.options.columns, function (i, column) { + var falign = '', // footer align style + style = '', + class_ = sprintf(' class="%s"', column['class']); + + if (!column.visible) { + return; + } + + if (that.options.cardView && (!column.cardVisible)) { + return; + } + + falign = sprintf('text-align: %s; ', column.falign ? column.falign : column.align); + style = sprintf('vertical-align: %s; ', column.valign); + + html.push('<td', class_, sprintf(' style="%s"', falign + style), '>'); + + html.push(calculateObjectValue(column, column.footerFormatter, [data], ' ') || ' '); + html.push('</td>'); + }); + + this.$tableFooter.find('tr').html(html.join('')); + clearTimeout(this.timeoutFooter_); + this.timeoutFooter_ = setTimeout($.proxy(this.fitFooter, this), + this.$el.is(':hidden') ? 100 : 0); + }; + + BootstrapTable.prototype.fitFooter = function () { + var that = this, + $footerTd, + elWidth, + scrollWidth; + + clearTimeout(this.timeoutFooter_); + if (this.$el.is(':hidden')) { + this.timeoutFooter_ = setTimeout($.proxy(this.fitFooter, this), 100); + return; + } + + elWidth = this.$el.css('width'); + scrollWidth = elWidth > this.$tableBody.width() ? getScrollBarWidth() : 0; + + this.$tableFooter.css({ + 'margin-right': scrollWidth + }).find('table').css('width', elWidth) + .attr('class', this.$el.attr('class')); + + $footerTd = this.$tableFooter.find('td'); + + this.$tableBody.find('tbody tr:first-child:not(.no-records-found) > td').each(function (i) { + $footerTd.eq(i).outerWidth($(this).outerWidth()); + }); + }; + + BootstrapTable.prototype.toggleColumn = function (index, checked, needUpdate) { + if (index === -1) { + return; + } + this.options.columns[index].visible = checked; + this.initHeader(); + this.initSearch(); + this.initPagination(); + this.initBody(); + + if (this.options.showColumns) { + var $items = this.$toolbar.find('.keep-open input').prop('disabled', false); + + if (needUpdate) { + $items.filter(sprintf('[value="%s"]', index)).prop('checked', checked); + } + + if ($items.filter(':checked').length <= this.options.minimumCountColumns) { + $items.filter(':checked').prop('disabled', true); + } + } + }; + + BootstrapTable.prototype.toggleRow = function (index, isIdField, visible) { + if (index === -1) { + return; + } + + $(this.$body[0]).children().filter(sprintf(isIdField ? '[data-uniqueid="%s"]' : '[data-index="%s"]', index)) + [visible ? 'show' : 'hide'](); + }; + + // PUBLIC FUNCTION DEFINITION + // ======================= + + BootstrapTable.prototype.resetView = function (params) { + var padding = 0; + + if (params && params.height) { + this.options.height = params.height; + } + + this.$selectAll.prop('checked', this.$selectItem.length > 0 && + this.$selectItem.length === this.$selectItem.filter(':checked').length); + + if (this.options.height) { + var toolbarHeight = getRealHeight(this.$toolbar), + paginationHeight = getRealHeight(this.$pagination), + height = this.options.height - toolbarHeight - paginationHeight; + + this.$tableContainer.css('height', height + 'px'); + } + + if (this.options.cardView) { + // remove the element css + this.$el.css('margin-top', '0'); + this.$tableContainer.css('padding-bottom', '0'); + return; + } + + if (this.options.showHeader && this.options.height) { + this.$tableHeader.show(); + this.resetHeader(); + padding += cellHeight; + } else { + this.$tableHeader.hide(); + this.trigger('post-header'); + } + + if (this.options.showFooter) { + this.resetFooter(); + if (this.options.height) { + padding += cellHeight; + } + } + + // Assign the correct sortable arrow + this.getCaretHtml(); + this.$tableContainer.css('padding-bottom', padding + 'px'); + }; + + BootstrapTable.prototype.getData = function (useCurrentPage) { + return (this.searchText + || !$.isEmptyObject(this.filterColumns) + || !$.isEmptyObject(this.filterColumnsPartial)) ? + (useCurrentPage ? this.data.slice(this.pageFrom -1, this.pageTo) + : this.data) : + (useCurrentPage ? this.options.data.slice(this.pageFrom - 1, this.pageTo) + : this.options.data); + }; + + BootstrapTable.prototype.load = function (data) { + var fixedScroll = false; + + // #431: support pagination + if (this.options.sidePagination === 'server') { + this.options.totalRows = data.total; + fixedScroll = data.fixedScroll; + data = data.rows; + } else if (!$.isArray(data)) { // support fixedScroll + fixedScroll = data.fixedScroll; + data = data.data; + } + + this.initData(data); + this.initSearch(); + this.initPagination(); + this.initBody(fixedScroll); + }; + + BootstrapTable.prototype.append = function (data) { + this.initData(data, 'append'); + this.initSearch(); + this.initPagination(); + this.initBody(true); + }; + + BootstrapTable.prototype.prepend = function (data) { + this.initData(data, 'prepend'); + this.initSearch(); + this.initPagination(); + this.initBody(true); + }; + + BootstrapTable.prototype.remove = function (params) { + var len = this.options.data.length, + i, row; + + if (!params.hasOwnProperty('field') || !params.hasOwnProperty('values')) { + return; + } + + for (i = len - 1; i >= 0; i--) { + row = this.options.data[i]; + + if (!row.hasOwnProperty(params.field)) { + continue; + } + if ($.inArray(row[params.field], params.values) !== -1) { + this.options.data.splice(i, 1); + } + } + + if (len === this.options.data.length) { + return; + } + + this.initSearch(); + this.initPagination(); + this.initBody(true); + }; + + BootstrapTable.prototype.removeAll = function () { + if (this.options.data.length > 0) { + this.options.data.splice(0, this.options.data.length); + this.initSearch(); + this.initPagination(); + this.initBody(true); + } + }; + + BootstrapTable.prototype.removeByUniqueId = function (id) { + var uniqueId = this.options.uniqueId, + len = this.options.data.length, + i, row; + + for (i = len - 1; i >= 0; i--) { + row = this.options.data[i]; + + if (!row.hasOwnProperty(uniqueId)) { + continue; + } + + if (typeof row[uniqueId] === 'string') { + id = id.toString(); + } else if (typeof row[uniqueId] === 'number') { + if ((Number(row[uniqueId]) === row[uniqueId]) && (row[uniqueId] % 1 === 0)) { + id = parseInt(id); + } else if ((row[uniqueId] === Number(row[uniqueId])) && (row[uniqueId] !== 0)) { + id = parseFloat(id); + } + } + + if (row[uniqueId] === id) { + this.options.data.splice(i, 1); + } + } + + if (len === this.options.data.length) { + return; + } + + this.initSearch(); + this.initPagination(); + this.initBody(true); + }; + + BootstrapTable.prototype.insertRow = function (params) { + if (!params.hasOwnProperty('index') || !params.hasOwnProperty('row')) { + return; + } + this.data.splice(params.index, 0, params.row); + this.initSearch(); + this.initPagination(); + this.initSort(); + this.initBody(true); + }; + + BootstrapTable.prototype.updateRow = function (params) { + if (!params.hasOwnProperty('index') || !params.hasOwnProperty('row')) { + return; + } + $.extend(this.data[params.index], params.row); + this.initSort(); + this.initBody(true); + }; + + BootstrapTable.prototype.showRow = function (params) { + if (!params.hasOwnProperty('index')) { + return; + } + + this.toggleRow(params.index, params.isIdField === undefined ? false : true, true); + }; + + BootstrapTable.prototype.hideRow = function (params) { + if (!params.hasOwnProperty('index')) { + return; + } + + this.toggleRow(params.index, params.isIdField === undefined ? false : true, false); + }; + + BootstrapTable.prototype.getRowsHidden = function (show) { + var rows = $(this.$body[0]).children().filter(':hidden'), + i = 0; + if (show) { + for (; i < rows.length; i++) { + $(rows[i]).show(); + } + } + return rows; + }; + + BootstrapTable.prototype.mergeCells = function (options) { + var row = options.index, + col = $.inArray(options.field, this.header.fields), + rowspan = options.rowspan || 1, + colspan = options.colspan || 1, + i, j, + $tr = this.$body.find('tr'), + $td = $tr.eq(row).find('td').eq(col); + + if (!this.options.cardView && this.options.detailView) { + col += 1; + } + $td = $tr.eq(row).find('td').eq(col); + + if (row < 0 || col < 0 || row >= this.data.length) { + return; + } + + for (i = row; i < row + rowspan; i++) { + for (j = col; j < col + colspan; j++) { + $tr.eq(i).find('td').eq(j).hide(); + } + } + + $td.attr('rowspan', rowspan).attr('colspan', colspan).show(); + }; + + BootstrapTable.prototype.updateCell = function (params) { + if (!params.hasOwnProperty('rowIndex') || !params.hasOwnProperty('fieldName') || !params.hasOwnProperty('fieldValue')) { + return; + } + this.data[params.rowIndex][params.fieldName] = params.fieldValue; + this.initSort(); + this.initBody(true); + }; + + BootstrapTable.prototype.getOptions = function () { + return this.options; + }; + + BootstrapTable.prototype.getSelections = function () { + var that = this; + + return $.grep(this.data, function (row) { + return row[that.header.stateField]; + }); + }; + + BootstrapTable.prototype.getAllSelections = function () { + var that = this; + + return $.grep(this.options.data, function (row) { + return row[that.header.stateField]; + }); + }; + + BootstrapTable.prototype.checkAll = function () { + this.checkAll_(true); + }; + + BootstrapTable.prototype.uncheckAll = function () { + this.checkAll_(false); + }; + + BootstrapTable.prototype.checkAll_ = function (checked) { + var rows; + if (!checked) { + rows = this.getSelections(); + } + this.$selectItem.filter(':enabled').prop('checked', checked); + this.updateRows(); + this.updateSelected(); + if (checked) { + rows = this.getSelections(); + } + this.trigger(checked ? 'check-all' : 'uncheck-all', rows); + }; + + BootstrapTable.prototype.check = function (index) { + this.check_(true, index); + }; + + BootstrapTable.prototype.uncheck = function (index) { + this.check_(false, index); + }; + + BootstrapTable.prototype.check_ = function (checked, index) { + this.$selectItem.filter(sprintf('[data-index="%s"]', index)).prop('checked', checked); + this.data[index][this.header.stateField] = checked; + this.updateSelected(); + this.trigger(checked ? 'check' : 'uncheck', this.data[index]); + }; + + BootstrapTable.prototype.checkBy = function (obj) { + this.checkBy_(true, obj); + }; + + BootstrapTable.prototype.uncheckBy = function (obj) { + this.checkBy_(false, obj); + }; + + BootstrapTable.prototype.checkBy_ = function (checked, obj) { + if (!obj.hasOwnProperty('field') || !obj.hasOwnProperty('values')) { + return; + } + + var that = this, + rows = []; + $.each(this.options.data, function (index, row) { + if (!row.hasOwnProperty(obj.field)) { + return false; + } + if ($.inArray(row[obj.field], obj.values) !== -1) { + that.$selectItem.filter(sprintf('[data-index="%s"]', index)).prop('checked', checked); + row[that.header.stateField] = checked; + rows.push(row); + that.trigger(checked ? 'check' : 'uncheck', row); + } + }); + this.updateSelected(); + this.trigger(checked ? 'check-some' : 'uncheck-some', rows); + }; + + BootstrapTable.prototype.destroy = function () { + this.$el.insertBefore(this.$container); + $(this.options.toolbar).insertBefore(this.$el); + this.$container.next().remove(); + this.$container.remove(); + this.$el.html(this.$el_.html()) + .css('margin-top', '0') + .attr('class', this.$el_.attr('class') || ''); // reset the class + }; + + BootstrapTable.prototype.showLoading = function () { + this.$tableLoading.show(); + }; + + BootstrapTable.prototype.hideLoading = function () { + this.$tableLoading.hide(); + }; + + BootstrapTable.prototype.togglePagination = function () { + this.options.pagination = !this.options.pagination; + var button = this.$toolbar.find('button[name="paginationSwitch"] i'); + if (this.options.pagination) { + button.attr("class", this.options.iconsPrefix + " " + this.options.icons.paginationSwitchDown); + } else { + button.attr("class", this.options.iconsPrefix + " " + this.options.icons.paginationSwitchUp); + } + this.updatePagination(); + }; + + BootstrapTable.prototype.refresh = function (params) { + if (params && params.url) { + this.options.url = params.url; + this.options.pageNumber = 1; + } + this.initServer(params && params.silent, params && params.query); + }; + + BootstrapTable.prototype.resetWidth = function () { + if (this.options.showHeader && this.options.height) { + this.fitHeader(); + } + if (this.options.showFooter) { + this.fitFooter(); + } + }; + + BootstrapTable.prototype.showColumn = function (field) { + this.toggleColumn(getFieldIndex(this.options.columns, field), true, true); + }; + + BootstrapTable.prototype.hideColumn = function (field) { + this.toggleColumn(getFieldIndex(this.options.columns, field), false, true); + }; + + BootstrapTable.prototype.filterBy = function (columns) { + this.filterColumns = $.isEmptyObject(columns) ? {} : columns; + this.options.pageNumber = 1; + this.initSearch(); + this.updatePagination(); + }; + + BootstrapTable.prototype.scrollTo = function (value) { + if (typeof value === 'string') { + value = value === 'bottom' ? this.$tableBody[0].scrollHeight : 0; + } + if (typeof value === 'number') { + this.$tableBody.scrollTop(value); + } + if (typeof value === 'undefined') { + return this.$tableBody.scrollTop(); + } + }; + + BootstrapTable.prototype.getScrollPosition = function () { + return this.scrollTo(); + } + + BootstrapTable.prototype.selectPage = function (page) { + if (page > 0 && page <= this.options.totalPages) { + this.options.pageNumber = page; + this.updatePagination(); + } + }; + + BootstrapTable.prototype.prevPage = function () { + if (this.options.pageNumber > 1) { + this.options.pageNumber--; + this.updatePagination(); + } + }; + + BootstrapTable.prototype.nextPage = function () { + if (this.options.pageNumber < this.options.totalPages) { + this.options.pageNumber++; + this.updatePagination(); + } + }; + + BootstrapTable.prototype.toggleView = function () { + this.options.cardView = !this.options.cardView; + this.initHeader(); + // Fixed remove toolbar when click cardView button. + //that.initToolbar(); + this.initBody(); + this.trigger('toggle', this.options.cardView); + }; + + // BOOTSTRAP TABLE PLUGIN DEFINITION + // ======================= + + var allowedMethods = [ + 'getOptions', + 'getSelections', 'getAllSelections', 'getData', + 'load', 'append', 'prepend', 'remove', 'removeAll', + 'insertRow', 'updateRow', 'updateCell', 'removeByUniqueId', + 'showRow', 'hideRow', 'getRowsHidden', + 'mergeCells', + 'checkAll', 'uncheckAll', + 'check', 'uncheck', + 'checkBy', 'uncheckBy', + 'refresh', + 'resetView', + 'resetWidth', + 'destroy', + 'showLoading', 'hideLoading', + 'showColumn', 'hideColumn', + 'filterBy', + 'scrollTo', + 'getScrollPosition', + 'selectPage', 'prevPage', 'nextPage', + 'togglePagination', + 'toggleView' + ]; + + $.fn.bootstrapTable = function (option) { + var value, + args = Array.prototype.slice.call(arguments, 1); + + this.each(function () { + var $this = $(this), + data = $this.data('bootstrap.table'), + options = $.extend({}, BootstrapTable.DEFAULTS, $this.data(), + typeof option === 'object' && option); + + if (typeof option === 'string') { + if ($.inArray(option, allowedMethods) < 0) { + throw new Error("Unknown method: " + option); + } + + if (!data) { + return; + } + + value = data[option].apply(data, args); + + if (option === 'destroy') { + $this.removeData('bootstrap.table'); + } + } + + if (!data) { + $this.data('bootstrap.table', (data = new BootstrapTable(this, options))); + } + }); + + return typeof value === 'undefined' ? this : value; + }; + + $.fn.bootstrapTable.Constructor = BootstrapTable; + $.fn.bootstrapTable.defaults = BootstrapTable.DEFAULTS; + $.fn.bootstrapTable.columnDefaults = BootstrapTable.COLUMN_DEFAULTS; + $.fn.bootstrapTable.locales = BootstrapTable.LOCALES; + $.fn.bootstrapTable.methods = allowedMethods; + + // BOOTSTRAP TABLE INIT + // ======================= + + $(function () { + $('[data-toggle="table"]').bootstrapTable(); + }); + +}(jQuery); From b85e9bb97fc0c2a41ac94a1ed0d724fccf92015f Mon Sep 17 00:00:00 2001 From: madd15 <joshdeakin@adam.com.au> Date: Tue, 28 Jul 2015 13:59:34 +0930 Subject: [PATCH 008/120] Add bootstrap extensions and export libs --- .../cookie/bootstrap-table-cookie.js | 234 ++++++++++ .../cookie/bootstrap-table-cookie.min.js | 7 + .../editable/bootstrap-table-editable.js | 83 ++++ .../editable/bootstrap-table-editable.min.js | 7 + .../export/bootstrap-table-export.js | 84 ++++ .../export/bootstrap-table-export.min.js | 7 + .../bootstrap-table-filter-control.js | 283 ++++++++++++ .../bootstrap-table-filter-control.min.js | 7 + .../filter/bootstrap-table-filter.js | 67 +++ .../filter/bootstrap-table-filter.min.js | 7 + .../flat-json/bootstrap-table-flat-json.js | 70 +++ .../bootstrap-table-flat-json.min.js | 7 + .../key-events/bootstrap-table-key-events.js | 81 ++++ .../bootstrap-table-key-events.min.js | 7 + .../mobile/bootstrap-table-mobile.js | 87 ++++ .../mobile/bootstrap-table-mobile.min.js | 7 + .../bootstrap-table-multiple-sort.js | 370 ++++++++++++++++ .../bootstrap-table-multiple-sort.min.js | 7 + .../bootstrap-table-natural-sorting.js | 47 ++ .../bootstrap-table-natural-sorting.min.js | 7 + .../bootstrap-table-reorder-columns.js | 118 +++++ .../bootstrap-table-reorder-columns.min.js | 7 + .../bootstrap-table-reorder-rows.css | 14 + .../bootstrap-table-reorder-rows.js | 115 +++++ .../bootstrap-table-reorder-rows.min.js | 7 + .../resizable/bootstrap-table-resizable.js | 74 ++++ .../bootstrap-table-resizable.min.js | 7 + .../toolbar/bootstrap-table-toolbar.js | 237 ++++++++++ .../toolbar/bootstrap-table-toolbar.min.js | 7 + .../assets/js/libs/FileSaver/FileSaver.min.js | 2 + public/assets/js/libs/FileSaver/LICENSE.md | 9 + public/assets/js/libs/html2canvas/LICENSE | 22 + .../js/libs/html2canvas/html2canvas.min.js | 9 + .../js/libs/jsPDF-AutoTable/LICENSE.txt | 20 + .../jsPDF-AutoTable/jspdf.plugin.autotable.js | 418 ++++++++++++++++++ public/assets/js/libs/jsPDF/MIT-LICENSE.txt | 20 + public/assets/js/libs/jsPDF/jspdf.min.js | 171 +++++++ 37 files changed, 2733 insertions(+) create mode 100644 public/assets/js/extensions/cookie/bootstrap-table-cookie.js create mode 100644 public/assets/js/extensions/cookie/bootstrap-table-cookie.min.js create mode 100644 public/assets/js/extensions/editable/bootstrap-table-editable.js create mode 100644 public/assets/js/extensions/editable/bootstrap-table-editable.min.js create mode 100644 public/assets/js/extensions/export/bootstrap-table-export.js create mode 100644 public/assets/js/extensions/export/bootstrap-table-export.min.js create mode 100644 public/assets/js/extensions/filter-control/bootstrap-table-filter-control.js create mode 100644 public/assets/js/extensions/filter-control/bootstrap-table-filter-control.min.js create mode 100644 public/assets/js/extensions/filter/bootstrap-table-filter.js create mode 100644 public/assets/js/extensions/filter/bootstrap-table-filter.min.js create mode 100644 public/assets/js/extensions/flat-json/bootstrap-table-flat-json.js create mode 100644 public/assets/js/extensions/flat-json/bootstrap-table-flat-json.min.js create mode 100644 public/assets/js/extensions/key-events/bootstrap-table-key-events.js create mode 100644 public/assets/js/extensions/key-events/bootstrap-table-key-events.min.js create mode 100644 public/assets/js/extensions/mobile/bootstrap-table-mobile.js create mode 100644 public/assets/js/extensions/mobile/bootstrap-table-mobile.min.js create mode 100644 public/assets/js/extensions/multiple-sort/bootstrap-table-multiple-sort.js create mode 100644 public/assets/js/extensions/multiple-sort/bootstrap-table-multiple-sort.min.js create mode 100644 public/assets/js/extensions/natural-sorting/bootstrap-table-natural-sorting.js create mode 100644 public/assets/js/extensions/natural-sorting/bootstrap-table-natural-sorting.min.js create mode 100644 public/assets/js/extensions/reorder-columns/bootstrap-table-reorder-columns.js create mode 100644 public/assets/js/extensions/reorder-columns/bootstrap-table-reorder-columns.min.js create mode 100644 public/assets/js/extensions/reorder-rows/bootstrap-table-reorder-rows.css create mode 100644 public/assets/js/extensions/reorder-rows/bootstrap-table-reorder-rows.js create mode 100644 public/assets/js/extensions/reorder-rows/bootstrap-table-reorder-rows.min.js create mode 100644 public/assets/js/extensions/resizable/bootstrap-table-resizable.js create mode 100644 public/assets/js/extensions/resizable/bootstrap-table-resizable.min.js create mode 100644 public/assets/js/extensions/toolbar/bootstrap-table-toolbar.js create mode 100644 public/assets/js/extensions/toolbar/bootstrap-table-toolbar.min.js create mode 100644 public/assets/js/libs/FileSaver/FileSaver.min.js create mode 100644 public/assets/js/libs/FileSaver/LICENSE.md create mode 100644 public/assets/js/libs/html2canvas/LICENSE create mode 100644 public/assets/js/libs/html2canvas/html2canvas.min.js create mode 100644 public/assets/js/libs/jsPDF-AutoTable/LICENSE.txt create mode 100644 public/assets/js/libs/jsPDF-AutoTable/jspdf.plugin.autotable.js create mode 100644 public/assets/js/libs/jsPDF/MIT-LICENSE.txt create mode 100644 public/assets/js/libs/jsPDF/jspdf.min.js diff --git a/public/assets/js/extensions/cookie/bootstrap-table-cookie.js b/public/assets/js/extensions/cookie/bootstrap-table-cookie.js new file mode 100644 index 0000000000..b5a0c67754 --- /dev/null +++ b/public/assets/js/extensions/cookie/bootstrap-table-cookie.js @@ -0,0 +1,234 @@ +/** + * @author: Dennis Hernández + * @webSite: http://djhvscf.github.io/Blog + * @version: v1.1.0 + * + * @update zhixin wen <wenzhixin2010@gmail.com> + */ + +(function ($) { + 'use strict'; + + var idsStateSaveList = { + sortOrder: 'bs.table.sortOrder', + sortName: 'bs.table.sortName', + pageNumber: 'bs.table.pageNumber', + pageList: 'bs.table.pageList', + columns: 'bs.table.columns', + searchText: 'bs.table.searchText' + }; + + var cookieEnabled = function () { + return (navigator.cookieEnabled) ? true : false; + }; + + var setCookie = function (that, cookieName, sValue, sPath, sDomain, bSecure) { + if ((!that.options.stateSave) || (!cookieEnabled()) || (that.options.stateSaveIdTable === '')) { + return; + } + + var tableName = that.options.stateSaveIdTable, + vEnd = that.options.stateSaveExpire; + + cookieName = tableName + '.' + cookieName; + if (!cookieName || /^(?:expires|max\-age|path|domain|secure)$/i.test(cookieName)) { + return false; + } + + document.cookie = encodeURIComponent(cookieName) + '=' + encodeURIComponent(sValue) + calculateExpiration(vEnd) + (sDomain ? '; domain=' + sDomain : '') + (sPath ? '; path=' + sPath : '') + (bSecure ? '; secure' : ''); + return true; + }; + + var getCookie = function (tableName, cookieName) { + cookieName = tableName + '.' + cookieName; + if (!cookieName) { + return null; + } + return decodeURIComponent(document.cookie.replace(new RegExp('(?:(?:^|.*;)\\s*' + encodeURIComponent(cookieName).replace(/[\-\.\+\*]/g, '\\$&') + '\\s*\\=\\s*([^;]*).*$)|^.*$'), '$1')) || null; + }; + + var hasCookie = function (cookieName) { + if (!cookieName) { + return false; + } + return (new RegExp('(?:^|;\\s*)' + encodeURIComponent(cookieName).replace(/[\-\.\+\*]/g, '\\$&') + '\\s*\\=')).test(document.cookie); + }; + + var deleteCookie = function (tableName, cookieName, sPath, sDomain) { + cookieName = tableName + '.' + cookieName; + if (!hasCookie(cookieName)) { + return false; + } + document.cookie = encodeURIComponent(cookieName) + '=; expires=Thu, 01 Jan 1970 00:00:00 GMT' + (sDomain ? '; domain=' + sDomain : '') + (sPath ? '; path=' + sPath : ''); + return true; + }; + + var calculateExpiration = function(vEnd) { + var time = vEnd.replace(/[0-9]/, ''); //s,mi,h,d,m,y + vEnd = vEnd.replace(/[A-Za-z]/, ''); //number + + switch (time.toLowerCase()) { + case 's': + vEnd = +vEnd; + break; + case 'mi': + vEnd = vEnd * 60; + break; + case 'h': + vEnd = vEnd * 60 * 60; + break; + case 'd': + vEnd = vEnd * 24 * 60 * 60; + break; + case 'm': + vEnd = vEnd * 30 * 24 * 60 * 60; + break; + case 'y': + vEnd = vEnd * 365 * 30 * 24 * 60 * 60; + break; + default: + vEnd = undefined; + break; + } + + return vEnd === undefined ? '' : '; max-age=' + vEnd; + } + + $.extend($.fn.bootstrapTable.defaults, { + stateSave: false, + stateSaveExpire: '2h', + stateSaveIdTable: '' + }); + + $.fn.bootstrapTable.methods.push('deleteCookie'); + + var BootstrapTable = $.fn.bootstrapTable.Constructor, + _initTable = BootstrapTable.prototype.initTable, + _onSort = BootstrapTable.prototype.onSort, + _onPageNumber = BootstrapTable.prototype.onPageNumber, + _onPageListChange = BootstrapTable.prototype.onPageListChange, + _onPageFirst = BootstrapTable.prototype.onPageFirst, + _onPagePre = BootstrapTable.prototype.onPagePre, + _onPageNext = BootstrapTable.prototype.onPageNext, + _onPageLast = BootstrapTable.prototype.onPageLast, + _toggleColumn = BootstrapTable.prototype.toggleColumn, + _onSearch = BootstrapTable.prototype.onSearch; + + // init save data after initTable function + BootstrapTable.prototype.initTable = function () { + _initTable.apply(this, Array.prototype.slice.apply(arguments)); + this.initStateSave(); + }; + + BootstrapTable.prototype.initStateSave = function () { + if (!this.options.stateSave) { + return; + } + + if (!cookieEnabled()) { + return; + } + + if (this.options.stateSaveIdTable === '') { + return; + } + + var sortOrderStateSave = getCookie(this.options.stateSaveIdTable, idsStateSaveList.sortOrder), + sortOrderStateName = getCookie(this.options.stateSaveIdTable, idsStateSaveList.sortName), + pageNumberStateSave = getCookie(this.options.stateSaveIdTable, idsStateSaveList.pageNumber), + pageListStateSave = getCookie(this.options.stateSaveIdTable, idsStateSaveList.pageList), + columnsStateSave = JSON.parse(getCookie(this.options.stateSaveIdTable, idsStateSaveList.columns)), + searchStateSave = getCookie(this.options.stateSaveIdTable, idsStateSaveList.searchText); + + if (sortOrderStateSave) { + this.options.sortOrder = sortOrderStateSave; + this.options.sortName = sortOrderStateName; + } + + if (pageNumberStateSave) { + this.options.pageNumber = +pageNumberStateSave; + } + + if (pageListStateSave) { + this.options.pageSize = pageListStateSave === + this.options.formatAllRows() ? pageListStateSave : +pageListStateSave; + } + + if (columnsStateSave) { + $.each(this.options.columns, function (i, column) { + column.visible = columnsStateSave.indexOf(i) !== -1; + }); + } + + if (searchStateSave) { + this.options.searchText = searchStateSave; + } + }; + + BootstrapTable.prototype.onSort = function () { + _onSort.apply(this, Array.prototype.slice.apply(arguments)); + + setCookie(this, idsStateSaveList.sortOrder, this.options.sortOrder); + setCookie(this, idsStateSaveList.sortName, this.options.sortName); + }; + + BootstrapTable.prototype.onPageNumber = function () { + _onPageNumber.apply(this, Array.prototype.slice.apply(arguments)); + + setCookie(this, idsStateSaveList.pageNumber, this.options.pageNumber); + }; + + BootstrapTable.prototype.onPageListChange = function () { + _onPageListChange.apply(this, Array.prototype.slice.apply(arguments)); + + setCookie(this, idsStateSaveList.pageList, this.options.pageSize); + }; + + BootstrapTable.prototype.onPageFirst = function () { + _onPageFirst.apply(this, Array.prototype.slice.apply(arguments)); + setCookie(this, idsStateSaveList.pageNumber, this.options.pageNumber); + }; + + BootstrapTable.prototype.onPagePre = function () { + _onPagePre.apply(this, Array.prototype.slice.apply(arguments)); + setCookie(this, idsStateSaveList.pageNumber, this.options.pageNumber); + }; + + BootstrapTable.prototype.onPageNext = function () { + _onPageNext.apply(this, Array.prototype.slice.apply(arguments)); + setCookie(this, idsStateSaveList.pageNumber, this.options.pageNumber); + }; + + BootstrapTable.prototype.onPageLast = function () { + _onPageLast.apply(this, Array.prototype.slice.apply(arguments)); + setCookie(this, idsStateSaveList.pageNumber, this.options.pageNumber); + }; + + BootstrapTable.prototype.toggleColumn = function () { + _toggleColumn.apply(this, Array.prototype.slice.apply(arguments)); + + var visibleColumns = []; + + $.each(this.options.columns, function (i) { + if (this.visible) { + visibleColumns.push(i); + } + }); + + setCookie(this, idsStateSaveList.columns, JSON.stringify(visibleColumns)); + }; + + BootstrapTable.prototype.onSearch = function () { + _onSearch.apply(this, Array.prototype.slice.apply(arguments)); + + setCookie(this, idsStateSaveList.searchText, this.searchText); + }; + + BootstrapTable.prototype.deleteCookie = function (cookieName) { + if ((cookieName === '') || (!cookieEnabled())) { + return; + } + + deleteCookie(idsStateSaveList[cookieName]); + }; +})(jQuery); diff --git a/public/assets/js/extensions/cookie/bootstrap-table-cookie.min.js b/public/assets/js/extensions/cookie/bootstrap-table-cookie.min.js new file mode 100644 index 0000000000..92b7107e0a --- /dev/null +++ b/public/assets/js/extensions/cookie/bootstrap-table-cookie.min.js @@ -0,0 +1,7 @@ +/* +* bootstrap-table - v1.8.1 - 2015-05-29 +* https://github.com/wenzhixin/bootstrap-table +* Copyright (c) 2015 zhixin wen +* Licensed MIT License +*/ +!function(a){"use strict";var b={sortOrder:"bs.table.sortOrder",sortName:"bs.table.sortName",pageNumber:"bs.table.pageNumber",pageList:"bs.table.pageList",columns:"bs.table.columns",searchText:"bs.table.searchText"},c=function(){return navigator.cookieEnabled?!0:!1},d=function(a,b,d,e,f,g){if(a.options.stateSave&&c()&&""!==a.options.stateSaveIdTable){var i=a.options.stateSaveIdTable,j=a.options.stateSaveExpire;return b=i+"."+b,!b||/^(?:expires|max\-age|path|domain|secure)$/i.test(b)?!1:(document.cookie=encodeURIComponent(b)+"="+encodeURIComponent(d)+h(j)+(f?"; domain="+f:"")+(e?"; path="+e:"")+(g?"; secure":""),!0)}},e=function(a,b){return b=a+"."+b,b?decodeURIComponent(document.cookie.replace(new RegExp("(?:(?:^|.*;)\\s*"+encodeURIComponent(b).replace(/[\-\.\+\*]/g,"\\$&")+"\\s*\\=\\s*([^;]*).*$)|^.*$"),"$1"))||null:null},f=function(a){return a?new RegExp("(?:^|;\\s*)"+encodeURIComponent(a).replace(/[\-\.\+\*]/g,"\\$&")+"\\s*\\=").test(document.cookie):!1},g=function(a,b,c,d){return b=a+"."+b,f(b)?(document.cookie=encodeURIComponent(b)+"=; expires=Thu, 01 Jan 1970 00:00:00 GMT"+(d?"; domain="+d:"")+(c?"; path="+c:""),!0):!1},h=function(a){var b=a.replace(/[0-9]/,"");switch(a=a.replace(/[A-Za-z]/,""),b.toLowerCase()){case"s":a=+a;break;case"mi":a=60*a;break;case"h":a=60*a*60;break;case"d":a=24*a*60*60;break;case"m":a=30*a*24*60*60;break;case"y":a=365*a*30*24*60*60;break;default:a=void 0}return void 0===a?"":"; max-age="+a};a.extend(a.fn.bootstrapTable.defaults,{stateSave:!1,stateSaveExpire:"2h",stateSaveIdTable:""}),a.fn.bootstrapTable.methods.push("deleteCookie");var i=a.fn.bootstrapTable.Constructor,j=i.prototype.initTable,k=i.prototype.onSort,l=i.prototype.onPageNumber,m=i.prototype.onPageListChange,n=i.prototype.onPageFirst,o=i.prototype.onPagePre,p=i.prototype.onPageNext,q=i.prototype.onPageLast,r=i.prototype.toggleColumn,s=i.prototype.onSearch;i.prototype.initTable=function(){j.apply(this,Array.prototype.slice.apply(arguments)),this.initStateSave()},i.prototype.initStateSave=function(){if(this.options.stateSave&&c()&&""!==this.options.stateSaveIdTable){var d=e(this.options.stateSaveIdTable,b.sortOrder),f=e(this.options.stateSaveIdTable,b.sortName),g=e(this.options.stateSaveIdTable,b.pageNumber),h=e(this.options.stateSaveIdTable,b.pageList),i=JSON.parse(e(this.options.stateSaveIdTable,b.columns)),j=e(this.options.stateSaveIdTable,b.searchText);d&&(this.options.sortOrder=d,this.options.sortName=f),g&&(this.options.pageNumber=+g),h&&(this.options.pageSize=h===this.options.formatAllRows()?h:+h),i&&a.each(this.options.columns,function(a,b){b.visible=-1!==i.indexOf(a)}),j&&(this.options.searchText=j)}},i.prototype.onSort=function(){k.apply(this,Array.prototype.slice.apply(arguments)),d(this,b.sortOrder,this.options.sortOrder),d(this,b.sortName,this.options.sortName)},i.prototype.onPageNumber=function(){l.apply(this,Array.prototype.slice.apply(arguments)),d(this,b.pageNumber,this.options.pageNumber)},i.prototype.onPageListChange=function(){m.apply(this,Array.prototype.slice.apply(arguments)),d(this,b.pageList,this.options.pageSize)},i.prototype.onPageFirst=function(){n.apply(this,Array.prototype.slice.apply(arguments)),d(this,b.pageNumber,this.options.pageNumber)},i.prototype.onPagePre=function(){o.apply(this,Array.prototype.slice.apply(arguments)),d(this,b.pageNumber,this.options.pageNumber)},i.prototype.onPageNext=function(){p.apply(this,Array.prototype.slice.apply(arguments)),d(this,b.pageNumber,this.options.pageNumber)},i.prototype.onPageLast=function(){q.apply(this,Array.prototype.slice.apply(arguments)),d(this,b.pageNumber,this.options.pageNumber)},i.prototype.toggleColumn=function(){r.apply(this,Array.prototype.slice.apply(arguments));var c=[];a.each(this.options.columns,function(a){this.visible&&c.push(a)}),d(this,b.columns,JSON.stringify(c))},i.prototype.onSearch=function(){s.apply(this,Array.prototype.slice.apply(arguments)),d(this,b.searchText,this.searchText)},i.prototype.deleteCookie=function(a){""!==a&&c()&&g(b[a])}}(jQuery); \ No newline at end of file diff --git a/public/assets/js/extensions/editable/bootstrap-table-editable.js b/public/assets/js/extensions/editable/bootstrap-table-editable.js new file mode 100644 index 0000000000..cd37f42b19 --- /dev/null +++ b/public/assets/js/extensions/editable/bootstrap-table-editable.js @@ -0,0 +1,83 @@ +/** + * @author zhixin wen <wenzhixin2010@gmail.com> + * extensions: https://github.com/vitalets/x-editable + */ + +!function ($) { + + 'use strict'; + + $.extend($.fn.bootstrapTable.defaults, { + editable: true, + onEditableInit: function () { + return false; + }, + onEditableSave: function (field, row, oldValue, $el) { + return false; + } + }); + + $.extend($.fn.bootstrapTable.Constructor.EVENTS, { + 'editable-init.bs.table': 'onEditableInit', + 'editable-save.bs.table': 'onEditableSave' + }); + + var BootstrapTable = $.fn.bootstrapTable.Constructor, + _initTable = BootstrapTable.prototype.initTable, + _initBody = BootstrapTable.prototype.initBody; + + BootstrapTable.prototype.initTable = function () { + var that = this; + _initTable.apply(this, Array.prototype.slice.apply(arguments)); + + if (!this.options.editable) { + return; + } + + $.each(this.options.columns, function (i, column) { + if (!column.editable) { + return; + } + + var _formatter = column.formatter; + column.formatter = function (value, row, index) { + var result = _formatter ? _formatter(value, row, index) : value; + + return ['<a href="javascript:void(0)"', + ' data-name="' + column.field + '"', + ' data-pk="' + row[that.options.idField] + '"', + ' data-value="' + result + '"', + '>' + '</a>' + ].join(''); + }; + }); + }; + + BootstrapTable.prototype.initBody = function () { + var that = this; + _initBody.apply(this, Array.prototype.slice.apply(arguments)); + + if (!this.options.editable) { + return; + } + + $.each(this.options.columns, function (i, column) { + if (!column.editable) { + return; + } + + that.$body.find('a[data-name="' + column.field + '"]').editable(column.editable) + .off('save').on('save', function (e, params) { + var data = that.getData(), + index = $(this).parents('tr[data-index]').data('index'), + row = data[index], + oldValue = row[column.field]; + + row[column.field] = params.submitValue; + that.trigger('editable-save', column.field, row, oldValue, $(this)); + }); + }); + this.trigger('editable-init'); + }; + +}(jQuery); diff --git a/public/assets/js/extensions/editable/bootstrap-table-editable.min.js b/public/assets/js/extensions/editable/bootstrap-table-editable.min.js new file mode 100644 index 0000000000..80355398ce --- /dev/null +++ b/public/assets/js/extensions/editable/bootstrap-table-editable.min.js @@ -0,0 +1,7 @@ +/* +* bootstrap-table - v1.8.1 - 2015-05-29 +* https://github.com/wenzhixin/bootstrap-table +* Copyright (c) 2015 zhixin wen +* Licensed MIT License +*/ +!function(a){"use strict";a.extend(a.fn.bootstrapTable.defaults,{editable:!0,onEditableInit:function(){return!1},onEditableSave:function(){return!1}}),a.extend(a.fn.bootstrapTable.Constructor.EVENTS,{"editable-init.bs.table":"onEditableInit","editable-save.bs.table":"onEditableSave"});var b=a.fn.bootstrapTable.Constructor,c=b.prototype.initTable,d=b.prototype.initBody;b.prototype.initTable=function(){var b=this;c.apply(this,Array.prototype.slice.apply(arguments)),this.options.editable&&a.each(this.options.columns,function(a,c){if(c.editable){var d=c.formatter;c.formatter=function(a,e,f){var g=d?d(a,e,f):a;return['<a href="javascript:void(0)"',' data-name="'+c.field+'"',' data-pk="'+e[b.options.idField]+'"',' data-value="'+g+'"',"></a>"].join("")}}})},b.prototype.initBody=function(){var b=this;d.apply(this,Array.prototype.slice.apply(arguments)),this.options.editable&&(a.each(this.options.columns,function(c,d){d.editable&&b.$body.find('a[data-name="'+d.field+'"]').editable(d.editable).off("save").on("save",function(c,e){var f=b.getData(),g=a(this).parents("tr[data-index]").data("index"),h=f[g],i=h[d.field];h[d.field]=e.submitValue,b.trigger("editable-save",d.field,h,i,a(this))})}),this.trigger("editable-init"))}}(jQuery); \ No newline at end of file diff --git a/public/assets/js/extensions/export/bootstrap-table-export.js b/public/assets/js/extensions/export/bootstrap-table-export.js new file mode 100644 index 0000000000..2e2f4c3326 --- /dev/null +++ b/public/assets/js/extensions/export/bootstrap-table-export.js @@ -0,0 +1,84 @@ +/** + * @author zhixin wen <wenzhixin2010@gmail.com> + * extensions: https://github.com/kayalshri/tableExport.jquery.plugin + */ + +(function ($) { + 'use strict'; + + var TYPE_NAME = { + json: 'JSON', + xml: 'XML', + png: 'PNG', + csv: 'CSV', + txt: 'TXT', + sql: 'SQL', + doc: 'MS-Word', + excel: 'Ms-Excel', + powerpoint: 'Ms-Powerpoint', + pdf: 'PDF' + }; + + $.extend($.fn.bootstrapTable.defaults, { + showExport: false, + // 'json', 'xml', 'png', 'csv', 'txt', 'sql', 'doc', 'excel', 'powerpoint', 'pdf' + exportTypes: ['json', 'xml', 'csv', 'txt', 'sql', 'excel'], + exportOptions: {} + }); + + var BootstrapTable = $.fn.bootstrapTable.Constructor, + _initToolbar = BootstrapTable.prototype.initToolbar; + + BootstrapTable.prototype.initToolbar = function () { + this.showToolbar = this.options.showExport; + + _initToolbar.apply(this, Array.prototype.slice.apply(arguments)); + + if (this.options.showExport) { + var that = this, + $btnGroup = this.$toolbar.find('>.btn-group'), + $export = $btnGroup.find('div.export'); + + if (!$export.length) { + $export = $([ + '<div class="export btn-group">', + '<button class="btn btn-default dropdown-toggle" ' + + 'data-toggle="dropdown" type="button">', + '<i class="glyphicon glyphicon-export icon-share"></i> ', + '<span class="caret"></span>', + '</button>', + '<ul class="dropdown-menu" role="menu">', + '</ul>', + '</div>'].join('')).appendTo($btnGroup); + + var $menu = $export.find('.dropdown-menu'), + exportTypes = this.options.exportTypes; + + if (typeof this.options.exportTypes === 'string') { + var types = this.options.exportTypes.slice(1, -1).replace(/ /g, '').split(','); + + exportTypes = []; + $.each(types, function (i, value) { + exportTypes.push(value.slice(1, -1)); + }); + } + $.each(exportTypes, function (i, type) { + if (TYPE_NAME.hasOwnProperty(type)) { + $menu.append(['<li data-type="' + type + '">', + '<a href="javascript:void(0)">', + TYPE_NAME[type], + '</a>', + '</li>'].join('')); + } + }); + + $menu.find('li').click(function () { + that.$el.tableExport($.extend({}, that.options.exportOptions, { + type: $(this).data('type'), + escape: false + })); + }); + } + } + }; +})(jQuery); diff --git a/public/assets/js/extensions/export/bootstrap-table-export.min.js b/public/assets/js/extensions/export/bootstrap-table-export.min.js new file mode 100644 index 0000000000..5df6e1c271 --- /dev/null +++ b/public/assets/js/extensions/export/bootstrap-table-export.min.js @@ -0,0 +1,7 @@ +/* +* bootstrap-table - v1.8.1 - 2015-05-29 +* https://github.com/wenzhixin/bootstrap-table +* Copyright (c) 2015 zhixin wen +* Licensed MIT License +*/ +!function(a){"use strict";var b={json:"JSON",xml:"XML",png:"PNG",csv:"CSV",txt:"TXT",sql:"SQL",doc:"MS-Word",excel:"Ms-Excel",powerpoint:"Ms-Powerpoint",pdf:"PDF"};a.extend(a.fn.bootstrapTable.defaults,{showExport:!1,exportTypes:["json","xml","csv","txt","sql","excel"],exportOptions:{}});var c=a.fn.bootstrapTable.Constructor,d=c.prototype.initToolbar;c.prototype.initToolbar=function(){if(this.showToolbar=this.options.showExport,d.apply(this,Array.prototype.slice.apply(arguments)),this.options.showExport){var c=this,e=this.$toolbar.find(">.btn-group"),f=e.find("div.export");if(!f.length){f=a(['<div class="export btn-group">','<button class="btn btn-default dropdown-toggle" data-toggle="dropdown" type="button">','<i class="glyphicon glyphicon-export icon-share"></i> ','<span class="caret"></span>',"</button>",'<ul class="dropdown-menu" role="menu">',"</ul>","</div>"].join("")).appendTo(e);var g=f.find(".dropdown-menu"),h=this.options.exportTypes;if("string"==typeof this.options.exportTypes){var i=this.options.exportTypes.slice(1,-1).replace(/ /g,"").split(",");h=[],a.each(i,function(a,b){h.push(b.slice(1,-1))})}a.each(h,function(a,c){b.hasOwnProperty(c)&&g.append(['<li data-type="'+c+'">','<a href="javascript:void(0)">',b[c],"</a>","</li>"].join(""))}),g.find("li").click(function(){c.$el.tableExport(a.extend({},c.options.exportOptions,{type:a(this).data("type"),escape:!1}))})}}}}(jQuery); \ No newline at end of file diff --git a/public/assets/js/extensions/filter-control/bootstrap-table-filter-control.js b/public/assets/js/extensions/filter-control/bootstrap-table-filter-control.js new file mode 100644 index 0000000000..fc80c1cb41 --- /dev/null +++ b/public/assets/js/extensions/filter-control/bootstrap-table-filter-control.js @@ -0,0 +1,283 @@ +/** + * @author: Dennis Hernández + * @webSite: http://djhvscf.github.io/Blog + * @version: v1.0.0 + */ + +!function ($) { + + 'use strict'; + + var sprintf = function (str) { + var args = arguments, + flag = true, + i = 1; + + str = str.replace(/%s/g, function () { + var arg = args[i++]; + + if (typeof arg === 'undefined') { + flag = false; + return ''; + } + return arg; + }); + return flag ? str : ''; + }; + + var getFieldIndex = function (columns, field) { + var index = -1; + + $.each(columns, function (i, column) { + if (column.field === field) { + index = i; + return false; + } + return true; + }); + return index; + }; + + var calculateObjectValue = function (self, name, args, defaultValue) { + if (typeof name === 'string') { + // support obj.func1.func2 + var names = name.split('.'); + + if (names.length > 1) { + name = window; + $.each(names, function (i, f) { + name = name[f]; + }); + } else { + name = window[name]; + } + } + if (typeof name === 'object') { + return name; + } + if (typeof name === 'function') { + return name.apply(self, args); + } + return defaultValue; + }; + + $.extend($.fn.bootstrapTable.defaults, { + filterControl: false, + onColumnSearch: function (field, text) { + return false; + } + }); + + $.extend($.fn.bootstrapTable.COLUMN_DEFAULTS, { + filterControl: undefined, + filterData: undefined + }); + + $.extend($.fn.bootstrapTable.Constructor.EVENTS, { + 'column-search.bs.table': 'onColumnSearch' + }); + + var BootstrapTable = $.fn.bootstrapTable.Constructor, + _initHeader = BootstrapTable.prototype.initHeader, + _initBody = BootstrapTable.prototype.initBody, + _initSearch = BootstrapTable.prototype.initSearch; + + BootstrapTable.prototype.initHeader = function () { + _initHeader.apply(this, Array.prototype.slice.apply(arguments)); + + if (!this.options.filterControl) { + return; + } + + var addedFilterControl = false, + that = this, + isVisible, + html, + timeoutId = 0; + + $.each(this.options.columns, function (i, column) { + isVisible = 'hidden'; + html = []; + + if (!column.visible) { + return; + } + + if (!column.filterControl) { + html.push('<div style="height: 34px;"></div>'); + } else { + html.push('<div style="margin: 0px 2px 2px 2px;" class="filterControl">'); + + if (column.filterControl && column.searchable) { + addedFilterControl = true; + isVisible = 'visible' + } + switch (column.filterControl.toLowerCase()) { + case 'input' : + html.push(sprintf('<input type="text" class="form-control" style="width: 100%; visibility: %s">', isVisible)); + break; + case 'select': + html.push(sprintf('<select class="%s form-control" style="width: 100%; visibility: %s"></select>', + column.field, isVisible)) + break; + } + } + + that.$header.find(sprintf('.th-inner:eq("%s")', i)).next().append(html.join('')); + if (column.filterData !== undefined && column.filterData.toLowerCase() !== 'column') { + var filterDataType = column.filterData.substring(0, 3); + var filterDataSource = column.filterData.substring(4, column.filterData.length); + var selectControl = $('.' + column.field); + selectControl.append($("<option></option>") + .attr("value", '') + .text('')); + switch (filterDataType) { + case 'url': + $.ajax({ + url: filterDataSource, + dataType: 'json', + success: function (data) { + $.each(data, function (key, value) { + selectControl.append($("<option></option>") + .attr("value", key) + .text(value)); + }); + } + }); + break; + case 'var': + var variableValues = window[filterDataSource]; + for (var key in variableValues) { + selectControl.append($("<option></option>") + .attr("value", key) + .text(variableValues[key])); + }; + break; + } + } + }); + + if (addedFilterControl) { + this.$header.off('keyup', 'input').on('keyup', 'input', function (event) { + clearTimeout(timeoutId); + timeoutId = setTimeout(function () { + that.onColumnSearch(event); + }, that.options.searchTimeOut); + }); + + this.$header.off('change', 'select').on('change', 'select', function (event) { + clearTimeout(timeoutId); + timeoutId = setTimeout(function () { + that.onColumnSearch(event); + }, that.options.searchTimeOut); + }); + } else { + this.$header.find('.filterControl').hide(); + } + }; + + BootstrapTable.prototype.initBody = function () { + _initBody.apply(this, Array.prototype.slice.apply(arguments)); + + var that = this, + data = this.getData(); + + for (var i = this.pageFrom - 1; i < this.pageTo; i++) { + var key, + item = data[i]; + + $.each(this.header.fields, function (j, field) { + var value = item[field], + column = that.options.columns[getFieldIndex(that.options.columns, field)]; + + value = calculateObjectValue(that.header, + that.header.formatters[j], [value, item, i], value); + + if ((!column.checkbox) || (!column.radio)) { + if (column.filterControl !== undefined && column.filterControl.toLowerCase() === 'select' + && column.searchable) { + + if (column.filterData === undefined || column.filterData.toLowerCase() === 'column') { + var selectControl = $('.' + column.field), + iOpt = 0, + exitsOpt = false, + options; + if (selectControl !== undefined) { + options = selectControl.get(0).options; + + if (options.length === 0) { + + //Added the default option + selectControl.append($("<option></option>") + .attr("value", '') + .text('')); + + selectControl.append($("<option></option>") + .attr("value", value) + .text(value)); + } else { + for (; iOpt < options.length; iOpt++) { + if (options[iOpt].value === value) { + exitsOpt = true; + break; + } + } + + if (!exitsOpt) { + selectControl.append($("<option></option>") + .attr("value", value) + .text(value)); + } + } + } + } + } + } + }); + } + }; + + BootstrapTable.prototype.initSearch = function () { + _initSearch.apply(this, Array.prototype.slice.apply(arguments)); + + var that = this; + var fp = $.isEmptyObject(this.filterColumnsPartial) ? null : this.filterColumnsPartial; + + //Check partial column filter + this.data = fp ? $.grep(this.data, function (item, i) { + for (var key in fp) { + var fval = fp[key].toLowerCase(); + var value = item[key]; + value = calculateObjectValue(that.header, + that.header.formatters[$.inArray(key, that.header.fields)], + [value, item, i], value); + + if (!($.inArray(key, that.header.fields) !== -1 && + (typeof value === 'string' || typeof value === 'number') && + (value + '').toLowerCase().indexOf(fval) !== -1)) { + return false; + } + } + return true; + }) : this.data; + }; + + BootstrapTable.prototype.onColumnSearch = function (event) { + var text = $.trim($(event.currentTarget).val()); + var $field = $(event.currentTarget).parent().parent().parent().data('field') + + if ($.isEmptyObject(this.filterColumnsPartial)) { + this.filterColumnsPartial = {}; + } + if (text) { + this.filterColumnsPartial[$field] = text; + } else { + delete this.filterColumnsPartial[$field]; + } + + this.options.pageNumber = 1; + this.onSearch(event); + this.updatePagination(); + this.trigger('column-search', $field, text); + }; +}(jQuery); diff --git a/public/assets/js/extensions/filter-control/bootstrap-table-filter-control.min.js b/public/assets/js/extensions/filter-control/bootstrap-table-filter-control.min.js new file mode 100644 index 0000000000..9a7457df02 --- /dev/null +++ b/public/assets/js/extensions/filter-control/bootstrap-table-filter-control.min.js @@ -0,0 +1,7 @@ +/* +* bootstrap-table - v1.8.1 - 2015-05-29 +* https://github.com/wenzhixin/bootstrap-table +* Copyright (c) 2015 zhixin wen +* Licensed MIT License +*/ +!function(a){"use strict";var b=function(a){var b=arguments,c=!0,d=1;return a=a.replace(/%s/g,function(){var a=b[d++];return"undefined"==typeof a?(c=!1,""):a}),c?a:""},c=function(b,c){var d=-1;return a.each(b,function(a,b){return b.field===c?(d=a,!1):!0}),d},d=function(b,c,d,e){if("string"==typeof c){var f=c.split(".");f.length>1?(c=window,a.each(f,function(a,b){c=c[b]})):c=window[c]}return"object"==typeof c?c:"function"==typeof c?c.apply(b,d):e};a.extend(a.fn.bootstrapTable.defaults,{filterControl:!1,onColumnSearch:function(){return!1}}),a.extend(a.fn.bootstrapTable.COLUMN_DEFAULTS,{filterControl:void 0,filterData:void 0}),a.extend(a.fn.bootstrapTable.Constructor.EVENTS,{"column-search.bs.table":"onColumnSearch"});var e=a.fn.bootstrapTable.Constructor,f=e.prototype.initHeader,g=e.prototype.initBody,h=e.prototype.initSearch;e.prototype.initHeader=function(){if(f.apply(this,Array.prototype.slice.apply(arguments)),this.options.filterControl){var c,d,e=!1,g=this,h=0;a.each(this.options.columns,function(f,h){if(c="hidden",d=[],h.visible){if(h.filterControl)switch(d.push('<div style="margin: 0px 2px 2px 2px;" class="filterControl">'),h.filterControl&&h.searchable&&(e=!0,c="visible"),h.filterControl.toLowerCase()){case"input":d.push(b('<input type="text" class="form-control" style="width: 100%; visibility: %s">',c));break;case"select":d.push(b('<select class="%s form-control" style="width: 100%; visibility: %s"></select>',h.field,c))}else d.push('<div style="height: 34px;"></div>');if(g.$header.find(b('.th-inner:eq("%s")',f)).next().append(d.join("")),void 0!==h.filterData&&"column"!==h.filterData.toLowerCase()){var i=h.filterData.substring(0,3),j=h.filterData.substring(4,h.filterData.length),k=a("."+h.field);switch(k.append(a("<option></option>").attr("value","").text("")),i){case"url":a.ajax({url:j,dataType:"json",success:function(b){a.each(b,function(b,c){k.append(a("<option></option>").attr("value",b).text(c))})}});break;case"var":var l=window[j];for(var m in l)k.append(a("<option></option>").attr("value",m).text(l[m]))}}}}),e?(this.$header.off("keyup","input").on("keyup","input",function(a){clearTimeout(h),h=setTimeout(function(){g.onColumnSearch(a)},g.options.searchTimeOut)}),this.$header.off("change","select").on("change","select",function(a){clearTimeout(h),h=setTimeout(function(){g.onColumnSearch(a)},g.options.searchTimeOut)})):this.$header.find(".filterControl").hide()}},e.prototype.initBody=function(){g.apply(this,Array.prototype.slice.apply(arguments));for(var b=this,e=this.getData(),f=this.pageFrom-1;f<this.pageTo;f++){var h=e[f];a.each(this.header.fields,function(e,g){var i=h[g],j=b.options.columns[c(b.options.columns,g)];if(i=d(b.header,b.header.formatters[e],[i,h,f],i),!(j.checkbox&&j.radio||void 0===j.filterControl||"select"!==j.filterControl.toLowerCase()||!j.searchable||void 0!==j.filterData&&"column"!==j.filterData.toLowerCase())){var k,l=a("."+j.field),m=0,n=!1;if(void 0!==l)if(k=l.get(0).options,0===k.length)l.append(a("<option></option>").attr("value","").text("")),l.append(a("<option></option>").attr("value",i).text(i));else{for(;m<k.length;m++)if(k[m].value===i){n=!0;break}n||l.append(a("<option></option>").attr("value",i).text(i))}}})}},e.prototype.initSearch=function(){h.apply(this,Array.prototype.slice.apply(arguments));var b=this,c=a.isEmptyObject(this.filterColumnsPartial)?null:this.filterColumnsPartial;this.data=c?a.grep(this.data,function(e,f){for(var g in c){var h=c[g].toLowerCase(),i=e[g];if(i=d(b.header,b.header.formatters[a.inArray(g,b.header.fields)],[i,e,f],i),-1===a.inArray(g,b.header.fields)||"string"!=typeof i&&"number"!=typeof i||-1===(i+"").toLowerCase().indexOf(h))return!1}return!0}):this.data},e.prototype.onColumnSearch=function(b){var c=a.trim(a(b.currentTarget).val()),d=a(b.currentTarget).parent().parent().parent().data("field");a.isEmptyObject(this.filterColumnsPartial)&&(this.filterColumnsPartial={}),c?this.filterColumnsPartial[d]=c:delete this.filterColumnsPartial[d],this.options.pageNumber=1,this.onSearch(b),this.updatePagination(),this.trigger("column-search",d,c)}}(jQuery); \ No newline at end of file diff --git a/public/assets/js/extensions/filter/bootstrap-table-filter.js b/public/assets/js/extensions/filter/bootstrap-table-filter.js new file mode 100644 index 0000000000..086566916f --- /dev/null +++ b/public/assets/js/extensions/filter/bootstrap-table-filter.js @@ -0,0 +1,67 @@ +/** + * @author zhixin wen <wenzhixin2010@gmail.com> + * extensions: https://github.com/lukaskral/bootstrap-table-filter + */ + +!function($) { + + 'use strict'; + + $.extend($.fn.bootstrapTable.defaults, { + showFilter: false + }); + + var BootstrapTable = $.fn.bootstrapTable.Constructor, + _init = BootstrapTable.prototype.init, + _initSearch = BootstrapTable.prototype.initSearch; + + BootstrapTable.prototype.init = function () { + _init.apply(this, Array.prototype.slice.apply(arguments)); + + var that = this; + this.$el.on('load-success.bs.table', function () { + if (that.options.showFilter) { + $(that.options.toolbar).bootstrapTableFilter({ + connectTo: that.$el + }); + } + }); + }; + + BootstrapTable.prototype.initSearch = function () { + _initSearch.apply(this, Array.prototype.slice.apply(arguments)); + + if (this.options.sidePagination !== 'server') { + if (typeof this.searchCallback === 'function') { + this.data = $.grep(this.options.data, this.searchCallback); + } + } + }; + + BootstrapTable.prototype.getData = function () { + return (this.searchText || this.searchCallback) ? this.data : this.options.data; + }; + + BootstrapTable.prototype.getColumns = function () { + return this.options.columns; + }; + + BootstrapTable.prototype.registerSearchCallback = function (callback) { + this.searchCallback = callback; + }; + + BootstrapTable.prototype.updateSearch = function () { + this.options.pageNumber = 1; + this.initSearch(); + this.updatePagination(); + }; + + BootstrapTable.prototype.getServerUrl = function () { + return (this.options.sidePagination === 'server') ? this.options.url : false; + }; + + $.fn.bootstrapTable.methods.push('getColumns', + 'registerSearchCallback', 'updateSearch', + 'getServerUrl'); + +}(jQuery); \ No newline at end of file diff --git a/public/assets/js/extensions/filter/bootstrap-table-filter.min.js b/public/assets/js/extensions/filter/bootstrap-table-filter.min.js new file mode 100644 index 0000000000..125cdb7bfa --- /dev/null +++ b/public/assets/js/extensions/filter/bootstrap-table-filter.min.js @@ -0,0 +1,7 @@ +/* +* bootstrap-table - v1.8.1 - 2015-05-29 +* https://github.com/wenzhixin/bootstrap-table +* Copyright (c) 2015 zhixin wen +* Licensed MIT License +*/ +!function(a){"use strict";a.extend(a.fn.bootstrapTable.defaults,{showFilter:!1});var b=a.fn.bootstrapTable.Constructor,c=b.prototype.init,d=b.prototype.initSearch;b.prototype.init=function(){c.apply(this,Array.prototype.slice.apply(arguments));var b=this;this.$el.on("load-success.bs.table",function(){b.options.showFilter&&a(b.options.toolbar).bootstrapTableFilter({connectTo:b.$el})})},b.prototype.initSearch=function(){d.apply(this,Array.prototype.slice.apply(arguments)),"server"!==this.options.sidePagination&&"function"==typeof this.searchCallback&&(this.data=a.grep(this.options.data,this.searchCallback))},b.prototype.getData=function(){return this.searchText||this.searchCallback?this.data:this.options.data},b.prototype.getColumns=function(){return this.options.columns},b.prototype.registerSearchCallback=function(a){this.searchCallback=a},b.prototype.updateSearch=function(){this.options.pageNumber=1,this.initSearch(),this.updatePagination()},b.prototype.getServerUrl=function(){return"server"===this.options.sidePagination?this.options.url:!1},a.fn.bootstrapTable.methods.push("getColumns","registerSearchCallback","updateSearch","getServerUrl")}(jQuery); \ No newline at end of file diff --git a/public/assets/js/extensions/flat-json/bootstrap-table-flat-json.js b/public/assets/js/extensions/flat-json/bootstrap-table-flat-json.js new file mode 100644 index 0000000000..f5f3a35c35 --- /dev/null +++ b/public/assets/js/extensions/flat-json/bootstrap-table-flat-json.js @@ -0,0 +1,70 @@ +/** + * @author: Dennis Hernández + * @webSite: http://djhvscf.github.io/Blog + * @version: v1.2.0 + */ + + +(function ($) { + 'use strict'; + + $.extend($.fn.bootstrapTable.defaults, { + flat: false + }); + + var BootstrapTable = $.fn.bootstrapTable.Constructor, + _initData = BootstrapTable.prototype.initData; + + BootstrapTable.prototype.initData = function (data, type) { + if( this.options.flat ){ + data = data === undefined ? this.options.data : data; + data = sd.flatHelper(data); + } + _initData.apply(this, [data, type]); + }; + + //Main functions + var sd = { + flat: function (element) { + var result = {}; + + function recurse(cur, prop) { + if (Object(cur) !== cur) { + result[prop] = cur; + } else if ($.isArray(cur)) { + for (var i = 0, l = cur.length; i < l; i++) { + recurse(cur[i], prop ? prop + "." + i : "" + i); + if (l == 0) { + result[prop] = []; + } + } + } else { + var isEmpty = true; + for (var p in cur) { + isEmpty = false; + recurse(cur[p], prop ? prop + "." + p : p); + } + if (isEmpty) { + result[prop] = {}; + } + } + } + + recurse(element, ""); + return result; + }, + + flatHelper: function (data) { + var flatArray = [], + arrayHelper = []; + if (!$.isArray(data)) { + arrayHelper.push(data); + data = arrayHelper; + } + $.each(data, function (i, element) { + flatArray.push(sd.flat(element)); + }); + return flatArray; + } + }; +})(jQuery); diff --git a/public/assets/js/extensions/flat-json/bootstrap-table-flat-json.min.js b/public/assets/js/extensions/flat-json/bootstrap-table-flat-json.min.js new file mode 100644 index 0000000000..d842a6cada --- /dev/null +++ b/public/assets/js/extensions/flat-json/bootstrap-table-flat-json.min.js @@ -0,0 +1,7 @@ +/* +* bootstrap-table - v1.8.1 - 2015-05-29 +* https://github.com/wenzhixin/bootstrap-table +* Copyright (c) 2015 zhixin wen +* Licensed MIT License +*/ +!function(a){"use strict";a.extend(a.fn.bootstrapTable.defaults,{flat:!1});var b=a.fn.bootstrapTable.Constructor,c=b.prototype.initData;b.prototype.initData=function(a,b){this.options.flat&&(a=void 0===a?this.options.data:a,a=d.flatHelper(a)),c.apply(this,[a,b])};var d={flat:function(b){function c(b,e){if(Object(b)!==b)d[e]=b;else if(a.isArray(b))for(var f=0,g=b.length;g>f;f++)c(b[f],e?e+"."+f:""+f),0==g&&(d[e]=[]);else{var h=!0;for(var i in b)h=!1,c(b[i],e?e+"."+i:i);h&&(d[e]={})}}var d={};return c(b,""),d},flatHelper:function(b){var c=[],e=[];return a.isArray(b)||(e.push(b),b=e),a.each(b,function(a,b){c.push(d.flat(b))}),c}}}(jQuery); \ No newline at end of file diff --git a/public/assets/js/extensions/key-events/bootstrap-table-key-events.js b/public/assets/js/extensions/key-events/bootstrap-table-key-events.js new file mode 100644 index 0000000000..ee33565189 --- /dev/null +++ b/public/assets/js/extensions/key-events/bootstrap-table-key-events.js @@ -0,0 +1,81 @@ +/** + * @author: Dennis Hernández + * @webSite: http://djhvscf.github.io/Blog + * @version: v1.0.0 + * + * @update zhixin wen <wenzhixin2010@gmail.com> + */ + +!function ($) { + + 'use strict'; + + $.extend($.fn.bootstrapTable.defaults, { + keyEvents: false + }); + + var BootstrapTable = $.fn.bootstrapTable.Constructor, + _init = BootstrapTable.prototype.init; + + BootstrapTable.prototype.init = function () { + _init.apply(this, Array.prototype.slice.apply(arguments)); + + this.initKeyEvents(); + }; + + BootstrapTable.prototype.initKeyEvents = function () { + if (this.options.keyEvents) { + var that = this; + + $(document).off('keydown').on('keydown', function (e) { + var $search = that.$toolbar.find('.search input'), + $refresh = that.$toolbar.find('button[name="refresh"]'), + $toggle = that.$toolbar.find('button[name="toggle"]'), + $paginationSwitch = that.$toolbar.find('button[name="paginationSwitch"]'); + + if (document.activeElement === $search.get(0)) { + return true; + } + + switch (e.keyCode) { + case 83: //s + if (!that.options.search) { + return; + } + $search.focus(); + return false; + case 82: //r + if (!that.options.showRefresh) { + return; + } + $refresh.click(); + return false; + case 84: //t + if (!that.options.showToggle) { + return; + } + $toggle.click(); + return false; + case 80: //p + if (!that.options.showPaginationSwitch) { + return; + } + $paginationSwitch.click(); + return false; + case 37: // left + if (!that.options.pagination) { + return; + } + that.prevPage(); + return false; + case 39: // right + if (!that.options.pagination) { + return; + } + that.nextPage(); + return; + } + }); + } + }; +}(jQuery); diff --git a/public/assets/js/extensions/key-events/bootstrap-table-key-events.min.js b/public/assets/js/extensions/key-events/bootstrap-table-key-events.min.js new file mode 100644 index 0000000000..e82ad41730 --- /dev/null +++ b/public/assets/js/extensions/key-events/bootstrap-table-key-events.min.js @@ -0,0 +1,7 @@ +/* +* bootstrap-table - v1.8.1 - 2015-05-29 +* https://github.com/wenzhixin/bootstrap-table +* Copyright (c) 2015 zhixin wen +* Licensed MIT License +*/ +!function(a){"use strict";a.extend(a.fn.bootstrapTable.defaults,{keyEvents:!1});var b=a.fn.bootstrapTable.Constructor,c=b.prototype.init;b.prototype.init=function(){c.apply(this,Array.prototype.slice.apply(arguments)),this.initKeyEvents()},b.prototype.initKeyEvents=function(){if(this.options.keyEvents){var b=this;a(document).off("keydown").on("keydown",function(a){var c=b.$toolbar.find(".search input"),d=b.$toolbar.find('button[name="refresh"]'),e=b.$toolbar.find('button[name="toggle"]'),f=b.$toolbar.find('button[name="paginationSwitch"]');if(document.activeElement===c.get(0))return!0;switch(a.keyCode){case 83:if(!b.options.search)return;return c.focus(),!1;case 82:if(!b.options.showRefresh)return;return d.click(),!1;case 84:if(!b.options.showToggle)return;return e.click(),!1;case 80:if(!b.options.showPaginationSwitch)return;return f.click(),!1;case 37:if(!b.options.pagination)return;return b.prevPage(),!1;case 39:if(!b.options.pagination)return;return void b.nextPage()}})}}}(jQuery); \ No newline at end of file diff --git a/public/assets/js/extensions/mobile/bootstrap-table-mobile.js b/public/assets/js/extensions/mobile/bootstrap-table-mobile.js new file mode 100644 index 0000000000..0917821d49 --- /dev/null +++ b/public/assets/js/extensions/mobile/bootstrap-table-mobile.js @@ -0,0 +1,87 @@ +/** + * @author: Dennis Hernández + * @webSite: http://djhvscf.github.io/Blog + * @version: v1.1.0 + */ + +!function ($) { + + 'use strict'; + + var resetView = function (that) { + if (that.options.height || that.options.showFooter) { + setTimeout(that.resetView(), 1); + } + }; + + var changeView = function (that, width, height) { + if (that.options.minHeight) { + if (checkValuesLessEqual(width, that.options.minWidth) && checkValuesLessEqual(height, that.options.minHeight)) { + conditionCardView(that); + } else if (checkValuesGreater(width, that.options.minWidth) && checkValuesGreater(height, that.options.minHeight)) { + conditionFullView(that); + } + } else { + if (checkValuesLessEqual(width, that.options.minWidth)) { + conditionCardView(that); + } else if (checkValuesGreater(width, that.options.minWidth)) { + conditionFullView(that); + } + } + + resetView(that); + }; + + var checkValuesLessEqual = function (currentValue, targetValue) { + return currentValue <= targetValue; + }; + + var checkValuesGreater = function (currentValue, targetValue) { + return currentValue > targetValue; + }; + + var conditionCardView = function (that) { + changeTableView(that, false); + }; + + var conditionFullView = function (that) { + changeTableView(that, true); + }; + + var changeTableView = function (that, cardViewState) { + that.options.cardView = cardViewState; + that.toggleView(); + }; + + $.extend($.fn.bootstrapTable.defaults, { + mobileResponsive: false, + minWidth: 562, + minHeight: undefined, + checkOnInit: true, + toggled: false + }); + + var BootstrapTable = $.fn.bootstrapTable.Constructor, + _init = BootstrapTable.prototype.init; + + BootstrapTable.prototype.init = function () { + _init.apply(this, Array.prototype.slice.apply(arguments)); + + if (!this.options.mobileResponsive) { + return; + } + + if (!this.options.minWidth) { + return; + } + + var that = this; + $(window).resize(function () { + changeView(that, $(this).width(), $(this).height()) + }); + + if (this.options.checkOnInit) { + changeView(this, $(window).width(), $(window).height()); + } + }; +}(jQuery); diff --git a/public/assets/js/extensions/mobile/bootstrap-table-mobile.min.js b/public/assets/js/extensions/mobile/bootstrap-table-mobile.min.js new file mode 100644 index 0000000000..843975add6 --- /dev/null +++ b/public/assets/js/extensions/mobile/bootstrap-table-mobile.min.js @@ -0,0 +1,7 @@ +/* +* bootstrap-table - v1.8.1 - 2015-05-29 +* https://github.com/wenzhixin/bootstrap-table +* Copyright (c) 2015 zhixin wen +* Licensed MIT License +*/ +!function(a){"use strict";var b=function(a){(a.options.height||a.options.showFooter)&&setTimeout(a.resetView(),1)},c=function(a,c,h){a.options.minHeight?d(c,a.options.minWidth)&&d(h,a.options.minHeight)?f(a):e(c,a.options.minWidth)&&e(h,a.options.minHeight)&&g(a):d(c,a.options.minWidth)?f(a):e(c,a.options.minWidth)&&g(a),b(a)},d=function(a,b){return b>=a},e=function(a,b){return a>b},f=function(a){h(a,!1)},g=function(a){h(a,!0)},h=function(a,b){a.options.cardView=b,a.toggleView()};a.extend(a.fn.bootstrapTable.defaults,{mobileResponsive:!1,minWidth:562,minHeight:void 0,checkOnInit:!0,toggled:!1});var i=a.fn.bootstrapTable.Constructor,j=i.prototype.init;i.prototype.init=function(){if(j.apply(this,Array.prototype.slice.apply(arguments)),this.options.mobileResponsive&&this.options.minWidth){var b=this;a(window).resize(function(){c(b,a(this).width(),a(this).height())}),this.options.checkOnInit&&c(this,a(window).width(),a(window).height())}}}(jQuery); \ No newline at end of file diff --git a/public/assets/js/extensions/multiple-sort/bootstrap-table-multiple-sort.js b/public/assets/js/extensions/multiple-sort/bootstrap-table-multiple-sort.js new file mode 100644 index 0000000000..fc8bb1c4e7 --- /dev/null +++ b/public/assets/js/extensions/multiple-sort/bootstrap-table-multiple-sort.js @@ -0,0 +1,370 @@ +/** + * @author Nadim Basalamah <dimbslmh@gmail.com> + * @version: v1.0.0 + * https://github.com/dimbslmh/bootstrap-table/tree/master/src/extensions/multiple-sort/bootstrap-table-multiple-sort.js + */ + +(function($) { + 'use strict'; + + var isSingleSort = false; + + var sort_order = { + asc: 'Ascending', + desc: 'Descending' + }, + arrowAsc = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAATCAYAAAByUDbMAAAAZ' + + '0lEQVQ4y2NgGLKgquEuFxBPAGI2ahhWCsS/gDibUoO0gPgxEP8H4ttArEyuQYxAPBd' + + 'qEAxPBImTY5gjEL9DM+wTENuQahAvEO9DMwiGdwAxOymGJQLxTyD+jgWDxCMZRsEoGAVo' + + 'AADeemwtPcZI2wAAAABJRU5ErkJggg==', + arrowDesc = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAATCAYAAAByUDbMAAAAZUlEQVQ4y2NgGAWj' + + 'YBSggaqGu5FA/BOIv2PBIPFEUgxjB+IdQPwfC94HxLykus4GiD+hGfQOiB3J8SojEE9EM2wuSJ' + + 'zcsFMG4ttQgx4DsRalkZENxL+AuJQaMcsGxBOAmGvopk8AVz1sLZgg0bsAAAAASUVORK5CYII= '; + + var showSortModal = function(that) { + if (!$("#sortModal").hasClass("modal")) { + var sModal = ' <div class="modal fade" id="sortModal" tabindex="-1" role="dialog" aria-labelledby="sortModalLabel" aria-hidden="true">'; + sModal += ' <div class="modal-dialog">'; + sModal += ' <div class="modal-content">'; + sModal += ' <div class="modal-header">'; + sModal += ' <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>'; + sModal += ' <h4 class="modal-title" id="sortModalLabel">' + that.options.formatMultipleSort() + '</h4>'; + sModal += ' </div>'; + sModal += ' <div class="modal-body">'; + sModal += ' <div class="bootstrap-table">'; + sModal += ' <div class="fixed-table-toolbar">'; + sModal += ' <div class="bars">'; + sModal += ' <div id="toolbar">'; + sModal += ' <button id="add" type="button" class="btn btn-default"><i class="' + that.options.iconsPrefix + ' ' + that.options.icons.plus + '"></i> ' + that.options.formatAddLevel() + '</button>'; + sModal += ' <button id="delete" type="button" class="btn btn-default" disabled><i class="' + that.options.iconsPrefix + ' ' + that.options.icons.minus + '"></i> ' + that.options.formatDeleteLevel() + '</button>'; + sModal += ' </div>'; + sModal += ' </div>'; + sModal += ' </div>'; + sModal += ' <div class="fixed-table-container">'; + sModal += ' <table id="multi-sort" class="table">'; + sModal += ' <thead>'; + sModal += ' <tr>'; + sModal += ' <th></th>'; + sModal += ' <th><div class="th-inner">' + that.options.formatColumn() + '</div></th>'; + sModal += ' <th><div class="th-inner">' + that.options.formatOrder() + '</div></th>'; + sModal += ' </tr>'; + sModal += ' </thead>'; + sModal += ' <tbody></tbody>'; + sModal += ' </table>'; + sModal += ' </div>'; + sModal += ' </div>'; + sModal += ' </div>'; + sModal += ' <div class="modal-footer">'; + sModal += ' <button type="button" class="btn btn-default" data-dismiss="modal">' + that.options.formatCancel() + '</button>'; + sModal += ' <button type="button" class="btn btn-primary">' + that.options.formatSort() + '</button>'; + sModal += ' </div>'; + sModal += ' </div>'; + sModal += ' </div>'; + sModal += ' </div>'; + + $("body").append($(sModal)); + + var $sortModal = $('#sortModal'), + $rows = $sortModal.find("tbody > tr"); + + $sortModal.off('click', '#add').on('click', '#add', function() { + var total = $sortModal.find('.multi-sort-name:first option').length, + current = $sortModal.find('tbody tr').length; + + if (current < total) { + current++; + that.addLevel(); + that.setButtonStates(); + } + }); + + $sortModal.off('click', '#delete').on('click', '#delete', function() { + var total = $sortModal.find('.multi-sort-name:first option').length, + current = $sortModal.find('tbody tr').length; + + if (current > 1 && current <= total) { + current--; + $sortModal.find('tbody tr:last').remove(); + that.setButtonStates(); + } + }); + + $sortModal.off('click', '.btn-primary').on('click', '.btn-primary', function() { + var $rows = $sortModal.find("tbody > tr"), + $alert = $sortModal.find('div.alert'), + fields = [], + results = []; + + + that.options.sortPriority = $.map($rows, function(row) { + var $row = $(row), + name = $row.find('.multi-sort-name').val(), + order = $row.find('.multi-sort-order').val(); + + fields.push(name); + + return { + sortName: name, + sortOrder: order + }; + }); + + var sorted_fields = fields.sort(); + + for (var i = 0; i < fields.length - 1; i++) { + if (sorted_fields[i + 1] == sorted_fields[i]) { + results.push(sorted_fields[i]); + } + } + + if (results.length > 0) { + if ($alert.length === 0) { + $alert = '<div class="alert alert-danger" role="alert"><strong>' + that.options.formatDuplicateAlertTitle() + '</strong> ' + that.options.formatDuplicateAlertDescription() + '</div>'; + $($alert).insertBefore($sortModal.find('.bars')); + } + } else { + if ($alert.length === 1) { + $($alert).remove(); + } + + that.options.sortName = ""; + that.onMultipleSort(); + $sortModal.modal('hide'); + } + }); + + if (that.options.sortPriority === null) { + if (that.options.sortName) { + that.options.sortPriority = [{ + sortName: that.options.sortName, + sortOrder: that.options.sortOrder + }]; + } + } + + if (that.options.sortPriority !== null) { + if ($rows.length < that.options.sortPriority.length && typeof that.options.sortPriority === 'object') { + for (var i = 0; i < that.options.sortPriority.length; i++) { + that.addLevel(i, that.options.sortPriority[i]); + } + } + } else { + that.addLevel(0); + } + + that.setButtonStates(); + } + }; + + $.extend($.fn.bootstrapTable.defaults, { + showMultiSort: false, + sortPriority: null, + onMultipleSort: function() { + return false; + } + }); + + $.extend($.fn.bootstrapTable.defaults.icons, { + sort: 'glyphicon-sort', + plus: 'glyphicon-plus', + minus: 'glyphicon-minus' + }); + + $.extend($.fn.bootstrapTable.Constructor.EVENTS, { + 'multiple-sort.bs.table': 'onMultipleSort' + }); + + $.extend($.fn.bootstrapTable.locales, { + formatMultipleSort: function() { + return 'Multiple Sort'; + }, + formatAddLevel: function() { + return "Add Level"; + }, + formatDeleteLevel: function() { + return "Delete Level"; + }, + formatColumn: function() { + return "Column"; + }, + formatOrder: function() { + return "Order"; + }, + formatSortBy: function() { + return "Sort by"; + }, + formatThenBy: function() { + return "Then by"; + }, + formatSort: function() { + return "Sort"; + }, + formatCancel: function() { + return "Cancel"; + }, + formatDuplicateAlertTitle: function() { + return "Duplicate(s) detected!"; + }, + formatDuplicateAlertDescription: function() { + return "Please remove or change any duplicate column."; + } + }); + + $.extend($.fn.bootstrapTable.defaults, $.fn.bootstrapTable.locales); + + var BootstrapTable = $.fn.bootstrapTable.Constructor, + _initToolbar = BootstrapTable.prototype.initToolbar; + + BootstrapTable.prototype.initToolbar = function() { + this.showToolbar = true; + var that = this; + + _initToolbar.apply(this, Array.prototype.slice.apply(arguments)); + + if (this.options.showMultiSort) { + var $btnGroup = this.$toolbar.find('>.btn-group'), + $multiSortBtn = $btnGroup.find('div.multi-sort'); + + if (!$multiSortBtn.length) { + $multiSortBtn = ' <button class="multi-sort btn btn-default' + (this.options.iconSize === undefined ? '' : ' btn-' + this.options.iconSize) + '" type="button" data-toggle="modal" data-target="#sortModal" title="' + this.options.formatMultipleSort() + '">'; + $multiSortBtn += ' <i class="' + this.options.iconsPrefix + ' ' + this.options.icons.sort + '"></i>'; + $multiSortBtn += '</button>'; + + $btnGroup.append($multiSortBtn); + + showSortModal(that); + } + + this.$el.one('sort.bs.table', function() { + isSingleSort = true; + }); + + this.$el.on('multiple-sort.bs.table', function() { + isSingleSort = false; + }); + + this.$el.on('load-success.bs.table', function() { + if (!isSingleSort && that.options.sortPriority !== null && typeof that.options.sortPriority === 'object') { + that.onMultipleSort(); + } + }); + + this.$el.on('column-switch.bs.table', function() { + that.options.sortPriority = null; + $('#sortModal').remove(); + showSortModal(that); + }); + } + }; + + BootstrapTable.prototype.onMultipleSort = function() { + var that = this; + + var cmp = function(x, y) { + return x > y ? 1 : x < y ? -1 : 0; + }; + + var arrayCmp = function(a, b) { + var arr1 = [], + arr2 = []; + + for (var i = 0; i < that.options.sortPriority.length; i++) { + var order = that.options.sortPriority[i].sortOrder === 'desc' ? -1 : 1, + aa = a[that.options.sortPriority[i].sortName], + bb = b[that.options.sortPriority[i].sortName]; + + if (aa === undefined || aa === null) { + aa = ''; + } + if (bb === undefined || bb === null) { + bb = ''; + } + if ($.isNumeric(aa) && $.isNumeric(bb)) { + aa = parseFloat(aa); + bb = parseFloat(bb); + } + if (typeof aa !== 'string') { + aa = aa.toString(); + } + + arr1.push( + order * cmp(aa, bb)); + arr2.push( + order * cmp(bb, aa)); + } + + return cmp(arr1, arr2); + }; + + this.data.sort(function(a, b) { + return arrayCmp(a, b); + }); + + this.initBody(); + this.assignSortableArrows(); + this.trigger('multiple-sort'); + }; + + BootstrapTable.prototype.addLevel = function(index, sortPriority) { + var $sortModal = $("#sortModal"), + text = index === 0 ? this.options.formatSortBy() : this.options.formatThenBy(); + + $sortModal.find('tbody') + .append($('<tr>') + .append($('<td>').text(text)) + .append($('<td>').append($('<select class="form-control multi-sort-name">'))) + .append($('<td>').append($('<select class="form-control multi-sort-order">'))) + ); + + var $multiSortName = $sortModal.find('.multi-sort-name').last(), + $multiSortOrder = $sortModal.find('.multi-sort-order').last(); + + this.options.columns.forEach(function(column) { + if (column.sortable === false || column.visible === false) { + return true; + } + $multiSortName.append('<option value="' + column.field + '">' + column.title + '</option>'); + }); + + $.each(sort_order, function(value, order) { + $multiSortOrder.append('<option value="' + value + '">' + order + '</option>'); + }); + + if (sortPriority !== undefined) { + $multiSortName.find('option[value="' + sortPriority.sortName + '"]').attr("selected", true); + $multiSortOrder.find('option[value="' + sortPriority.sortOrder + '"]').attr("selected", true); + } + }; + + BootstrapTable.prototype.assignSortableArrows = function() { + var that = this, + headers = that.$header.find('th'); + + for (var i = 0; i < headers.length; i++) { + for (var c = 0; c < that.options.sortPriority.length; c++) { + if ($(headers[i]).data('field') === that.options.sortPriority[c].sortName) { + $(headers[i]).find('.sortable').css('background-image', 'url(' + (that.options.sortPriority[c].sortOrder === 'desc' ? arrowDesc : arrowAsc) + ')'); + } + } + } + }; + + BootstrapTable.prototype.setButtonStates = function() { + var $sortModal = $('#sortModal'), + total = $sortModal.find('.multi-sort-name:first option').length, + current = $sortModal.find('tbody tr').length; + + if (current == total) { + $sortModal.find('#add').attr('disabled', 'disabled'); + } + if (current > 1) { + $sortModal.find('#delete').removeAttr('disabled'); + } + if (current < total) { + $sortModal.find('#add').removeAttr('disabled'); + } + if (current == 1) { + $sortModal.find('#delete').attr('disabled', 'disabled'); + } + }; +})(jQuery); diff --git a/public/assets/js/extensions/multiple-sort/bootstrap-table-multiple-sort.min.js b/public/assets/js/extensions/multiple-sort/bootstrap-table-multiple-sort.min.js new file mode 100644 index 0000000000..dbcf11a11f --- /dev/null +++ b/public/assets/js/extensions/multiple-sort/bootstrap-table-multiple-sort.min.js @@ -0,0 +1,7 @@ +/* +* bootstrap-table - v1.8.1 - 2015-05-29 +* https://github.com/wenzhixin/bootstrap-table +* Copyright (c) 2015 zhixin wen +* Licensed MIT License +*/ +!function(a){"use strict";var b=!1,c={asc:"Ascending",desc:"Descending"},d="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAATCAYAAAByUDbMAAAAZ0lEQVQ4y2NgGLKgquEuFxBPAGI2ahhWCsS/gDibUoO0gPgxEP8H4ttArEyuQYxAPBdqEAxPBImTY5gjEL9DM+wTENuQahAvEO9DMwiGdwAxOymGJQLxTyD+jgWDxCMZRsEoGAVoAADeemwtPcZI2wAAAABJRU5ErkJggg==",e="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAATCAYAAAByUDbMAAAAZUlEQVQ4y2NgGAWjYBSggaqGu5FA/BOIv2PBIPFEUgxjB+IdQPwfC94HxLykus4GiD+hGfQOiB3J8SojEE9EM2wuSJzcsFMG4ttQgx4DsRalkZENxL+AuJQaMcsGxBOAmGvopk8AVz1sLZgg0bsAAAAASUVORK5CYII= ",f=function(b){if(!a("#sortModal").hasClass("modal")){var c=' <div class="modal fade" id="sortModal" tabindex="-1" role="dialog" aria-labelledby="sortModalLabel" aria-hidden="true">';c+=' <div class="modal-dialog">',c+=' <div class="modal-content">',c+=' <div class="modal-header">',c+=' <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>',c+=' <h4 class="modal-title" id="sortModalLabel">'+b.options.formatMultipleSort()+"</h4>",c+=" </div>",c+=' <div class="modal-body">',c+=' <div class="bootstrap-table">',c+=' <div class="fixed-table-toolbar">',c+=' <div class="bars">',c+=' <div id="toolbar">',c+=' <button id="add" type="button" class="btn btn-default"><i class="'+b.options.iconsPrefix+" "+b.options.icons.plus+'"></i> '+b.options.formatAddLevel()+"</button>",c+=' <button id="delete" type="button" class="btn btn-default" disabled><i class="'+b.options.iconsPrefix+" "+b.options.icons.minus+'"></i> '+b.options.formatDeleteLevel()+"</button>",c+=" </div>",c+=" </div>",c+=" </div>",c+=' <div class="fixed-table-container">',c+=' <table id="multi-sort" class="table">',c+=" <thead>",c+=" <tr>",c+=" <th></th>",c+=' <th><div class="th-inner">'+b.options.formatColumn()+"</div></th>",c+=' <th><div class="th-inner">'+b.options.formatOrder()+"</div></th>",c+=" </tr>",c+=" </thead>",c+=" <tbody></tbody>",c+=" </table>",c+=" </div>",c+=" </div>",c+=" </div>",c+=' <div class="modal-footer">',c+=' <button type="button" class="btn btn-default" data-dismiss="modal">'+b.options.formatCancel()+"</button>",c+=' <button type="button" class="btn btn-primary">'+b.options.formatSort()+"</button>",c+=" </div>",c+=" </div>",c+=" </div>",c+=" </div>",a("body").append(a(c));var d=a("#sortModal"),e=d.find("tbody > tr");if(d.off("click","#add").on("click","#add",function(){var a=d.find(".multi-sort-name:first option").length,c=d.find("tbody tr").length;a>c&&(c++,b.addLevel(),b.setButtonStates())}),d.off("click","#delete").on("click","#delete",function(){var a=d.find(".multi-sort-name:first option").length,c=d.find("tbody tr").length;c>1&&a>=c&&(c--,d.find("tbody tr:last").remove(),b.setButtonStates())}),d.off("click",".btn-primary").on("click",".btn-primary",function(){var c=d.find("tbody > tr"),e=d.find("div.alert"),f=[],g=[];b.options.sortPriority=a.map(c,function(b){var c=a(b),d=c.find(".multi-sort-name").val(),e=c.find(".multi-sort-order").val();return f.push(d),{sortName:d,sortOrder:e}});for(var h=f.sort(),i=0;i<f.length-1;i++)h[i+1]==h[i]&&g.push(h[i]);g.length>0?0===e.length&&(e='<div class="alert alert-danger" role="alert"><strong>'+b.options.formatDuplicateAlertTitle()+"</strong> "+b.options.formatDuplicateAlertDescription()+"</div>",a(e).insertBefore(d.find(".bars"))):(1===e.length&&a(e).remove(),b.options.sortName="",b.onMultipleSort(),d.modal("hide"))}),null===b.options.sortPriority&&b.options.sortName&&(b.options.sortPriority=[{sortName:b.options.sortName,sortOrder:b.options.sortOrder}]),null!==b.options.sortPriority){if(e.length<b.options.sortPriority.length&&"object"==typeof b.options.sortPriority)for(var f=0;f<b.options.sortPriority.length;f++)b.addLevel(f,b.options.sortPriority[f])}else b.addLevel(0);b.setButtonStates()}};a.extend(a.fn.bootstrapTable.defaults,{showMultiSort:!1,sortPriority:null,onMultipleSort:function(){return!1}}),a.extend(a.fn.bootstrapTable.defaults.icons,{sort:"glyphicon-sort",plus:"glyphicon-plus",minus:"glyphicon-minus"}),a.extend(a.fn.bootstrapTable.Constructor.EVENTS,{"multiple-sort.bs.table":"onMultipleSort"}),a.extend(a.fn.bootstrapTable.locales,{formatMultipleSort:function(){return"Multiple Sort"},formatAddLevel:function(){return"Add Level"},formatDeleteLevel:function(){return"Delete Level"},formatColumn:function(){return"Column"},formatOrder:function(){return"Order"},formatSortBy:function(){return"Sort by"},formatThenBy:function(){return"Then by"},formatSort:function(){return"Sort"},formatCancel:function(){return"Cancel"},formatDuplicateAlertTitle:function(){return"Duplicate(s) detected!"},formatDuplicateAlertDescription:function(){return"Please remove or change any duplicate column."}}),a.extend(a.fn.bootstrapTable.defaults,a.fn.bootstrapTable.locales);var g=a.fn.bootstrapTable.Constructor,h=g.prototype.initToolbar;g.prototype.initToolbar=function(){this.showToolbar=!0;var c=this;if(h.apply(this,Array.prototype.slice.apply(arguments)),this.options.showMultiSort){var d=this.$toolbar.find(">.btn-group"),e=d.find("div.multi-sort");e.length||(e=' <button class="multi-sort btn btn-default'+(void 0===this.options.iconSize?"":" btn-"+this.options.iconSize)+'" type="button" data-toggle="modal" data-target="#sortModal" title="'+this.options.formatMultipleSort()+'">',e+=' <i class="'+this.options.iconsPrefix+" "+this.options.icons.sort+'"></i>',e+="</button>",d.append(e),f(c)),this.$el.one("sort.bs.table",function(){b=!0}),this.$el.on("multiple-sort.bs.table",function(){b=!1}),this.$el.on("load-success.bs.table",function(){b||null===c.options.sortPriority||"object"!=typeof c.options.sortPriority||c.onMultipleSort()}),this.$el.on("column-switch.bs.table",function(){c.options.sortPriority=null,a("#sortModal").remove(),f(c)})}},g.prototype.onMultipleSort=function(){var b=this,c=function(a,b){return a>b?1:b>a?-1:0},d=function(d,e){for(var f=[],g=[],h=0;h<b.options.sortPriority.length;h++){var i="desc"===b.options.sortPriority[h].sortOrder?-1:1,j=d[b.options.sortPriority[h].sortName],k=e[b.options.sortPriority[h].sortName];(void 0===j||null===j)&&(j=""),(void 0===k||null===k)&&(k=""),a.isNumeric(j)&&a.isNumeric(k)&&(j=parseFloat(j),k=parseFloat(k)),"string"!=typeof j&&(j=j.toString()),f.push(i*c(j,k)),g.push(i*c(k,j))}return c(f,g)};this.data.sort(function(a,b){return d(a,b)}),this.initBody(),this.assignSortableArrows(),this.trigger("multiple-sort")},g.prototype.addLevel=function(b,d){var e=a("#sortModal"),f=0===b?this.options.formatSortBy():this.options.formatThenBy();e.find("tbody").append(a("<tr>").append(a("<td>").text(f)).append(a("<td>").append(a('<select class="form-control multi-sort-name">'))).append(a("<td>").append(a('<select class="form-control multi-sort-order">'))));var g=e.find(".multi-sort-name").last(),h=e.find(".multi-sort-order").last();this.options.columns.forEach(function(a){return a.sortable===!1||a.visible===!1?!0:void g.append('<option value="'+a.field+'">'+a.title+"</option>")}),a.each(c,function(a,b){h.append('<option value="'+a+'">'+b+"</option>")}),void 0!==d&&(g.find('option[value="'+d.sortName+'"]').attr("selected",!0),h.find('option[value="'+d.sortOrder+'"]').attr("selected",!0))},g.prototype.assignSortableArrows=function(){for(var b=this,c=b.$header.find("th"),f=0;f<c.length;f++)for(var g=0;g<b.options.sortPriority.length;g++)a(c[f]).data("field")===b.options.sortPriority[g].sortName&&a(c[f]).find(".sortable").css("background-image","url("+("desc"===b.options.sortPriority[g].sortOrder?e:d)+")")},g.prototype.setButtonStates=function(){var b=a("#sortModal"),c=b.find(".multi-sort-name:first option").length,d=b.find("tbody tr").length;d==c&&b.find("#add").attr("disabled","disabled"),d>1&&b.find("#delete").removeAttr("disabled"),c>d&&b.find("#add").removeAttr("disabled"),1==d&&b.find("#delete").attr("disabled","disabled")}}(jQuery); \ No newline at end of file diff --git a/public/assets/js/extensions/natural-sorting/bootstrap-table-natural-sorting.js b/public/assets/js/extensions/natural-sorting/bootstrap-table-natural-sorting.js new file mode 100644 index 0000000000..8e84eb659b --- /dev/null +++ b/public/assets/js/extensions/natural-sorting/bootstrap-table-natural-sorting.js @@ -0,0 +1,47 @@ +/** + * @author: Brian Huisman + * @webSite: http://www.greywyvern.com + * @version: v1.0.0 + * JS function to allow natural sorting on bootstrap-table columns + * just add data-sorter="alphanum" to any th + * + * @update Dennis Hernández <http://djhvscf.github.io/Blog> + */ + +function alphanum(a, b) { + function chunkify(t) { + var tz = [], + x = 0, + y = -1, + n = 0, + i, + j; + + while (i = (j = t.charAt(x++)).charCodeAt(0)) { + var m = (i === 46 || (i >= 48 && i <= 57)); + if (m !== n) { + tz[++y] = ""; + n = m; + } + tz[y] += j; + } + return tz; + } + + var aa = chunkify(a); + var bb = chunkify(b); + + for (x = 0; aa[x] && bb[x]; x++) { + if (aa[x] !== bb[x]) { + var c = Number(aa[x]), + d = Number(bb[x]); + + if (c == aa[x] && d == bb[x]) { + return c - d; + } else { + return (aa[x] > bb[x]) ? 1 : -1; + } + } + } + return aa.length - bb.length; +} \ No newline at end of file diff --git a/public/assets/js/extensions/natural-sorting/bootstrap-table-natural-sorting.min.js b/public/assets/js/extensions/natural-sorting/bootstrap-table-natural-sorting.min.js new file mode 100644 index 0000000000..3d1130f722 --- /dev/null +++ b/public/assets/js/extensions/natural-sorting/bootstrap-table-natural-sorting.min.js @@ -0,0 +1,7 @@ +/* +* bootstrap-table - v1.8.1 - 2015-05-29 +* https://github.com/wenzhixin/bootstrap-table +* Copyright (c) 2015 zhixin wen +* Licensed MIT License +*/ +function alphanum(a,b){function c(a){for(var b,c,d=[],e=0,f=-1,g=0;b=(c=a.charAt(e++)).charCodeAt(0);){var h=46===b||b>=48&&57>=b;h!==g&&(d[++f]="",g=h),d[f]+=c}return d}var d=c(a),e=c(b);for(x=0;d[x]&&e[x];x++)if(d[x]!==e[x]){var f=Number(d[x]),g=Number(e[x]);return f==d[x]&&g==e[x]?f-g:d[x]>e[x]?1:-1}return d.length-e.length} \ No newline at end of file diff --git a/public/assets/js/extensions/reorder-columns/bootstrap-table-reorder-columns.js b/public/assets/js/extensions/reorder-columns/bootstrap-table-reorder-columns.js new file mode 100644 index 0000000000..7ae94b3414 --- /dev/null +++ b/public/assets/js/extensions/reorder-columns/bootstrap-table-reorder-columns.js @@ -0,0 +1,118 @@ +/** + * @author: Dennis Hernández + * @webSite: http://djhvscf.github.io/Blog + * @version: v1.1.0 + */ + +!function ($) { + + 'use strict'; + + var getFieldIndex = function (columns, field) { + var index = -1; + + $.each(columns, function (i, column) { + if (column.field === field) { + index = i; + return false; + } + return true; + }); + return index; + }; + + $.extend($.fn.bootstrapTable.defaults, { + reorderableColumns: false, + maxMovingRows: 10, + onReorderColumn: function (headerFields) { + return false; + } + }); + + $.extend($.fn.bootstrapTable.Constructor.EVENTS, { + 'reorder-column.bs.table': 'onReorderColumn' + }); + + var BootstrapTable = $.fn.bootstrapTable.Constructor, + _initHeader = BootstrapTable.prototype.initHeader, + _toggleColumn = BootstrapTable.prototype.toggleColumn, + _toggleView = BootstrapTable.prototype.toggleView, + _resetView = BootstrapTable.prototype.resetView; + + BootstrapTable.prototype.initHeader = function () { + _initHeader.apply(this, Array.prototype.slice.apply(arguments)); + + if (!this.options.reorderableColumns) { + return; + } + + this.makeRowsReorderable(); + }; + + BootstrapTable.prototype.toggleColumn = function () { + _toggleColumn.apply(this, Array.prototype.slice.apply(arguments)); + + if (!this.options.reorderableColumns) { + return; + } + + this.makeRowsReorderable(); + }; + + BootstrapTable.prototype.toggleView = function () { + _toggleView.apply(this, Array.prototype.slice.apply(arguments)); + + if (!this.options.reorderableColumns) { + return; + } + + if (this.options.cardView) { + return; + } + + this.makeRowsReorderable(); + }; + + BootstrapTable.prototype.resetView = function () { + _resetView.apply(this, Array.prototype.slice.apply(arguments)); + + if (!this.options.reorderableColumns) { + return; + } + + this.makeRowsReorderable(); + }; + + BootstrapTable.prototype.makeRowsReorderable = function () { + + var that = this; + try { + $(this.$el).dragtable('destroy'); + } catch (e) {} + $(this.$el).dragtable({ + maxMovingRows: that.options.maxMovingRows, + clickDelay:200, + beforeStop: function() { + var ths = [], + columns = [], + columnIndex = -1; + that.$header.find('th').each(function (i) { + ths.push($(this).data('field')); + }); + + for (var i = 0; i < ths.length; i++ ) { + columnIndex = getFieldIndex(that.options.columns, ths[i]); + if (columnIndex !== -1) { + columns.push(that.options.columns[columnIndex]); + that.options.columns.splice(columnIndex, 1); + } + } + + that.options.columns = that.options.columns.concat(columns); + that.header.fields = ths; + that.resetView(); + that.trigger('reorder-column', ths); + } + }); + }; +}(jQuery); \ No newline at end of file diff --git a/public/assets/js/extensions/reorder-columns/bootstrap-table-reorder-columns.min.js b/public/assets/js/extensions/reorder-columns/bootstrap-table-reorder-columns.min.js new file mode 100644 index 0000000000..466c379311 --- /dev/null +++ b/public/assets/js/extensions/reorder-columns/bootstrap-table-reorder-columns.min.js @@ -0,0 +1,7 @@ +/* +* bootstrap-table - v1.8.1 - 2015-05-29 +* https://github.com/wenzhixin/bootstrap-table +* Copyright (c) 2015 zhixin wen +* Licensed MIT License +*/ +!function(a){"use strict";var b=function(b,c){var d=-1;return a.each(b,function(a,b){return b.field===c?(d=a,!1):!0}),d};a.extend(a.fn.bootstrapTable.defaults,{reorderableColumns:!1,maxMovingRows:10,onReorderColumn:function(){return!1}}),a.extend(a.fn.bootstrapTable.Constructor.EVENTS,{"reorder-column.bs.table":"onReorderColumn"});var c=a.fn.bootstrapTable.Constructor,d=c.prototype.initHeader,e=c.prototype.toggleColumn,f=c.prototype.toggleView,g=c.prototype.resetView;c.prototype.initHeader=function(){d.apply(this,Array.prototype.slice.apply(arguments)),this.options.reorderableColumns&&this.makeRowsReorderable()},c.prototype.toggleColumn=function(){e.apply(this,Array.prototype.slice.apply(arguments)),this.options.reorderableColumns&&this.makeRowsReorderable()},c.prototype.toggleView=function(){f.apply(this,Array.prototype.slice.apply(arguments)),this.options.reorderableColumns&&(this.options.cardView||this.makeRowsReorderable())},c.prototype.resetView=function(){g.apply(this,Array.prototype.slice.apply(arguments)),this.options.reorderableColumns&&this.makeRowsReorderable()},c.prototype.makeRowsReorderable=function(){var c=this;try{a(this.$el).dragtable("destroy")}catch(d){}a(this.$el).dragtable({maxMovingRows:c.options.maxMovingRows,clickDelay:200,beforeStop:function(){var d=[],e=[],f=-1;c.$header.find("th").each(function(){d.push(a(this).data("field"))});for(var g=0;g<d.length;g++)f=b(c.options.columns,d[g]),-1!==f&&(e.push(c.options.columns[f]),c.options.columns.splice(f,1));c.options.columns=c.options.columns.concat(e),c.header.fields=d,c.resetView(),c.trigger("reorder-column",d)}})}}(jQuery); \ No newline at end of file diff --git a/public/assets/js/extensions/reorder-rows/bootstrap-table-reorder-rows.css b/public/assets/js/extensions/reorder-rows/bootstrap-table-reorder-rows.css new file mode 100644 index 0000000000..412ff145e3 --- /dev/null +++ b/public/assets/js/extensions/reorder-rows/bootstrap-table-reorder-rows.css @@ -0,0 +1,14 @@ +.reorder_rows_onDragClass td { + background-color: #eee; + -webkit-box-shadow: 11px 5px 12px 2px #333, 0 1px 0 #ccc inset, 0 -1px 0 #ccc inset; + -webkit-box-shadow: 6px 3px 5px #555, 0 1px 0 #ccc inset, 0 -1px 0 #ccc inset; + -moz-box-shadow: 6px 4px 5px 1px #555, 0 1px 0 #ccc inset, 0 -1px 0 #ccc inset; + -box-shadow: 6px 4px 5px 1px #555, 0 1px 0 #ccc inset, 0 -1px 0 #ccc inset; +} + +.reorder_rows_onDragClass td:last-child { + -webkit-box-shadow: 8px 7px 12px 0 #333, 0 1px 0 #ccc inset, 0 -1px 0 #ccc inset; + -webkit-box-shadow: 1px 8px 6px -4px #555, 0 1px 0 #ccc inset, 0 -1px 0 #ccc inset; + -moz-box-shadow: 0 9px 4px -4px #555, 0 1px 0 #ccc inset, 0 -1px 0 #ccc inset, -1px 0 0 #ccc inset; + -box-shadow: 0 9px 4px -4px #555, 0 1px 0 #ccc inset, 0 -1px 0 #ccc inset, -1px 0 0 #ccc inset; +} \ No newline at end of file diff --git a/public/assets/js/extensions/reorder-rows/bootstrap-table-reorder-rows.js b/public/assets/js/extensions/reorder-rows/bootstrap-table-reorder-rows.js new file mode 100644 index 0000000000..c65d6f666e --- /dev/null +++ b/public/assets/js/extensions/reorder-rows/bootstrap-table-reorder-rows.js @@ -0,0 +1,115 @@ +/** + * @author: Dennis Hernández + * @webSite: http://djhvscf.github.io/Blog + * @version: v1.0.0 + */ + +!function ($) { + + 'use strict'; + + var isSearch = false; + + var rowAttr = function (row, index) { + return { + id: 'customId_' + index + }; + }; + + $.extend($.fn.bootstrapTable.defaults, { + reorderableRows: false, + onDragStyle: null, + onDropStyle: null, + onDragClass: "reorder_rows_onDragClass", + dragHandle: null, + useRowAttrFunc: false, + onReorderRowsDrag: function (table, row) { + return false; + }, + onReorderRowsDrop: function (table, row) { + return false; + }, + onReorderRow: function (newData) { + return false; + } + }); + + $.extend($.fn.bootstrapTable.Constructor.EVENTS, { + 'reorder-row.bs.table': 'onReorderRow' + }); + + var BootstrapTable = $.fn.bootstrapTable.Constructor, + _init = BootstrapTable.prototype.init, + _initSearch = BootstrapTable.prototype.initSearch; + + BootstrapTable.prototype.init = function () { + + _init.apply(this, Array.prototype.slice.apply(arguments)); + + if (!this.options.reorderableRows) { + return; + } + + var that = this; + if (this.options.useRowAttrFunc) { + this.options.rowAttributes = rowAttr; + } + + var onPostBody = this.options.onPostBody; + this.options.onPostBody = function () { + setTimeout(function () { + that.makeRowsReorderable(); + onPostBody.apply(); + }, 1); + }; + }; + + BootstrapTable.prototype.initSearch = function () { + _initSearch.apply(this, Array.prototype.slice.apply(arguments)); + + if (!this.options.reorderableRows) { + return; + } + + //Known issue after search if you reorder the rows the data is not display properly + //isSearch = true; + }; + + BootstrapTable.prototype.makeRowsReorderable = function () { + if (this.options.cardView) { + return; + } + + var that = this; + this.$el.tableDnD({ + onDragStyle: that.options.onDragStyle, + onDropStyle: that.options.onDropStyle, + onDragClass: that.options.onDragClass, + onDrop: that.onDrop, + onDragStart: that.options.onReorderRowsDrag, + dragHandle: that.options.dragHandle + }); + }; + + BootstrapTable.prototype.onDrop = function (table, row) { + var tableBs = $(table), + tableBsData = tableBs.data('bootstrap.table'), + tableBsOptions = tableBs.data('bootstrap.table').options, + row = null, + newData = []; + + for (var i = 0; i < table.tBodies[0].rows.length; i++) { + row = $(table.tBodies[0].rows[i]); + newData.push(tableBsOptions.data[row.data('index')]); + row.data('index', i).attr('data-index', i); + } + + tableBsOptions.data = newData; + + //Call the user defined function + tableBsOptions.onReorderRowsDrop.apply(table, row); + + //Call the event reorder-row + tableBsData.trigger('reorder-row', newData); + }; +}(jQuery); \ No newline at end of file diff --git a/public/assets/js/extensions/reorder-rows/bootstrap-table-reorder-rows.min.js b/public/assets/js/extensions/reorder-rows/bootstrap-table-reorder-rows.min.js new file mode 100644 index 0000000000..785f15a121 --- /dev/null +++ b/public/assets/js/extensions/reorder-rows/bootstrap-table-reorder-rows.min.js @@ -0,0 +1,7 @@ +/* +* bootstrap-table - v1.8.1 - 2015-05-29 +* https://github.com/wenzhixin/bootstrap-table +* Copyright (c) 2015 zhixin wen +* Licensed MIT License +*/ +!function(a){"use strict";var b=function(a,b){return{id:"customId_"+b}};a.extend(a.fn.bootstrapTable.defaults,{reorderableRows:!1,onDragStyle:null,onDropStyle:null,onDragClass:"reorder_rows_onDragClass",dragHandle:null,useRowAttrFunc:!1,onReorderRowsDrag:function(){return!1},onReorderRowsDrop:function(){return!1},onReorderRow:function(){return!1}}),a.extend(a.fn.bootstrapTable.Constructor.EVENTS,{"reorder-row.bs.table":"onReorderRow"});var c=a.fn.bootstrapTable.Constructor,d=c.prototype.init,e=c.prototype.initSearch;c.prototype.init=function(){if(d.apply(this,Array.prototype.slice.apply(arguments)),this.options.reorderableRows){var a=this;this.options.useRowAttrFunc&&(this.options.rowAttributes=b);var c=this.options.onPostBody;this.options.onPostBody=function(){setTimeout(function(){a.makeRowsReorderable(),c.apply()},1)}}},c.prototype.initSearch=function(){e.apply(this,Array.prototype.slice.apply(arguments)),!this.options.reorderableRows},c.prototype.makeRowsReorderable=function(){if(!this.options.cardView){var a=this;this.$el.tableDnD({onDragStyle:a.options.onDragStyle,onDropStyle:a.options.onDropStyle,onDragClass:a.options.onDragClass,onDrop:a.onDrop,onDragStart:a.options.onReorderRowsDrag,dragHandle:a.options.dragHandle})}},c.prototype.onDrop=function(b,c){for(var d=a(b),e=d.data("bootstrap.table"),f=d.data("bootstrap.table").options,c=null,g=[],h=0;h<b.tBodies[0].rows.length;h++)c=a(b.tBodies[0].rows[h]),g.push(f.data[c.data("index")]),c.data("index",h).attr("data-index",h);f.data=g,f.onReorderRowsDrop.apply(b,c),e.trigger("reorder-row",g)}}(jQuery); \ No newline at end of file diff --git a/public/assets/js/extensions/resizable/bootstrap-table-resizable.js b/public/assets/js/extensions/resizable/bootstrap-table-resizable.js new file mode 100644 index 0000000000..8be7b09641 --- /dev/null +++ b/public/assets/js/extensions/resizable/bootstrap-table-resizable.js @@ -0,0 +1,74 @@ +/** + * @author: Dennis Hernández + * @webSite: http://djhvscf.github.io/Blog + * @version: v1.0.0 + */ + +(function ($) { + 'use strict'; + + var initResizable = function (that) { + //Deletes the plugin to re-create it + that.$el.colResizable({disable: true}); + + //Creates the plugin + that.$el.colResizable({ + liveDrag: that.options.liveDrag, + fixed: that.options.fixed, + headerOnly: that.options.headerOnly, + minWidth: that.options.minWidth, + hoverCursor: that.options.hoverCursor, + dragCursor: that.options.dragCursor, + onResize: that.onResize, + onDrag: that.options.onResizableDrag + }); + }; + + $.extend($.fn.bootstrapTable.defaults, { + resizable: false, + liveDrag: false, + fixed: true, + headerOnly: false, + minWidth: 15, + hoverCursor: 'e-resize', + dragCursor: 'e-resize', + onResizableResize: function (e) { + return false; + }, + onResizableDrag: function (e) { + return false; + } + }); + + var BootstrapTable = $.fn.bootstrapTable.Constructor, + _toggleView = BootstrapTable.prototype.toggleView, + _resetView = BootstrapTable.prototype.resetView; + + BootstrapTable.prototype.toggleView = function () { + _toggleView.apply(this, Array.prototype.slice.apply(arguments)); + + if (this.options.resizable && this.options.cardView) { + //Deletes the plugin + $(this.$el).colResizable({disable: true}); + } + }; + + BootstrapTable.prototype.resetView = function () { + var that = this; + + _resetView.apply(this, Array.prototype.slice.apply(arguments)); + + if (this.options.resizable) { + // because in fitHeader function, we use setTimeout(func, 100); + setTimeout(function () { + initResizable(that); + }, 100); + } + }; + + BootstrapTable.prototype.onResize = function (e) { + var that = $(e.currentTarget); + that.bootstrapTable('resetView'); + that.data('bootstrap.table').options.onResizableResize.apply(e); + } +})(jQuery); diff --git a/public/assets/js/extensions/resizable/bootstrap-table-resizable.min.js b/public/assets/js/extensions/resizable/bootstrap-table-resizable.min.js new file mode 100644 index 0000000000..3be404fd6c --- /dev/null +++ b/public/assets/js/extensions/resizable/bootstrap-table-resizable.min.js @@ -0,0 +1,7 @@ +/* +* bootstrap-table - v1.8.1 - 2015-05-29 +* https://github.com/wenzhixin/bootstrap-table +* Copyright (c) 2015 zhixin wen +* Licensed MIT License +*/ +!function(a){"use strict";var b=function(a){a.$el.colResizable({disable:!0}),a.$el.colResizable({liveDrag:a.options.liveDrag,fixed:a.options.fixed,headerOnly:a.options.headerOnly,minWidth:a.options.minWidth,hoverCursor:a.options.hoverCursor,dragCursor:a.options.dragCursor,onResize:a.onResize,onDrag:a.options.onResizableDrag})};a.extend(a.fn.bootstrapTable.defaults,{resizable:!1,liveDrag:!1,fixed:!0,headerOnly:!1,minWidth:15,hoverCursor:"e-resize",dragCursor:"e-resize",onResizableResize:function(){return!1},onResizableDrag:function(){return!1}});var c=a.fn.bootstrapTable.Constructor,d=c.prototype.toggleView,e=c.prototype.resetView;c.prototype.toggleView=function(){d.apply(this,Array.prototype.slice.apply(arguments)),this.options.resizable&&this.options.cardView&&a(this.$el).colResizable({disable:!0})},c.prototype.resetView=function(){var a=this;e.apply(this,Array.prototype.slice.apply(arguments)),this.options.resizable&&setTimeout(function(){b(a)},100)},c.prototype.onResize=function(b){var c=a(b.currentTarget);c.bootstrapTable("resetView"),c.data("bootstrap.table").options.onResizableResize.apply(b)}}(jQuery); \ No newline at end of file diff --git a/public/assets/js/extensions/toolbar/bootstrap-table-toolbar.js b/public/assets/js/extensions/toolbar/bootstrap-table-toolbar.js new file mode 100644 index 0000000000..0e7f4dbb29 --- /dev/null +++ b/public/assets/js/extensions/toolbar/bootstrap-table-toolbar.js @@ -0,0 +1,237 @@ +/** + * @author: aperez <aperez@datadec.es> + * @version: v2.0.0 + * + * @update Dennis Hernández <http://djhvscf.github.io/Blog> + */ + +!function($) { + 'use strict'; + + var firstLoad = false; + + var sprintf = function(str) { + var args = arguments, + flag = true, + i = 1; + + str = str.replace(/%s/g, function() { + var arg = args[i++]; + + if (typeof arg === 'undefined') { + flag = false; + return ''; + } + return arg; + }); + return flag ? str : ''; + }; + + var calculateObjectValue = function (self, name, args, defaultValue) { + if (typeof name === 'string') { + // support obj.func1.func2 + var names = name.split('.'); + + if (names.length > 1) { + name = window; + $.each(names, function (i, f) { + name = name[f]; + }); + } else { + name = window[name]; + } + } + if (typeof name === 'object') { + return name; + } + if (typeof name === 'function') { + return name.apply(self, args); + } + return defaultValue; + }; + + var showAvdSearch = function(pColumns, searchTitle, searchText, that) { + if (!$("#avdSearchModal").hasClass("modal")) { + var vModal = "<div id=\"avdSearchModal\" class=\"modal fade\" tabindex=\"-1\" role=\"dialog\" aria-labelledby=\"mySmallModalLabel\" aria-hidden=\"true\">"; + vModal += "<div class=\"modal-dialog modal-xs\">"; + vModal += " <div class=\"modal-content\">"; + vModal += " <div class=\"modal-header\">"; + vModal += " <button type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-hidden=\"true\" >×</button>"; + vModal += sprintf(" <h4 class=\"modal-title\">%s</h4>", searchTitle); + vModal += " </div>"; + vModal += " <div class=\"modal-body modal-body-custom\">"; + vModal += " <div class=\"container-fluid\" id=\"avdSearchModalContent\" style=\"padding-right: 0px;padding-left: 0px;\" >"; + vModal += " </div>"; + vModal += " </div>"; + vModal += " </div>"; + vModal += " </div>"; + vModal += "</div>"; + + $("body").append($(vModal)); + + var vFormAvd = createFormAvd(pColumns, searchText, that), + timeoutId = 0;; + + $('#avdSearchModalContent').append(vFormAvd.join('')); + + $('#' + that.options.idForm).off('keyup blur', 'input').on('keyup blur', 'input', function (event) { + clearTimeout(timeoutId); + timeoutId = setTimeout(function () { + that.onColumnAdvancedSearch(event); + }, that.options.searchTimeOut); + }); + + $("#btnCloseAvd").click(function() { + $("#avdSearchModal").modal('hide'); + }); + + $("#avdSearchModal").modal(); + } else { + $("#avdSearchModal").modal(); + } + }; + + var createFormAvd = function(pColumns, searchText, that) { + var htmlForm = []; + htmlForm.push(sprintf('<form class="form-horizontal" id="%s" action="%s" >', that.options.idForm, that.options.actionForm)); + for (var i in pColumns) { + var vObjCol = pColumns[i]; + if (!vObjCol.checkbox && vObjCol.visible && vObjCol.searchable) { + htmlForm.push('<div class="form-group">'); + htmlForm.push(sprintf('<label class="col-sm-4 control-label">%s</label>', vObjCol.title)); + htmlForm.push('<div class="col-sm-6">'); + htmlForm.push(sprintf('<input type="text" class="form-control input-md" name="%s" placeholder="%s" id="%s">', vObjCol.field, vObjCol.title, vObjCol.field)); + htmlForm.push('</div>'); + htmlForm.push('</div>'); + } + } + + htmlForm.push('<div class="form-group">'); + htmlForm.push('<div class="col-sm-offset-9 col-sm-3">'); + htmlForm.push(sprintf('<button type="button" id="btnCloseAvd" class="btn btn-default" >%s</button>', searchText)); + htmlForm.push('</div>'); + htmlForm.push('</div>'); + htmlForm.push('</form>'); + + return htmlForm; + }; + + $.extend($.fn.bootstrapTable.defaults, { + advancedSearch: false, + idForm: 'advancedSearch', + actionForm: '', + idTable: undefined, + onColumnAdvancedSearch: function (field, text) { + return false; + } + }); + + $.extend($.fn.bootstrapTable.defaults.icons, { + advancedSearchIcon: 'glyphicon-chevron-down' + }); + + $.extend($.fn.bootstrapTable.Constructor.EVENTS, { + 'column-advanced-search.bs.table': 'onColumnAdvancedSearch' + }); + + $.extend($.fn.bootstrapTable.locales, { + formatAdvancedSearch: function() { + return 'Advanced search'; + }, + formatAdvancedCloseButton: function() { + return "Close"; + } + }); + + $.extend($.fn.bootstrapTable.defaults, $.fn.bootstrapTable.locales); + + var BootstrapTable = $.fn.bootstrapTable.Constructor, + _initToolbar = BootstrapTable.prototype.initToolbar, + _load = BootstrapTable.prototype.load, + _initSearch = BootstrapTable.prototype.initSearch; + + BootstrapTable.prototype.initToolbar = function() { + _initToolbar.apply(this, Array.prototype.slice.apply(arguments)); + + if (!this.options.search) { + return; + } + + if (!this.options.advancedSearch) { + return; + } + + var that = this, + html = []; + + html.push(sprintf('<div class="columns columns-%s btn-group pull-%s" role="group">', this.options.buttonsAlign, this.options.buttonsAlign)); + html.push(sprintf('<button class="btn btn-default%s' + '" type="button" name="advancedSearch" title="%s">', that.options.iconSize === undefined ? '' : ' btn-' + that.options.iconSize, that.options.formatAdvancedSearch())); + html.push(sprintf('<i class="%s %s"></i>', that.options.iconsPrefix, that.options.icons.advancedSearchIcon)) + html.push('</button></div>'); + + that.$toolbar.prepend(html.join('')); + + that.$toolbar.find('button[name="advancedSearch"]') + .off('click').on('click', function() { + showAvdSearch(that.options.columns, that.options.formatAdvancedSearch(), that.options.formatAdvancedCloseButton(), that); + }); + }; + + BootstrapTable.prototype.load = function(data) { + _load.apply(this, Array.prototype.slice.apply(arguments)); + + if (typeof this.options.idTable === 'undefined') { + return; + } else { + if (!firstLoad) { + var height = parseInt($(".bootstrap-table").height()); + height += 10; + $("#" + this.options.idTable).bootstrapTable("resetView", {height: height}); + firstLoad = true; + } + } + }; + + BootstrapTable.prototype.initSearch = function () { + _initSearch.apply(this, Array.prototype.slice.apply(arguments)); + + var that = this; + var fp = $.isEmptyObject(this.filterColumnsPartial) ? null : this.filterColumnsPartial; + + this.data = fp ? $.grep(this.data, function (item, i) { + for (var key in fp) { + var fval = fp[key].toLowerCase(); + var value = item[key]; + value = calculateObjectValue(that.header, + that.header.formatters[$.inArray(key, that.header.fields)], + [value, item, i], value); + + if (!($.inArray(key, that.header.fields) !== -1 && + (typeof value === 'string' || typeof value === 'number') && + (value + '').toLowerCase().indexOf(fval) !== -1)) { + return false; + } + } + return true; + }) : this.data; + }; + + BootstrapTable.prototype.onColumnAdvancedSearch = function (event) { + var text = $.trim($(event.currentTarget).val()); + var $field = $(event.currentTarget)[0].id; + + if ($.isEmptyObject(this.filterColumnsPartial)) { + this.filterColumnsPartial = {}; + } + if (text) { + this.filterColumnsPartial[$field] = text; + } else { + delete this.filterColumnsPartial[$field]; + } + + this.options.pageNumber = 1; + this.onSearch(event); + this.updatePagination(); + this.trigger('column-advanced-search', $field, text); + }; +}(jQuery); diff --git a/public/assets/js/extensions/toolbar/bootstrap-table-toolbar.min.js b/public/assets/js/extensions/toolbar/bootstrap-table-toolbar.min.js new file mode 100644 index 0000000000..0f26ac6e2c --- /dev/null +++ b/public/assets/js/extensions/toolbar/bootstrap-table-toolbar.min.js @@ -0,0 +1,7 @@ +/* +* bootstrap-table - v1.8.1 - 2015-05-29 +* https://github.com/wenzhixin/bootstrap-table +* Copyright (c) 2015 zhixin wen +* Licensed MIT License +*/ +!function(a){"use strict";var b=!1,c=function(a){var b=arguments,c=!0,d=1;return a=a.replace(/%s/g,function(){var a=b[d++];return"undefined"==typeof a?(c=!1,""):a}),c?a:""},d=function(b,c,d,e){if("string"==typeof c){var f=c.split(".");f.length>1?(c=window,a.each(f,function(a,b){c=c[b]})):c=window[c]}return"object"==typeof c?c:"function"==typeof c?c.apply(b,d):e},e=function(b,d,e,g){if(a("#avdSearchModal").hasClass("modal"))a("#avdSearchModal").modal();else{var h='<div id="avdSearchModal" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="mySmallModalLabel" aria-hidden="true">';h+='<div class="modal-dialog modal-xs">',h+=' <div class="modal-content">',h+=' <div class="modal-header">',h+=' <button type="button" class="close" data-dismiss="modal" aria-hidden="true" >×</button>',h+=c(' <h4 class="modal-title">%s</h4>',d),h+=" </div>",h+=' <div class="modal-body modal-body-custom">',h+=' <div class="container-fluid" id="avdSearchModalContent" style="padding-right: 0px;padding-left: 0px;" >',h+=" </div>",h+=" </div>",h+=" </div>",h+=" </div>",h+="</div>",a("body").append(a(h));var i=f(b,e,g),j=0;a("#avdSearchModalContent").append(i.join("")),a("#"+g.options.idForm).off("keyup blur","input").on("keyup blur","input",function(a){clearTimeout(j),j=setTimeout(function(){g.onColumnAdvancedSearch(a)},g.options.searchTimeOut)}),a("#btnCloseAvd").click(function(){a("#avdSearchModal").modal("hide")}),a("#avdSearchModal").modal()}},f=function(a,b,d){var e=[];e.push(c('<form class="form-horizontal" id="%s" action="%s" >',d.options.idForm,d.options.actionForm));for(var f in a){var g=a[f];!g.checkbox&&g.visible&&g.searchable&&(e.push('<div class="form-group">'),e.push(c('<label class="col-sm-4 control-label">%s</label>',g.title)),e.push('<div class="col-sm-6">'),e.push(c('<input type="text" class="form-control input-md" name="%s" placeholder="%s" id="%s">',g.field,g.title,g.field)),e.push("</div>"),e.push("</div>"))}return e.push('<div class="form-group">'),e.push('<div class="col-sm-offset-9 col-sm-3">'),e.push(c('<button type="button" id="btnCloseAvd" class="btn btn-default" >%s</button>',b)),e.push("</div>"),e.push("</div>"),e.push("</form>"),e};a.extend(a.fn.bootstrapTable.defaults,{advancedSearch:!1,idForm:"advancedSearch",actionForm:"",idTable:void 0,onColumnAdvancedSearch:function(){return!1}}),a.extend(a.fn.bootstrapTable.defaults.icons,{advancedSearchIcon:"glyphicon-chevron-down"}),a.extend(a.fn.bootstrapTable.Constructor.EVENTS,{"column-advanced-search.bs.table":"onColumnAdvancedSearch"}),a.extend(a.fn.bootstrapTable.locales,{formatAdvancedSearch:function(){return"Advanced search"},formatAdvancedCloseButton:function(){return"Close"}}),a.extend(a.fn.bootstrapTable.defaults,a.fn.bootstrapTable.locales);var g=a.fn.bootstrapTable.Constructor,h=g.prototype.initToolbar,i=g.prototype.load,j=g.prototype.initSearch;g.prototype.initToolbar=function(){if(h.apply(this,Array.prototype.slice.apply(arguments)),this.options.search&&this.options.advancedSearch){var a=this,b=[];b.push(c('<div class="columns columns-%s btn-group pull-%s" role="group">',this.options.buttonsAlign,this.options.buttonsAlign)),b.push(c('<button class="btn btn-default%s" type="button" name="advancedSearch" title="%s">',void 0===a.options.iconSize?"":" btn-"+a.options.iconSize,a.options.formatAdvancedSearch())),b.push(c('<i class="%s %s"></i>',a.options.iconsPrefix,a.options.icons.advancedSearchIcon)),b.push("</button></div>"),a.$toolbar.prepend(b.join("")),a.$toolbar.find('button[name="advancedSearch"]').off("click").on("click",function(){e(a.options.columns,a.options.formatAdvancedSearch(),a.options.formatAdvancedCloseButton(),a)})}},g.prototype.load=function(){if(i.apply(this,Array.prototype.slice.apply(arguments)),"undefined"!=typeof this.options.idTable&&!b){var c=parseInt(a(".bootstrap-table").height());c+=10,a("#"+this.options.idTable).bootstrapTable("resetView",{height:c}),b=!0}},g.prototype.initSearch=function(){j.apply(this,Array.prototype.slice.apply(arguments));var b=this,c=a.isEmptyObject(this.filterColumnsPartial)?null:this.filterColumnsPartial;this.data=c?a.grep(this.data,function(e,f){for(var g in c){var h=c[g].toLowerCase(),i=e[g];if(i=d(b.header,b.header.formatters[a.inArray(g,b.header.fields)],[i,e,f],i),-1===a.inArray(g,b.header.fields)||"string"!=typeof i&&"number"!=typeof i||-1===(i+"").toLowerCase().indexOf(h))return!1}return!0}):this.data},g.prototype.onColumnAdvancedSearch=function(b){var c=a.trim(a(b.currentTarget).val()),d=a(b.currentTarget)[0].id;a.isEmptyObject(this.filterColumnsPartial)&&(this.filterColumnsPartial={}),c?this.filterColumnsPartial[d]=c:delete this.filterColumnsPartial[d],this.options.pageNumber=1,this.onSearch(b),this.updatePagination(),this.trigger("column-advanced-search",d,c)}}(jQuery); \ No newline at end of file diff --git a/public/assets/js/libs/FileSaver/FileSaver.min.js b/public/assets/js/libs/FileSaver/FileSaver.min.js new file mode 100644 index 0000000000..c0792332af --- /dev/null +++ b/public/assets/js/libs/FileSaver/FileSaver.min.js @@ -0,0 +1,2 @@ +/*! @source http://purl.eligrey.com/github/FileSaver.js/blob/master/FileSaver.js */ +var saveAs=saveAs||function(e){"use strict";if("undefined"==typeof navigator||!/MSIE [1-9]\./.test(navigator.userAgent)){var t=e.document,n=function(){return e.URL||e.webkitURL||e},o=t.createElementNS("http://www.w3.org/1999/xhtml","a"),r="download"in o,i=function(n){var o=t.createEvent("MouseEvents");o.initMouseEvent("click",!0,!1,e,0,0,0,0,0,!1,!1,!1,!1,0,null),n.dispatchEvent(o)},a=e.webkitRequestFileSystem,c=e.requestFileSystem||a||e.mozRequestFileSystem,u=function(t){(e.setImmediate||e.setTimeout)(function(){throw t},0)},f="application/octet-stream",s=0,d=500,l=function(t){var o=function(){"string"==typeof t?n().revokeObjectURL(t):t.remove()};e.chrome?o():setTimeout(o,d)},v=function(e,t,n){t=[].concat(t);for(var o=t.length;o--;){var r=e["on"+t[o]];if("function"==typeof r)try{r.call(e,n||e)}catch(i){u(i)}}},p=function(e){return/^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(e.type)?new Blob(["\ufeff",e],{type:e.type}):e},w=function(t,u){t=p(t);var d,w,y,m=this,S=t.type,h=!1,O=function(){v(m,"writestart progress write writeend".split(" "))},E=function(){if((h||!d)&&(d=n().createObjectURL(t)),w)w.location.href=d;else{var o=e.open(d,"_blank");void 0==o&&"undefined"!=typeof safari&&(e.location.href=d)}m.readyState=m.DONE,O(),l(d)},R=function(e){return function(){return m.readyState!==m.DONE?e.apply(this,arguments):void 0}},b={create:!0,exclusive:!1};return m.readyState=m.INIT,u||(u="download"),r?(d=n().createObjectURL(t),o.href=d,o.download=u,i(o),m.readyState=m.DONE,O(),void l(d)):(e.chrome&&S&&S!==f&&(y=t.slice||t.webkitSlice,t=y.call(t,0,t.size,f),h=!0),a&&"download"!==u&&(u+=".download"),(S===f||a)&&(w=e),c?(s+=t.size,void c(e.TEMPORARY,s,R(function(e){e.root.getDirectory("saved",b,R(function(e){var n=function(){e.getFile(u,b,R(function(e){e.createWriter(R(function(n){n.onwriteend=function(t){w.location.href=e.toURL(),m.readyState=m.DONE,v(m,"writeend",t),l(e)},n.onerror=function(){var e=n.error;e.code!==e.ABORT_ERR&&E()},"writestart progress write abort".split(" ").forEach(function(e){n["on"+e]=m["on"+e]}),n.write(t),m.abort=function(){n.abort(),m.readyState=m.DONE},m.readyState=m.WRITING}),E)}),E)};e.getFile(u,{create:!1},R(function(e){e.remove(),n()}),R(function(e){e.code===e.NOT_FOUND_ERR?n():E()}))}),E)}),E)):void E())},y=w.prototype,m=function(e,t){return new w(e,t)};return"undefined"!=typeof navigator&&navigator.msSaveOrOpenBlob?function(e,t){return navigator.msSaveOrOpenBlob(p(e),t)}:(y.abort=function(){var e=this;e.readyState=e.DONE,v(e,"abort")},y.readyState=y.INIT=0,y.WRITING=1,y.DONE=2,y.error=y.onwritestart=y.onprogress=y.onwrite=y.onabort=y.onerror=y.onwriteend=null,m)}}("undefined"!=typeof self&&self||"undefined"!=typeof window&&window||this.content);"undefined"!=typeof module&&module.exports?module.exports.saveAs=saveAs:"undefined"!=typeof define&&null!==define&&null!=define.amd&&define([],function(){return saveAs}); \ No newline at end of file diff --git a/public/assets/js/libs/FileSaver/LICENSE.md b/public/assets/js/libs/FileSaver/LICENSE.md new file mode 100644 index 0000000000..9e3115bd5e --- /dev/null +++ b/public/assets/js/libs/FileSaver/LICENSE.md @@ -0,0 +1,9 @@ +Copyright © 2015 [Eli Grey][1]. + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + [1]: http://eligrey.com diff --git a/public/assets/js/libs/html2canvas/LICENSE b/public/assets/js/libs/html2canvas/LICENSE new file mode 100644 index 0000000000..a73ffc9143 --- /dev/null +++ b/public/assets/js/libs/html2canvas/LICENSE @@ -0,0 +1,22 @@ +Copyright (c) 2012 Niklas von Hertzen + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/public/assets/js/libs/html2canvas/html2canvas.min.js b/public/assets/js/libs/html2canvas/html2canvas.min.js new file mode 100644 index 0000000000..b3d8eb06d8 --- /dev/null +++ b/public/assets/js/libs/html2canvas/html2canvas.min.js @@ -0,0 +1,9 @@ +/* + html2canvas 0.5.0-alpha2 <http://html2canvas.hertzen.com> + Copyright (c) 2015 Niklas von Hertzen + + Released under MIT License +*/ +!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var n;"undefined"!=typeof window?n=window:"undefined"!=typeof global?n=global:"undefined"!=typeof self&&(n=self),n.html2canvas=e()}}(function(){var e;return function n(e,f,o){function d(t,l){if(!f[t]){if(!e[t]){var s="function"==typeof require&&require;if(!l&&s)return s(t,!0);if(i)return i(t,!0);var u=new Error("Cannot find module '"+t+"'");throw u.code="MODULE_NOT_FOUND",u}var a=f[t]={exports:{}};e[t][0].call(a.exports,function(n){var f=e[t][1][n];return d(f?f:n)},a,a.exports,n,e,f,o)}return f[t].exports}for(var i="function"==typeof require&&require,t=0;t<o.length;t++)d(o[t]);return d}({1:[function(n,f){(function(n,o){(function(){"use strict";function d(e){return"function"==typeof e||"object"==typeof e&&null!==e}function i(e){return"function"==typeof e}function t(e){return"object"==typeof e&&null!==e}function l(){}function s(){return function(){n.nextTick(c)}}function u(){var e=0,n=new P(c),f=document.createTextNode("");return n.observe(f,{characterData:!0}),function(){f.data=e=++e%2}}function a(){var e=new MessageChannel;return e.port1.onmessage=c,function(){e.port2.postMessage(0)}}function p(){return function(){setTimeout(c,1)}}function c(){for(var e=0;M>e;e+=2){var n=R[e],f=R[e+1];n(f),R[e]=void 0,R[e+1]=void 0}M=0}function y(){}function m(){return new TypeError("You cannot resolve a promise with itself")}function r(){return new TypeError("A promises callback cannot return that same promise.")}function v(e){try{return e.then}catch(n){return V.error=n,V}}function w(e,n,f,o){try{e.call(n,f,o)}catch(d){return d}}function b(e,n,f){N(function(e){var o=!1,d=w(f,n,function(f){o||(o=!0,n!==f?x(e,f):k(e,f))},function(n){o||(o=!0,q(e,n))},"Settle: "+(e._label||" unknown promise"));!o&&d&&(o=!0,q(e,d))},e)}function g(e,n){n._state===T?k(e,n._result):e._state===U?q(e,n._result):z(n,void 0,function(n){x(e,n)},function(n){q(e,n)})}function h(e,n){if(n.constructor===e.constructor)g(e,n);else{var f=v(n);f===V?q(e,V.error):void 0===f?k(e,n):i(f)?b(e,n,f):k(e,n)}}function x(e,n){e===n?q(e,m()):d(n)?h(e,n):k(e,n)}function j(e){e._onerror&&e._onerror(e._result),A(e)}function k(e,n){e._state===S&&(e._result=n,e._state=T,0===e._subscribers.length||N(A,e))}function q(e,n){e._state===S&&(e._state=U,e._result=n,N(j,e))}function z(e,n,f,o){var d=e._subscribers,i=d.length;e._onerror=null,d[i]=n,d[i+T]=f,d[i+U]=o,0===i&&e._state&&N(A,e)}function A(e){var n=e._subscribers,f=e._state;if(0!==n.length){for(var o,d,i=e._result,t=0;t<n.length;t+=3)o=n[t],d=n[t+f],o?D(f,o,d,i):d(i);e._subscribers.length=0}}function B(){this.error=null}function C(e,n){try{return e(n)}catch(f){return W.error=f,W}}function D(e,n,f,o){var d,t,l,s,u=i(f);if(u){if(d=C(f,o),d===W?(s=!0,t=d.error,d=null):l=!0,n===d)return void q(n,r())}else d=o,l=!0;n._state!==S||(u&&l?x(n,d):s?q(n,t):e===T?k(n,d):e===U&&q(n,d))}function E(e,n){try{n(function(n){x(e,n)},function(n){q(e,n)})}catch(f){q(e,f)}}function F(e,n,f,o){this._instanceConstructor=e,this.promise=new e(y,o),this._abortOnReject=f,this._validateInput(n)?(this._input=n,this.length=n.length,this._remaining=n.length,this._init(),0===this.length?k(this.promise,this._result):(this.length=this.length||0,this._enumerate(),0===this._remaining&&k(this.promise,this._result))):q(this.promise,this._validationError())}function G(){throw new TypeError("You must pass a resolver function as the first argument to the promise constructor")}function H(){throw new TypeError("Failed to construct 'Promise': Please use the 'new' operator, this object constructor cannot be called as a function.")}function I(e){this._id=en++,this._state=void 0,this._result=void 0,this._subscribers=[],y!==e&&(i(e)||G(),this instanceof I||H(),E(this,e))}var J;J=Array.isArray?Array.isArray:function(e){return"[object Array]"===Object.prototype.toString.call(e)};var K,L=J,M=(Date.now||function(){return(new Date).getTime()},Object.create||function(e){if(arguments.length>1)throw new Error("Second argument not supported");if("object"!=typeof e)throw new TypeError("Argument must be an object");return l.prototype=e,new l},0),N=function(e,n){R[M]=e,R[M+1]=n,M+=2,2===M&&K()},O="undefined"!=typeof window?window:{},P=O.MutationObserver||O.WebKitMutationObserver,Q="undefined"!=typeof Uint8ClampedArray&&"undefined"!=typeof importScripts&&"undefined"!=typeof MessageChannel,R=new Array(1e3);K="undefined"!=typeof n&&"[object process]"==={}.toString.call(n)?s():P?u():Q?a():p();var S=void 0,T=1,U=2,V=new B,W=new B;F.prototype._validateInput=function(e){return L(e)},F.prototype._validationError=function(){return new Error("Array Methods must be provided an Array")},F.prototype._init=function(){this._result=new Array(this.length)};var X=F;F.prototype._enumerate=function(){for(var e=this.length,n=this.promise,f=this._input,o=0;n._state===S&&e>o;o++)this._eachEntry(f[o],o)},F.prototype._eachEntry=function(e,n){var f=this._instanceConstructor;t(e)?e.constructor===f&&e._state!==S?(e._onerror=null,this._settledAt(e._state,n,e._result)):this._willSettleAt(f.resolve(e),n):(this._remaining--,this._result[n]=this._makeResult(T,n,e))},F.prototype._settledAt=function(e,n,f){var o=this.promise;o._state===S&&(this._remaining--,this._abortOnReject&&e===U?q(o,f):this._result[n]=this._makeResult(e,n,f)),0===this._remaining&&k(o,this._result)},F.prototype._makeResult=function(e,n,f){return f},F.prototype._willSettleAt=function(e,n){var f=this;z(e,void 0,function(e){f._settledAt(T,n,e)},function(e){f._settledAt(U,n,e)})};var Y=function(e,n){return new X(this,e,!0,n).promise},Z=function(e,n){function f(e){x(i,e)}function o(e){q(i,e)}var d=this,i=new d(y,n);if(!L(e))return q(i,new TypeError("You must pass an array to race.")),i;for(var t=e.length,l=0;i._state===S&&t>l;l++)z(d.resolve(e[l]),void 0,f,o);return i},$=function(e,n){var f=this;if(e&&"object"==typeof e&&e.constructor===f)return e;var o=new f(y,n);return x(o,e),o},_=function(e,n){var f=this,o=new f(y,n);return q(o,e),o},en=0,nn=I;I.all=Y,I.race=Z,I.resolve=$,I.reject=_,I.prototype={constructor:I,then:function(e,n){var f=this,o=f._state;if(o===T&&!e||o===U&&!n)return this;var d=new this.constructor(y),i=f._result;if(o){var t=arguments[o-1];N(function(){D(o,d,t,i)})}else z(f,d,e,n);return d},"catch":function(e){return this.then(null,e)}};var fn=function(){var e;e="undefined"!=typeof o?o:"undefined"!=typeof window&&window.document?window:self;var n="Promise"in e&&"resolve"in e.Promise&&"reject"in e.Promise&&"all"in e.Promise&&"race"in e.Promise&&function(){var n;return new e.Promise(function(e){n=e}),i(n)}();n||(e.Promise=nn)},on={Promise:nn,polyfill:fn};"function"==typeof e&&e.amd?e(function(){return on}):"undefined"!=typeof f&&f.exports?f.exports=on:"undefined"!=typeof this&&(this.ES6Promise=on)}).call(this)}).call(this,n("_process"),"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{_process:2}],2:[function(e,n){function f(){if(!t){t=!0;for(var e,n=i.length;n;){e=i,i=[];for(var f=-1;++f<n;)e[f]();n=i.length}t=!1}}function o(){}var d=n.exports={},i=[],t=!1;d.nextTick=function(e){i.push(e),t||setTimeout(f,0)},d.title="browser",d.browser=!0,d.env={},d.argv=[],d.version="",d.on=o,d.addListener=o,d.once=o,d.off=o,d.removeListener=o,d.removeAllListeners=o,d.emit=o,d.binding=function(){throw new Error("process.binding is not supported")},d.cwd=function(){return"/"},d.chdir=function(){throw new Error("process.chdir is not supported")},d.umask=function(){return 0}},{}],3:[function(n,f,o){(function(n){!function(d){function i(e){throw RangeError(I[e])}function t(e,n){for(var f=e.length;f--;)e[f]=n(e[f]);return e}function l(e,n){return t(e.split(H),n).join(".")}function s(e){for(var n,f,o=[],d=0,i=e.length;i>d;)n=e.charCodeAt(d++),n>=55296&&56319>=n&&i>d?(f=e.charCodeAt(d++),56320==(64512&f)?o.push(((1023&n)<<10)+(1023&f)+65536):(o.push(n),d--)):o.push(n);return o}function u(e){return t(e,function(e){var n="";return e>65535&&(e-=65536,n+=L(e>>>10&1023|55296),e=56320|1023&e),n+=L(e)}).join("")}function a(e){return 10>e-48?e-22:26>e-65?e-65:26>e-97?e-97:k}function p(e,n){return e+22+75*(26>e)-((0!=n)<<5)}function c(e,n,f){var o=0;for(e=f?K(e/B):e>>1,e+=K(e/n);e>J*z>>1;o+=k)e=K(e/J);return K(o+(J+1)*e/(e+A))}function y(e){var n,f,o,d,t,l,s,p,y,m,r=[],v=e.length,w=0,b=D,g=C;for(f=e.lastIndexOf(E),0>f&&(f=0),o=0;f>o;++o)e.charCodeAt(o)>=128&&i("not-basic"),r.push(e.charCodeAt(o));for(d=f>0?f+1:0;v>d;){for(t=w,l=1,s=k;d>=v&&i("invalid-input"),p=a(e.charCodeAt(d++)),(p>=k||p>K((j-w)/l))&&i("overflow"),w+=p*l,y=g>=s?q:s>=g+z?z:s-g,!(y>p);s+=k)m=k-y,l>K(j/m)&&i("overflow"),l*=m;n=r.length+1,g=c(w-t,n,0==t),K(w/n)>j-b&&i("overflow"),b+=K(w/n),w%=n,r.splice(w++,0,b)}return u(r)}function m(e){var n,f,o,d,t,l,u,a,y,m,r,v,w,b,g,h=[];for(e=s(e),v=e.length,n=D,f=0,t=C,l=0;v>l;++l)r=e[l],128>r&&h.push(L(r));for(o=d=h.length,d&&h.push(E);v>o;){for(u=j,l=0;v>l;++l)r=e[l],r>=n&&u>r&&(u=r);for(w=o+1,u-n>K((j-f)/w)&&i("overflow"),f+=(u-n)*w,n=u,l=0;v>l;++l)if(r=e[l],n>r&&++f>j&&i("overflow"),r==n){for(a=f,y=k;m=t>=y?q:y>=t+z?z:y-t,!(m>a);y+=k)g=a-m,b=k-m,h.push(L(p(m+g%b,0))),a=K(g/b);h.push(L(p(a,0))),t=c(f,w,o==d),f=0,++o}++f,++n}return h.join("")}function r(e){return l(e,function(e){return F.test(e)?y(e.slice(4).toLowerCase()):e})}function v(e){return l(e,function(e){return G.test(e)?"xn--"+m(e):e})}var w="object"==typeof o&&o,b="object"==typeof f&&f&&f.exports==w&&f,g="object"==typeof n&&n;(g.global===g||g.window===g)&&(d=g);var h,x,j=2147483647,k=36,q=1,z=26,A=38,B=700,C=72,D=128,E="-",F=/^xn--/,G=/[^ -~]/,H=/\x2E|\u3002|\uFF0E|\uFF61/g,I={overflow:"Overflow: input needs wider integers to process","not-basic":"Illegal input >= 0x80 (not a basic code point)","invalid-input":"Invalid input"},J=k-q,K=Math.floor,L=String.fromCharCode;if(h={version:"1.2.4",ucs2:{decode:s,encode:u},decode:y,encode:m,toASCII:v,toUnicode:r},"function"==typeof e&&"object"==typeof e.amd&&e.amd)e("punycode",function(){return h});else if(w&&!w.nodeType)if(b)b.exports=h;else for(x in h)h.hasOwnProperty(x)&&(w[x]=h[x]);else d.punycode=h}(this)}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{}],4:[function(e,n){function f(e,n,f){!e.defaultView||n===e.defaultView.pageXOffset&&f===e.defaultView.pageYOffset||e.defaultView.scrollTo(n,f)}function o(e,n){try{n&&(n.width=e.width,n.height=e.height,n.getContext("2d").putImageData(e.getContext("2d").getImageData(0,0,e.width,e.height),0,0))}catch(f){t("Unable to copy canvas content from",e,f)}}function d(e,n){for(var f=3===e.nodeType?document.createTextNode(e.nodeValue):e.cloneNode(!1),i=e.firstChild;i;)(n===!0||1!==i.nodeType||"SCRIPT"!==i.nodeName)&&f.appendChild(d(i,n)),i=i.nextSibling;return 1===e.nodeType&&(f._scrollTop=e.scrollTop,f._scrollLeft=e.scrollLeft,"CANVAS"===e.nodeName?o(e,f):("TEXTAREA"===e.nodeName||"SELECT"===e.nodeName)&&(f.value=e.value)),f}function i(e){if(1===e.nodeType){e.scrollTop=e._scrollTop,e.scrollLeft=e._scrollLeft;for(var n=e.firstChild;n;)i(n),n=n.nextSibling}}var t=e("./log"),l=e("./promise");n.exports=function(e,n,o,t,s,u,a){var p=d(e.documentElement,s.javascriptEnabled),c=n.createElement("iframe");return c.className="html2canvas-container",c.style.visibility="hidden",c.style.position="fixed",c.style.left="-10000px",c.style.top="0px",c.style.border="0",c.width=o,c.height=t,c.scrolling="no",n.body.appendChild(c),new l(function(n){var o=c.contentWindow.document;c.contentWindow.onload=c.onload=function(){var e=setInterval(function(){o.body.childNodes.length>0&&(i(o.documentElement),clearInterval(e),"view"===s.type&&(c.contentWindow.scrollTo(u,a),!/(iPad|iPhone|iPod)/g.test(navigator.userAgent)||c.contentWindow.scrollY===a&&c.contentWindow.scrollX===u||(o.documentElement.style.top=-a+"px",o.documentElement.style.left=-u+"px",o.documentElement.style.position="absolute")),n(c))},50)},o.open(),o.write("<!DOCTYPE html><html></html>"),f(e,u,a),o.replaceChild(o.adoptNode(p),o.documentElement),o.close()})}},{"./log":15,"./promise":18}],5:[function(e,n){function f(e){this.r=0,this.g=0,this.b=0,this.a=null;this.fromArray(e)||this.namedColor(e)||this.rgb(e)||this.rgba(e)||this.hex6(e)||this.hex3(e)}f.prototype.darken=function(e){var n=1-e;return new f([Math.round(this.r*n),Math.round(this.g*n),Math.round(this.b*n),this.a])},f.prototype.isTransparent=function(){return 0===this.a},f.prototype.isBlack=function(){return 0===this.r&&0===this.g&&0===this.b},f.prototype.fromArray=function(e){return Array.isArray(e)&&(this.r=Math.min(e[0],255),this.g=Math.min(e[1],255),this.b=Math.min(e[2],255),e.length>3&&(this.a=e[3])),Array.isArray(e)};var o=/^#([a-f0-9]{3})$/i;f.prototype.hex3=function(e){var n=null;return null!==(n=e.match(o))&&(this.r=parseInt(n[1][0]+n[1][0],16),this.g=parseInt(n[1][1]+n[1][1],16),this.b=parseInt(n[1][2]+n[1][2],16)),null!==n};var d=/^#([a-f0-9]{6})$/i;f.prototype.hex6=function(e){var n=null;return null!==(n=e.match(d))&&(this.r=parseInt(n[1].substring(0,2),16),this.g=parseInt(n[1].substring(2,4),16),this.b=parseInt(n[1].substring(4,6),16)),null!==n};var i=/^rgb\((\d{1,3}) *, *(\d{1,3}) *, *(\d{1,3})\)$/;f.prototype.rgb=function(e){var n=null;return null!==(n=e.match(i))&&(this.r=Number(n[1]),this.g=Number(n[2]),this.b=Number(n[3])),null!==n};var t=/^rgba\((\d{1,3}) *, *(\d{1,3}) *, *(\d{1,3}) *, *(\d+\.?\d*)\)$/;f.prototype.rgba=function(e){var n=null;return null!==(n=e.match(t))&&(this.r=Number(n[1]),this.g=Number(n[2]),this.b=Number(n[3]),this.a=Number(n[4])),null!==n},f.prototype.toString=function(){return null!==this.a&&1!==this.a?"rgba("+[this.r,this.g,this.b,this.a].join(",")+")":"rgb("+[this.r,this.g,this.b].join(",")+")"},f.prototype.namedColor=function(e){var n=l[e.toLowerCase()];if(n)this.r=n[0],this.g=n[1],this.b=n[2];else if("transparent"===e.toLowerCase())return this.r=this.g=this.b=this.a=0,!0;return!!n},f.prototype.isColor=!0;var l={aliceblue:[240,248,255],antiquewhite:[250,235,215],aqua:[0,255,255],aquamarine:[127,255,212],azure:[240,255,255],beige:[245,245,220],bisque:[255,228,196],black:[0,0,0],blanchedalmond:[255,235,205],blue:[0,0,255],blueviolet:[138,43,226],brown:[165,42,42],burlywood:[222,184,135],cadetblue:[95,158,160],chartreuse:[127,255,0],chocolate:[210,105,30],coral:[255,127,80],cornflowerblue:[100,149,237],cornsilk:[255,248,220],crimson:[220,20,60],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgoldenrod:[184,134,11],darkgray:[169,169,169],darkgreen:[0,100,0],darkgrey:[169,169,169],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkseagreen:[143,188,143],darkslateblue:[72,61,139],darkslategray:[47,79,79],darkslategrey:[47,79,79],darkturquoise:[0,206,209],darkviolet:[148,0,211],deeppink:[255,20,147],deepskyblue:[0,191,255],dimgray:[105,105,105],dimgrey:[105,105,105],dodgerblue:[30,144,255],firebrick:[178,34,34],floralwhite:[255,250,240],forestgreen:[34,139,34],fuchsia:[255,0,255],gainsboro:[220,220,220],ghostwhite:[248,248,255],gold:[255,215,0],goldenrod:[218,165,32],gray:[128,128,128],green:[0,128,0],greenyellow:[173,255,47],grey:[128,128,128],honeydew:[240,255,240],hotpink:[255,105,180],indianred:[205,92,92],indigo:[75,0,130],ivory:[255,255,240],khaki:[240,230,140],lavender:[230,230,250],lavenderblush:[255,240,245],lawngreen:[124,252,0],lemonchiffon:[255,250,205],lightblue:[173,216,230],lightcoral:[240,128,128],lightcyan:[224,255,255],lightgoldenrodyellow:[250,250,210],lightgray:[211,211,211],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightsalmon:[255,160,122],lightseagreen:[32,178,170],lightskyblue:[135,206,250],lightslategray:[119,136,153],lightslategrey:[119,136,153],lightsteelblue:[176,196,222],lightyellow:[255,255,224],lime:[0,255,0],limegreen:[50,205,50],linen:[250,240,230],magenta:[255,0,255],maroon:[128,0,0],mediumaquamarine:[102,205,170],mediumblue:[0,0,205],mediumorchid:[186,85,211],mediumpurple:[147,112,219],mediumseagreen:[60,179,113],mediumslateblue:[123,104,238],mediumspringgreen:[0,250,154],mediumturquoise:[72,209,204],mediumvioletred:[199,21,133],midnightblue:[25,25,112],mintcream:[245,255,250],mistyrose:[255,228,225],moccasin:[255,228,181],navajowhite:[255,222,173],navy:[0,0,128],oldlace:[253,245,230],olive:[128,128,0],olivedrab:[107,142,35],orange:[255,165,0],orangered:[255,69,0],orchid:[218,112,214],palegoldenrod:[238,232,170],palegreen:[152,251,152],paleturquoise:[175,238,238],palevioletred:[219,112,147],papayawhip:[255,239,213],peachpuff:[255,218,185],peru:[205,133,63],pink:[255,192,203],plum:[221,160,221],powderblue:[176,224,230],purple:[128,0,128],rebeccapurple:[102,51,153],red:[255,0,0],rosybrown:[188,143,143],royalblue:[65,105,225],saddlebrown:[139,69,19],salmon:[250,128,114],sandybrown:[244,164,96],seagreen:[46,139,87],seashell:[255,245,238],sienna:[160,82,45],silver:[192,192,192],skyblue:[135,206,235],slateblue:[106,90,205],slategray:[112,128,144],slategrey:[112,128,144],snow:[255,250,250],springgreen:[0,255,127],steelblue:[70,130,180],tan:[210,180,140],teal:[0,128,128],thistle:[216,191,216],tomato:[255,99,71],turquoise:[64,224,208],violet:[238,130,238],wheat:[245,222,179],white:[255,255,255],whitesmoke:[245,245,245],yellow:[255,255,0],yellowgreen:[154,205,50]};n.exports=f},{}],6:[function(e,n){function f(e,n){var f=j++;if(n=n||{},n.logging&&(window.html2canvas.logging=!0,window.html2canvas.start=Date.now()),n.async="undefined"==typeof n.async?!0:n.async,n.allowTaint="undefined"==typeof n.allowTaint?!1:n.allowTaint,n.removeContainer="undefined"==typeof n.removeContainer?!0:n.removeContainer,n.javascriptEnabled="undefined"==typeof n.javascriptEnabled?!1:n.javascriptEnabled,n.imageTimeout="undefined"==typeof n.imageTimeout?1e4:n.imageTimeout,n.renderer="function"==typeof n.renderer?n.renderer:c,n.strict=!!n.strict,"string"==typeof e){if("string"!=typeof n.proxy)return a.reject("Proxy must be used when rendering url");var i=null!=n.width?n.width:window.innerWidth,t=null!=n.height?n.height:window.innerHeight;return g(u(e),n.proxy,document,i,t,n).then(function(e){return d(e.contentWindow.document.documentElement,e,n,i,t)})}var l=(void 0===e?[document.documentElement]:e.length?e:[e])[0];return l.setAttribute(x+f,f),o(l.ownerDocument,n,l.ownerDocument.defaultView.innerWidth,l.ownerDocument.defaultView.innerHeight,f).then(function(e){return"function"==typeof n.onrendered&&(v("options.onrendered is deprecated, html2canvas returns a Promise containing the canvas"),n.onrendered(e)),e})}function o(e,n,f,o,i){return b(e,e,f,o,n,e.defaultView.pageXOffset,e.defaultView.pageYOffset).then(function(t){v("Document cloned");var l=x+i,s="["+l+"='"+i+"']";e.querySelector(s).removeAttribute(l);var u=t.contentWindow,p=u.document.querySelector(s),c=a.resolve("function"==typeof n.onclone?n.onclone(u.document):!0);return c.then(function(){return d(p,t,n,f,o)})})}function d(e,n,f,o,d){var u=n.contentWindow,a=new p(u.document),c=new y(f,a),r=h(e),w="view"===f.type?o:l(u.document),b="view"===f.type?d:s(u.document),g=new f.renderer(w,b,c,f,document),x=new m(e,g,a,c,f);return x.ready.then(function(){v("Finished rendering");var o;return o="view"===f.type?t(g.canvas,{width:g.canvas.width,height:g.canvas.height,top:0,left:0,x:0,y:0}):e===u.document.body||e===u.document.documentElement||null!=f.canvas?g.canvas:t(g.canvas,{width:null!=f.width?f.width:r.width,height:null!=f.height?f.height:r.height,top:r.top,left:r.left,x:u.pageXOffset,y:u.pageYOffset}),i(n,f),o})}function i(e,n){n.removeContainer&&(e.parentNode.removeChild(e),v("Cleaned up container"))}function t(e,n){var f=document.createElement("canvas"),o=Math.min(e.width-1,Math.max(0,n.left)),d=Math.min(e.width,Math.max(1,n.left+n.width)),i=Math.min(e.height-1,Math.max(0,n.top)),t=Math.min(e.height,Math.max(1,n.top+n.height));return f.width=n.width,f.height=n.height,v("Cropping canvas at:","left:",n.left,"top:",n.top,"width:",d-o,"height:",t-i),v("Resulting crop with width",n.width,"and height",n.height," with x",o,"and y",i),f.getContext("2d").drawImage(e,o,i,d-o,t-i,n.x,n.y,d-o,t-i),f}function l(e){return Math.max(Math.max(e.body.scrollWidth,e.documentElement.scrollWidth),Math.max(e.body.offsetWidth,e.documentElement.offsetWidth),Math.max(e.body.clientWidth,e.documentElement.clientWidth))}function s(e){return Math.max(Math.max(e.body.scrollHeight,e.documentElement.scrollHeight),Math.max(e.body.offsetHeight,e.documentElement.offsetHeight),Math.max(e.body.clientHeight,e.documentElement.clientHeight))}function u(e){var n=document.createElement("a");return n.href=e,n.href=n.href,n}var a=e("./promise"),p=e("./support"),c=e("./renderers/canvas"),y=e("./imageloader"),m=e("./nodeparser"),r=e("./nodecontainer"),v=e("./log"),w=e("./utils"),b=e("./clone"),g=e("./proxy").loadUrlDocument,h=w.getBounds,x="data-html2canvas-node",j=0;f.Promise=a,f.CanvasRenderer=c,f.NodeContainer=r,f.log=v,f.utils=w,n.exports="undefined"==typeof document||"function"!=typeof Object.create||"function"!=typeof document.createElement("canvas").getContext?function(){return a.reject("No canvas support")}:f},{"./clone":4,"./imageloader":13,"./log":15,"./nodecontainer":16,"./nodeparser":17,"./promise":18,"./proxy":19,"./renderers/canvas":23,"./support":25,"./utils":29}],7:[function(e,n){function f(e){if(this.src=e,d("DummyImageContainer for",e),!this.promise||!this.image){d("Initiating DummyImageContainer"),f.prototype.image=new Image;var n=this.image;f.prototype.promise=new o(function(e,f){n.onload=e,n.onerror=f,n.src=i(),n.complete===!0&&e(n)})}}var o=e("./promise"),d=e("./log"),i=e("./utils").smallImage;n.exports=f},{"./log":15,"./promise":18,"./utils":29}],8:[function(e,n){function f(e,n){var f,d,i=document.createElement("div"),t=document.createElement("img"),l=document.createElement("span"),s="Hidden Text";i.style.visibility="hidden",i.style.fontFamily=e,i.style.fontSize=n,i.style.margin=0,i.style.padding=0,document.body.appendChild(i),t.src=o(),t.width=1,t.height=1,t.style.margin=0,t.style.padding=0,t.style.verticalAlign="baseline",l.style.fontFamily=e,l.style.fontSize=n,l.style.margin=0,l.style.padding=0,l.appendChild(document.createTextNode(s)),i.appendChild(l),i.appendChild(t),f=t.offsetTop-l.offsetTop+1,i.removeChild(l),i.appendChild(document.createTextNode(s)),i.style.lineHeight="normal",t.style.verticalAlign="super",d=t.offsetTop-i.offsetTop+1,document.body.removeChild(i),this.baseline=f,this.lineWidth=1,this.middle=d}var o=e("./utils").smallImage;n.exports=f},{"./utils":29}],9:[function(e,n){function f(){this.data={}}var o=e("./font");f.prototype.getMetrics=function(e,n){return void 0===this.data[e+"-"+n]&&(this.data[e+"-"+n]=new o(e,n)),this.data[e+"-"+n]},n.exports=f},{"./font":8}],10:[function(e,n){function f(n,f,o){this.image=null,this.src=n;var t=this,l=i(n);this.promise=(f?new d(function(e){"about:blank"===n.contentWindow.document.URL||null==n.contentWindow.document.documentElement?n.contentWindow.onload=n.onload=function(){e(n)}:e(n)}):this.proxyLoad(o.proxy,l,o)).then(function(n){var f=e("./core");return f(n.contentWindow.document.documentElement,{type:"view",width:n.width,height:n.height,proxy:o.proxy,javascriptEnabled:o.javascriptEnabled,removeContainer:o.removeContainer,allowTaint:o.allowTaint,imageTimeout:o.imageTimeout/2})}).then(function(e){return t.image=e})}var o=e("./utils"),d=e("./promise"),i=o.getBounds,t=e("./proxy").loadUrlDocument;f.prototype.proxyLoad=function(e,n,f){var o=this.src;return t(o.src,e,o.ownerDocument,n.width,n.height,f)},n.exports=f},{"./core":6,"./promise":18,"./proxy":19,"./utils":29}],11:[function(e,n){function f(e){this.src=e.value,this.colorStops=[],this.type=null,this.x0=.5,this.y0=.5,this.x1=.5,this.y1=.5,this.promise=o.resolve(!0)}var o=e("./promise");f.prototype.TYPES={LINEAR:1,RADIAL:2},n.exports=f},{"./promise":18}],12:[function(e,n){function f(e,n){this.src=e,this.image=new Image;var f=this;this.tainted=null,this.promise=new o(function(o,d){f.image.onload=o,f.image.onerror=d,n&&(f.image.crossOrigin="anonymous"),f.image.src=e,f.image.complete===!0&&o(f.image)})}var o=e("./promise");n.exports=f},{"./promise":18}],13:[function(e,n){function f(e,n){this.link=null,this.options=e,this.support=n,this.origin=this.getOrigin(window.location.href)}var o=e("./promise"),d=e("./log"),i=e("./imagecontainer"),t=e("./dummyimagecontainer"),l=e("./proxyimagecontainer"),s=e("./framecontainer"),u=e("./svgcontainer"),a=e("./svgnodecontainer"),p=e("./lineargradientcontainer"),c=e("./webkitgradientcontainer"),y=e("./utils").bind;f.prototype.findImages=function(e){var n=[];return e.reduce(function(e,n){switch(n.node.nodeName){case"IMG":return e.concat([{args:[n.node.src],method:"url"}]);case"svg":case"IFRAME":return e.concat([{args:[n.node],method:n.node.nodeName}])}return e},[]).forEach(this.addImage(n,this.loadImage),this),n},f.prototype.findBackgroundImage=function(e,n){return n.parseBackgroundImages().filter(this.hasImageBackground).forEach(this.addImage(e,this.loadImage),this),e},f.prototype.addImage=function(e,n){return function(f){f.args.forEach(function(o){this.imageExists(e,o)||(e.splice(0,0,n.call(this,f)),d("Added image #"+e.length,"string"==typeof o?o.substring(0,100):o))},this)}},f.prototype.hasImageBackground=function(e){return"none"!==e.method},f.prototype.loadImage=function(e){if("url"===e.method){var n=e.args[0];return!this.isSVG(n)||this.support.svg||this.options.allowTaint?n.match(/data:image\/.*;base64,/i)?new i(n.replace(/url\(['"]{0,}|['"]{0,}\)$/gi,""),!1):this.isSameOrigin(n)||this.options.allowTaint===!0||this.isSVG(n)?new i(n,!1):this.support.cors&&!this.options.allowTaint&&this.options.useCORS?new i(n,!0):this.options.proxy?new l(n,this.options.proxy):new t(n):new u(n)}return"linear-gradient"===e.method?new p(e):"gradient"===e.method?new c(e):"svg"===e.method?new a(e.args[0],this.support.svg):"IFRAME"===e.method?new s(e.args[0],this.isSameOrigin(e.args[0].src),this.options):new t(e)},f.prototype.isSVG=function(e){return"svg"===e.substring(e.length-3).toLowerCase()||u.prototype.isInline(e)},f.prototype.imageExists=function(e,n){return e.some(function(e){return e.src===n})},f.prototype.isSameOrigin=function(e){return this.getOrigin(e)===this.origin},f.prototype.getOrigin=function(e){var n=this.link||(this.link=document.createElement("a"));return n.href=e,n.href=n.href,n.protocol+n.hostname+n.port},f.prototype.getPromise=function(e){return this.timeout(e,this.options.imageTimeout)["catch"](function(){var n=new t(e.src);return n.promise.then(function(n){e.image=n})})},f.prototype.get=function(e){var n=null;return this.images.some(function(f){return(n=f).src===e})?n:null},f.prototype.fetch=function(e){return this.images=e.reduce(y(this.findBackgroundImage,this),this.findImages(e)),this.images.forEach(function(e,n){e.promise.then(function(){d("Succesfully loaded image #"+(n+1),e)},function(f){d("Failed loading image #"+(n+1),e,f)})}),this.ready=o.all(this.images.map(this.getPromise,this)),d("Finished searching images"),this},f.prototype.timeout=function(e,n){var f,i=o.race([e.promise,new o(function(o,i){f=setTimeout(function(){d("Timed out loading image",e),i(e)},n)})]).then(function(e){return clearTimeout(f),e});return i["catch"](function(){clearTimeout(f)}),i},n.exports=f},{"./dummyimagecontainer":7,"./framecontainer":10,"./imagecontainer":12,"./lineargradientcontainer":14,"./log":15,"./promise":18,"./proxyimagecontainer":20,"./svgcontainer":26,"./svgnodecontainer":27,"./utils":29,"./webkitgradientcontainer":30}],14:[function(e,n){function f(e){o.apply(this,arguments),this.type=this.TYPES.LINEAR;var n=null===e.args[0].match(this.stepRegExp);n?e.args[0].split(" ").reverse().forEach(function(e){switch(e){case"left":this.x0=0,this.x1=1;break;case"top":this.y0=0,this.y1=1;break;case"right":this.x0=1,this.x1=0;break;case"bottom":this.y0=1,this.y1=0;break;case"to":var n=this.y0,f=this.x0;this.y0=this.y1,this.x0=this.x1,this.x1=f,this.y1=n}},this):(this.y0=0,this.y1=1),this.colorStops=e.args.slice(n?1:0).map(function(e){var n=e.match(/((?:rgb|rgba)\(\d{1,3},\s\d{1,3},\s\d{1,3}(?:,\s[0-9\.]+)?\)|\w+)\s*(\d{1,3})?(%|px)?/);return{color:new d(n[1]),stop:"%"===n[3]?n[2]/100:null}},this),null===this.colorStops[0].stop&&(this.colorStops[0].stop=0),null===this.colorStops[this.colorStops.length-1].stop&&(this.colorStops[this.colorStops.length-1].stop=1),this.colorStops.forEach(function(e,n){null===e.stop&&this.colorStops.slice(n).some(function(f,o){return null!==f.stop?(e.stop=(f.stop-this.colorStops[n-1].stop)/(o+1)+this.colorStops[n-1].stop,!0):!1},this)},this)}var o=e("./gradientcontainer"),d=e("./color");f.prototype=Object.create(o.prototype),f.prototype.stepRegExp=/((?:rgb|rgba)\(\d{1,3},\s\d{1,3},\s\d{1,3}(?:,\s[0-9\.]+)?\))\s*(\d{1,3})?(%|px)?/,n.exports=f},{"./color":5,"./gradientcontainer":11}],15:[function(e,n){n.exports=function(){window.html2canvas.logging&&window.console&&window.console.log&&Function.prototype.bind.call(window.console.log,window.console).apply(window.console,[Date.now()-window.html2canvas.start+"ms","html2canvas:"].concat([].slice.call(arguments,0)))}},{}],16:[function(e,n){function f(e,n){this.node=e,this.parent=n,this.stack=null,this.bounds=null,this.borders=null,this.clip=[],this.backgroundClip=[],this.offsetBounds=null,this.visible=null,this.computedStyles=null,this.colors={},this.styles={},this.backgroundImages=null,this.transformData=null,this.transformMatrix=null,this.isPseudoElement=!1,this.opacity=null}function o(e){var n=e.options[e.selectedIndex||0];return n?n.text||"":""}function d(e){if(e&&"matrix"===e[1])return e[2].split(",").map(function(e){return parseFloat(e.trim())});if(e&&"matrix3d"===e[1]){var n=e[2].split(",").map(function(e){return parseFloat(e.trim())});return[n[0],n[1],n[4],n[5],n[12],n[13]]}}function i(e){return-1!==e.toString().indexOf("%")}function t(e){return e.replace("px","")}function l(e){return parseFloat(e)}var s=e("./color"),u=e("./utils"),a=u.getBounds,p=u.parseBackgrounds,c=u.offsetBounds;f.prototype.cloneTo=function(e){e.visible=this.visible,e.borders=this.borders,e.bounds=this.bounds,e.clip=this.clip,e.backgroundClip=this.backgroundClip,e.computedStyles=this.computedStyles,e.styles=this.styles,e.backgroundImages=this.backgroundImages,e.opacity=this.opacity},f.prototype.getOpacity=function(){return null===this.opacity?this.opacity=this.cssFloat("opacity"):this.opacity},f.prototype.assignStack=function(e){this.stack=e,e.children.push(this)},f.prototype.isElementVisible=function(){return this.node.nodeType===Node.TEXT_NODE?this.parent.visible:"none"!==this.css("display")&&"hidden"!==this.css("visibility")&&!this.node.hasAttribute("data-html2canvas-ignore")&&("INPUT"!==this.node.nodeName||"hidden"!==this.node.getAttribute("type"))},f.prototype.css=function(e){return this.computedStyles||(this.computedStyles=this.isPseudoElement?this.parent.computedStyle(this.before?":before":":after"):this.computedStyle(null)),this.styles[e]||(this.styles[e]=this.computedStyles[e])},f.prototype.prefixedCss=function(e){var n=["webkit","moz","ms","o"],f=this.css(e);return void 0===f&&n.some(function(n){return f=this.css(n+e.substr(0,1).toUpperCase()+e.substr(1)),void 0!==f},this),void 0===f?null:f},f.prototype.computedStyle=function(e){return this.node.ownerDocument.defaultView.getComputedStyle(this.node,e)},f.prototype.cssInt=function(e){var n=parseInt(this.css(e),10);return isNaN(n)?0:n},f.prototype.color=function(e){return this.colors[e]||(this.colors[e]=new s(this.css(e)))},f.prototype.cssFloat=function(e){var n=parseFloat(this.css(e));return isNaN(n)?0:n},f.prototype.fontWeight=function(){var e=this.css("fontWeight");switch(parseInt(e,10)){case 401:e="bold";break;case 400:e="normal"}return e},f.prototype.parseClip=function(){var e=this.css("clip").match(this.CLIP);return e?{top:parseInt(e[1],10),right:parseInt(e[2],10),bottom:parseInt(e[3],10),left:parseInt(e[4],10)}:null},f.prototype.parseBackgroundImages=function(){return this.backgroundImages||(this.backgroundImages=p(this.css("backgroundImage"))) +},f.prototype.cssList=function(e,n){var f=(this.css(e)||"").split(",");return f=f[n||0]||f[0]||"auto",f=f.trim().split(" "),1===f.length&&(f=[f[0],i(f[0])?"auto":f[0]]),f},f.prototype.parseBackgroundSize=function(e,n,f){var o,d,t=this.cssList("backgroundSize",f);if(i(t[0]))o=e.width*parseFloat(t[0])/100;else{if(/contain|cover/.test(t[0])){var l=e.width/e.height,s=n.width/n.height;return s>l^"contain"===t[0]?{width:e.height*s,height:e.height}:{width:e.width,height:e.width/s}}o=parseInt(t[0],10)}return d="auto"===t[0]&&"auto"===t[1]?n.height:"auto"===t[1]?o/n.width*n.height:i(t[1])?e.height*parseFloat(t[1])/100:parseInt(t[1],10),"auto"===t[0]&&(o=d/n.height*n.width),{width:o,height:d}},f.prototype.parseBackgroundPosition=function(e,n,f,o){var d,t,l=this.cssList("backgroundPosition",f);return d=i(l[0])?(e.width-(o||n).width)*(parseFloat(l[0])/100):parseInt(l[0],10),t="auto"===l[1]?d/n.width*n.height:i(l[1])?(e.height-(o||n).height)*parseFloat(l[1])/100:parseInt(l[1],10),"auto"===l[0]&&(d=t/n.height*n.width),{left:d,top:t}},f.prototype.parseBackgroundRepeat=function(e){return this.cssList("backgroundRepeat",e)[0]},f.prototype.parseTextShadows=function(){var e=this.css("textShadow"),n=[];if(e&&"none"!==e)for(var f=e.match(this.TEXT_SHADOW_PROPERTY),o=0;f&&o<f.length;o++){var d=f[o].match(this.TEXT_SHADOW_VALUES);n.push({color:new s(d[0]),offsetX:d[1]?parseFloat(d[1].replace("px","")):0,offsetY:d[2]?parseFloat(d[2].replace("px","")):0,blur:d[3]?d[3].replace("px",""):0})}return n},f.prototype.parseTransform=function(){if(!this.transformData)if(this.hasTransform()){var e=this.parseBounds(),n=this.prefixedCss("transformOrigin").split(" ").map(t).map(l);n[0]+=e.left,n[1]+=e.top,this.transformData={origin:n,matrix:this.parseTransformMatrix()}}else this.transformData={origin:[0,0],matrix:[1,0,0,1,0,0]};return this.transformData},f.prototype.parseTransformMatrix=function(){if(!this.transformMatrix){var e=this.prefixedCss("transform"),n=e?d(e.match(this.MATRIX_PROPERTY)):null;this.transformMatrix=n?n:[1,0,0,1,0,0]}return this.transformMatrix},f.prototype.parseBounds=function(){return this.bounds||(this.bounds=this.hasTransform()?c(this.node):a(this.node))},f.prototype.hasTransform=function(){return"1,0,0,1,0,0"!==this.parseTransformMatrix().join(",")||this.parent&&this.parent.hasTransform()},f.prototype.getValue=function(){var e=this.node.value||"";return"SELECT"===this.node.tagName?e=o(this.node):"password"===this.node.type&&(e=Array(e.length+1).join("•")),0===e.length?this.node.placeholder||"":e},f.prototype.MATRIX_PROPERTY=/(matrix|matrix3d)\((.+)\)/,f.prototype.TEXT_SHADOW_PROPERTY=/((rgba|rgb)\([^\)]+\)(\s-?\d+px){0,})/g,f.prototype.TEXT_SHADOW_VALUES=/(-?\d+px)|(#.+)|(rgb\(.+\))|(rgba\(.+\))/g,f.prototype.CLIP=/^rect\((\d+)px,? (\d+)px,? (\d+)px,? (\d+)px\)$/,n.exports=f},{"./color":5,"./utils":29}],17:[function(e,n){function f(e,n,f,o,d){N("Starting NodeParser"),this.renderer=n,this.options=d,this.range=null,this.support=f,this.renderQueue=[],this.stack=new V(!0,1,e.ownerDocument,null);var i=new P(e,null);if(d.background&&n.rectangle(0,0,n.width,n.height,new T(d.background)),e===e.ownerDocument.documentElement){var t=new P(i.color("backgroundColor").isTransparent()?e.ownerDocument.body:e.ownerDocument.documentElement,null);n.rectangle(0,0,n.width,n.height,t.color("backgroundColor"))}i.visibile=i.isElementVisible(),this.createPseudoHideStyles(e.ownerDocument),this.disableAnimations(e.ownerDocument),this.nodes=I([i].concat(this.getChildren(i)).filter(function(e){return e.visible=e.isElementVisible()}).map(this.getPseudoElements,this)),this.fontMetrics=new S,N("Fetched nodes, total:",this.nodes.length),N("Calculate overflow clips"),this.calculateOverflowClips(),N("Start fetching images"),this.images=o.fetch(this.nodes.filter(A)),this.ready=this.images.ready.then(X(function(){return N("Images loaded, starting parsing"),N("Creating stacking contexts"),this.createStackingContexts(),N("Sorting stacking contexts"),this.sortStackingContexts(this.stack),this.parse(this.stack),N("Render queue created with "+this.renderQueue.length+" items"),new U(X(function(e){d.async?"function"==typeof d.async?d.async.call(this,this.renderQueue,e):this.renderQueue.length>0?(this.renderIndex=0,this.asyncRenderer(this.renderQueue,e)):e():(this.renderQueue.forEach(this.paint,this),e())},this))},this))}function o(e){return e.parent&&e.parent.clip.length}function d(e){return e.replace(/(\-[a-z])/g,function(e){return e.toUpperCase().replace("-","")})}function i(){}function t(e,n,f,o){return e.map(function(d,i){if(d.width>0){var t=n.left,l=n.top,s=n.width,u=n.height-e[2].width;switch(i){case 0:u=e[0].width,d.args=a({c1:[t,l],c2:[t+s,l],c3:[t+s-e[1].width,l+u],c4:[t+e[3].width,l+u]},o[0],o[1],f.topLeftOuter,f.topLeftInner,f.topRightOuter,f.topRightInner);break;case 1:t=n.left+n.width-e[1].width,s=e[1].width,d.args=a({c1:[t+s,l],c2:[t+s,l+u+e[2].width],c3:[t,l+u],c4:[t,l+e[0].width]},o[1],o[2],f.topRightOuter,f.topRightInner,f.bottomRightOuter,f.bottomRightInner);break;case 2:l=l+n.height-e[2].width,u=e[2].width,d.args=a({c1:[t+s,l+u],c2:[t,l+u],c3:[t+e[3].width,l],c4:[t+s-e[3].width,l]},o[2],o[3],f.bottomRightOuter,f.bottomRightInner,f.bottomLeftOuter,f.bottomLeftInner);break;case 3:s=e[3].width,d.args=a({c1:[t,l+u+e[2].width],c2:[t,l],c3:[t+s,l+e[0].width],c4:[t+s,l+u]},o[3],o[0],f.bottomLeftOuter,f.bottomLeftInner,f.topLeftOuter,f.topLeftInner)}}return d})}function l(e,n,f,o){var d=4*((Math.sqrt(2)-1)/3),i=f*d,t=o*d,l=e+f,s=n+o;return{topLeft:u({x:e,y:s},{x:e,y:s-t},{x:l-i,y:n},{x:l,y:n}),topRight:u({x:e,y:n},{x:e+i,y:n},{x:l,y:s-t},{x:l,y:s}),bottomRight:u({x:l,y:n},{x:l,y:n+t},{x:e+i,y:s},{x:e,y:s}),bottomLeft:u({x:l,y:s},{x:l-i,y:s},{x:e,y:n+t},{x:e,y:n})}}function s(e,n,f){var o=e.left,d=e.top,i=e.width,t=e.height,s=n[0][0],u=n[0][1],a=n[1][0],p=n[1][1],c=n[2][0],y=n[2][1],m=n[3][0],r=n[3][1],v=i-a,w=t-y,b=i-c,g=t-r;return{topLeftOuter:l(o,d,s,u).topLeft.subdivide(.5),topLeftInner:l(o+f[3].width,d+f[0].width,Math.max(0,s-f[3].width),Math.max(0,u-f[0].width)).topLeft.subdivide(.5),topRightOuter:l(o+v,d,a,p).topRight.subdivide(.5),topRightInner:l(o+Math.min(v,i+f[3].width),d+f[0].width,v>i+f[3].width?0:a-f[3].width,p-f[0].width).topRight.subdivide(.5),bottomRightOuter:l(o+b,d+w,c,y).bottomRight.subdivide(.5),bottomRightInner:l(o+Math.min(b,i-f[3].width),d+Math.min(w,t+f[0].width),Math.max(0,c-f[1].width),y-f[2].width).bottomRight.subdivide(.5),bottomLeftOuter:l(o,d+g,m,r).bottomLeft.subdivide(.5),bottomLeftInner:l(o+f[3].width,d+g,Math.max(0,m-f[3].width),r-f[2].width).bottomLeft.subdivide(.5)}}function u(e,n,f,o){var d=function(e,n,f){return{x:e.x+(n.x-e.x)*f,y:e.y+(n.y-e.y)*f}};return{start:e,startControl:n,endControl:f,end:o,subdivide:function(i){var t=d(e,n,i),l=d(n,f,i),s=d(f,o,i),a=d(t,l,i),p=d(l,s,i),c=d(a,p,i);return[u(e,t,a,c),u(c,p,s,o)]},curveTo:function(e){e.push(["bezierCurve",n.x,n.y,f.x,f.y,o.x,o.y])},curveToReversed:function(o){o.push(["bezierCurve",f.x,f.y,n.x,n.y,e.x,e.y])}}}function a(e,n,f,o,d,i,t){var l=[];return n[0]>0||n[1]>0?(l.push(["line",o[1].start.x,o[1].start.y]),o[1].curveTo(l)):l.push(["line",e.c1[0],e.c1[1]]),f[0]>0||f[1]>0?(l.push(["line",i[0].start.x,i[0].start.y]),i[0].curveTo(l),l.push(["line",t[0].end.x,t[0].end.y]),t[0].curveToReversed(l)):(l.push(["line",e.c2[0],e.c2[1]]),l.push(["line",e.c3[0],e.c3[1]])),n[0]>0||n[1]>0?(l.push(["line",d[1].end.x,d[1].end.y]),d[1].curveToReversed(l)):l.push(["line",e.c4[0],e.c4[1]]),l}function p(e,n,f,o,d,i,t){n[0]>0||n[1]>0?(e.push(["line",o[0].start.x,o[0].start.y]),o[0].curveTo(e),o[1].curveTo(e)):e.push(["line",i,t]),(f[0]>0||f[1]>0)&&e.push(["line",d[0].start.x,d[0].start.y])}function c(e){return e.cssInt("zIndex")<0}function y(e){return e.cssInt("zIndex")>0}function m(e){return 0===e.cssInt("zIndex")}function r(e){return-1!==["inline","inline-block","inline-table"].indexOf(e.css("display"))}function v(e){return e instanceof V}function w(e){return e.node.data.trim().length>0}function b(e){return/^(normal|none|0px)$/.test(e.parent.css("letterSpacing"))}function g(e){return["TopLeft","TopRight","BottomRight","BottomLeft"].map(function(n){var f=e.css("border"+n+"Radius"),o=f.split(" ");return o.length<=1&&(o[1]=o[0]),o.map(F)})}function h(e){return e.nodeType===Node.TEXT_NODE||e.nodeType===Node.ELEMENT_NODE}function x(e){var n=e.css("position"),f=-1!==["absolute","relative","fixed"].indexOf(n)?e.css("zIndex"):"auto";return"auto"!==f}function j(e){return"static"!==e.css("position")}function k(e){return"none"!==e.css("float")}function q(e){return-1!==["inline-block","inline-table"].indexOf(e.css("display"))}function z(e){var n=this;return function(){return!e.apply(n,arguments)}}function A(e){return e.node.nodeType===Node.ELEMENT_NODE}function B(e){return e.isPseudoElement===!0}function C(e){return e.node.nodeType===Node.TEXT_NODE}function D(e){return function(n,f){return n.cssInt("zIndex")+e.indexOf(n)/e.length-(f.cssInt("zIndex")+e.indexOf(f)/e.length)}}function E(e){return e.getOpacity()<1}function F(e){return parseInt(e,10)}function G(e){return e.width}function H(e){return e.node.nodeType!==Node.ELEMENT_NODE||-1===["SCRIPT","HEAD","TITLE","OBJECT","BR","OPTION"].indexOf(e.node.nodeName)}function I(e){return[].concat.apply([],e)}function J(e){var n=e.substr(0,1);return n===e.substr(e.length-1)&&n.match(/'|"/)?e.substr(1,e.length-2):e}function K(e){for(var n,f=[],o=0,d=!1;e.length;)L(e[o])===d?(n=e.splice(0,o),n.length&&f.push(O.ucs2.encode(n)),d=!d,o=0):o++,o>=e.length&&(n=e.splice(0,o),n.length&&f.push(O.ucs2.encode(n)));return f}function L(e){return-1!==[32,13,10,9,45].indexOf(e)}function M(e){return/[^\u0000-\u00ff]/.test(e)}var N=e("./log"),O=e("punycode"),P=e("./nodecontainer"),Q=e("./textcontainer"),R=e("./pseudoelementcontainer"),S=e("./fontmetrics"),T=e("./color"),U=e("./promise"),V=e("./stackingcontext"),W=e("./utils"),X=W.bind,Y=W.getBounds,Z=W.parseBackgrounds,$=W.offsetBounds;f.prototype.calculateOverflowClips=function(){this.nodes.forEach(function(e){if(A(e)){B(e)&&e.appendToDOM(),e.borders=this.parseBorders(e);var n="hidden"===e.css("overflow")?[e.borders.clip]:[],f=e.parseClip();f&&-1!==["absolute","fixed"].indexOf(e.css("position"))&&n.push([["rect",e.bounds.left+f.left,e.bounds.top+f.top,f.right-f.left,f.bottom-f.top]]),e.clip=o(e)?e.parent.clip.concat(n):n,e.backgroundClip="hidden"!==e.css("overflow")?e.clip.concat([e.borders.clip]):e.clip,B(e)&&e.cleanDOM()}else C(e)&&(e.clip=o(e)?e.parent.clip:[]);B(e)||(e.bounds=null)},this)},f.prototype.asyncRenderer=function(e,n,f){f=f||Date.now(),this.paint(e[this.renderIndex++]),e.length===this.renderIndex?n():f+20>Date.now()?this.asyncRenderer(e,n,f):setTimeout(X(function(){this.asyncRenderer(e,n)},this),0)},f.prototype.createPseudoHideStyles=function(e){this.createStyles(e,"."+R.prototype.PSEUDO_HIDE_ELEMENT_CLASS_BEFORE+':before { content: "" !important; display: none !important; }.'+R.prototype.PSEUDO_HIDE_ELEMENT_CLASS_AFTER+':after { content: "" !important; display: none !important; }')},f.prototype.disableAnimations=function(e){this.createStyles(e,"* { -webkit-animation: none !important; -moz-animation: none !important; -o-animation: none !important; animation: none !important; -webkit-transition: none !important; -moz-transition: none !important; -o-transition: none !important; transition: none !important;}")},f.prototype.createStyles=function(e,n){var f=e.createElement("style");f.innerHTML=n,e.body.appendChild(f)},f.prototype.getPseudoElements=function(e){var n=[[e]];if(e.node.nodeType===Node.ELEMENT_NODE){var f=this.getPseudoElement(e,":before"),o=this.getPseudoElement(e,":after");f&&n.push(f),o&&n.push(o)}return I(n)},f.prototype.getPseudoElement=function(e,n){var f=e.computedStyle(n);if(!f||!f.content||"none"===f.content||"-moz-alt-content"===f.content||"none"===f.display)return null;for(var o=J(f.content),i="url"===o.substr(0,3),t=document.createElement(i?"img":"html2canvaspseudoelement"),l=new R(t,e,n),s=f.length-1;s>=0;s--){var u=d(f.item(s));t.style[u]=f[u]}if(t.className=R.prototype.PSEUDO_HIDE_ELEMENT_CLASS_BEFORE+" "+R.prototype.PSEUDO_HIDE_ELEMENT_CLASS_AFTER,i)return t.src=Z(o)[0].args[0],[l];var a=document.createTextNode(o);return t.appendChild(a),[l,new Q(a,l)]},f.prototype.getChildren=function(e){return I([].filter.call(e.node.childNodes,h).map(function(n){var f=[n.nodeType===Node.TEXT_NODE?new Q(n,e):new P(n,e)].filter(H);return n.nodeType===Node.ELEMENT_NODE&&f.length&&"TEXTAREA"!==n.tagName?f[0].isElementVisible()?f.concat(this.getChildren(f[0])):[]:f},this))},f.prototype.newStackingContext=function(e,n){var f=new V(n,e.getOpacity(),e.node,e.parent);e.cloneTo(f);var o=n?f.getParentStack(this):f.parent.stack;o.contexts.push(f),e.stack=f},f.prototype.createStackingContexts=function(){this.nodes.forEach(function(e){A(e)&&(this.isRootElement(e)||E(e)||x(e)||this.isBodyWithTransparentRoot(e)||e.hasTransform())?this.newStackingContext(e,!0):A(e)&&(j(e)&&m(e)||q(e)||k(e))?this.newStackingContext(e,!1):e.assignStack(e.parent.stack)},this)},f.prototype.isBodyWithTransparentRoot=function(e){return"BODY"===e.node.nodeName&&e.parent.color("backgroundColor").isTransparent()},f.prototype.isRootElement=function(e){return null===e.parent},f.prototype.sortStackingContexts=function(e){e.contexts.sort(D(e.contexts.slice(0))),e.contexts.forEach(this.sortStackingContexts,this)},f.prototype.parseTextBounds=function(e){return function(n,f,o){if("none"!==e.parent.css("textDecoration").substr(0,4)||0!==n.trim().length){if(this.support.rangeBounds&&!e.parent.hasTransform()){var d=o.slice(0,f).join("").length;return this.getRangeBounds(e.node,d,n.length)}if(e.node&&"string"==typeof e.node.data){var i=e.node.splitText(n.length),t=this.getWrapperBounds(e.node,e.parent.hasTransform());return e.node=i,t}}else(!this.support.rangeBounds||e.parent.hasTransform())&&(e.node=e.node.splitText(n.length));return{}}},f.prototype.getWrapperBounds=function(e,n){var f=e.ownerDocument.createElement("html2canvaswrapper"),o=e.parentNode,d=e.cloneNode(!0);f.appendChild(e.cloneNode(!0)),o.replaceChild(f,e);var i=n?$(f):Y(f);return o.replaceChild(d,f),i},f.prototype.getRangeBounds=function(e,n,f){var o=this.range||(this.range=e.ownerDocument.createRange());return o.setStart(e,n),o.setEnd(e,n+f),o.getBoundingClientRect()},f.prototype.parse=function(e){var n=e.contexts.filter(c),f=e.children.filter(A),o=f.filter(z(k)),d=o.filter(z(j)).filter(z(r)),t=f.filter(z(j)).filter(k),l=o.filter(z(j)).filter(r),s=e.contexts.concat(o.filter(j)).filter(m),u=e.children.filter(C).filter(w),a=e.contexts.filter(y);n.concat(d).concat(t).concat(l).concat(s).concat(u).concat(a).forEach(function(e){this.renderQueue.push(e),v(e)&&(this.parse(e),this.renderQueue.push(new i))},this)},f.prototype.paint=function(e){try{e instanceof i?this.renderer.ctx.restore():C(e)?(B(e.parent)&&e.parent.appendToDOM(),this.paintText(e),B(e.parent)&&e.parent.cleanDOM()):this.paintNode(e)}catch(n){if(N(n),this.options.strict)throw n}},f.prototype.paintNode=function(e){v(e)&&(this.renderer.setOpacity(e.opacity),this.renderer.ctx.save(),e.hasTransform()&&this.renderer.setTransform(e.parseTransform())),"INPUT"===e.node.nodeName&&"checkbox"===e.node.type?this.paintCheckbox(e):"INPUT"===e.node.nodeName&&"radio"===e.node.type?this.paintRadio(e):this.paintElement(e)},f.prototype.paintElement=function(e){var n=e.parseBounds();this.renderer.clip(e.backgroundClip,function(){this.renderer.renderBackground(e,n,e.borders.borders.map(G))},this),this.renderer.clip(e.clip,function(){this.renderer.renderBorders(e.borders.borders)},this),this.renderer.clip(e.backgroundClip,function(){switch(e.node.nodeName){case"svg":case"IFRAME":var f=this.images.get(e.node);f?this.renderer.renderImage(e,n,e.borders,f):N("Error loading <"+e.node.nodeName+">",e.node);break;case"IMG":var o=this.images.get(e.node.src);o?this.renderer.renderImage(e,n,e.borders,o):N("Error loading <img>",e.node.src);break;case"CANVAS":this.renderer.renderImage(e,n,e.borders,{image:e.node});break;case"SELECT":case"INPUT":case"TEXTAREA":this.paintFormValue(e)}},this)},f.prototype.paintCheckbox=function(e){var n=e.parseBounds(),f=Math.min(n.width,n.height),o={width:f-1,height:f-1,top:n.top,left:n.left},d=[3,3],i=[d,d,d,d],l=[1,1,1,1].map(function(e){return{color:new T("#A5A5A5"),width:e}}),u=s(o,i,l);this.renderer.clip(e.backgroundClip,function(){this.renderer.rectangle(o.left+1,o.top+1,o.width-2,o.height-2,new T("#DEDEDE")),this.renderer.renderBorders(t(l,o,u,i)),e.node.checked&&(this.renderer.font(new T("#424242"),"normal","normal","bold",f-3+"px","arial"),this.renderer.text("✔",o.left+f/6,o.top+f-1))},this)},f.prototype.paintRadio=function(e){var n=e.parseBounds(),f=Math.min(n.width,n.height)-2;this.renderer.clip(e.backgroundClip,function(){this.renderer.circleStroke(n.left+1,n.top+1,f,new T("#DEDEDE"),1,new T("#A5A5A5")),e.node.checked&&this.renderer.circle(Math.ceil(n.left+f/4)+1,Math.ceil(n.top+f/4)+1,Math.floor(f/2),new T("#424242"))},this)},f.prototype.paintFormValue=function(e){var n=e.getValue();if(n.length>0){var f=e.node.ownerDocument,o=f.createElement("html2canvaswrapper"),d=["lineHeight","textAlign","fontFamily","fontWeight","fontSize","color","paddingLeft","paddingTop","paddingRight","paddingBottom","width","height","borderLeftStyle","borderTopStyle","borderLeftWidth","borderTopWidth","boxSizing","whiteSpace","wordWrap"];d.forEach(function(n){try{o.style[n]=e.css(n)}catch(f){N("html2canvas: Parse: Exception caught in renderFormValue: "+f.message)}});var i=e.parseBounds();o.style.position="fixed",o.style.left=i.left+"px",o.style.top=i.top+"px",o.textContent=n,f.body.appendChild(o),this.paintText(new Q(o.firstChild,e)),f.body.removeChild(o)}},f.prototype.paintText=function(e){e.applyTextTransform();var n=O.ucs2.decode(e.node.data),f=this.options.letterRendering&&!b(e)||M(e.node.data)?n.map(function(e){return O.ucs2.encode([e])}):K(n),o=e.parent.fontWeight(),d=e.parent.css("fontSize"),i=e.parent.css("fontFamily"),t=e.parent.parseTextShadows();this.renderer.font(e.parent.color("color"),e.parent.css("fontStyle"),e.parent.css("fontVariant"),o,d,i),t.length?this.renderer.fontShadow(t[0].color,t[0].offsetX,t[0].offsetY,t[0].blur):this.renderer.clearShadow(),this.renderer.clip(e.parent.clip,function(){f.map(this.parseTextBounds(e),this).forEach(function(n,o){n&&(this.renderer.text(f[o],n.left,n.bottom),this.renderTextDecoration(e.parent,n,this.fontMetrics.getMetrics(i,d)))},this)},this)},f.prototype.renderTextDecoration=function(e,n,f){switch(e.css("textDecoration").split(" ")[0]){case"underline":this.renderer.rectangle(n.left,Math.round(n.top+f.baseline+f.lineWidth),n.width,1,e.color("color"));break;case"overline":this.renderer.rectangle(n.left,Math.round(n.top),n.width,1,e.color("color"));break;case"line-through":this.renderer.rectangle(n.left,Math.ceil(n.top+f.middle+f.lineWidth),n.width,1,e.color("color"))}};var _={inset:[["darken",.6],["darken",.1],["darken",.1],["darken",.6]]};f.prototype.parseBorders=function(e){var n=e.parseBounds(),f=g(e),o=["Top","Right","Bottom","Left"].map(function(n,f){var o=e.css("border"+n+"Style"),d=e.color("border"+n+"Color");"inset"===o&&d.isBlack()&&(d=new T([255,255,255,d.a]));var i=_[o]?_[o][f]:null;return{width:e.cssInt("border"+n+"Width"),color:i?d[i[0]](i[1]):d,args:null}}),d=s(n,f,o);return{clip:this.parseBackgroundClip(e,d,o,f,n),borders:t(o,n,d,f)}},f.prototype.parseBackgroundClip=function(e,n,f,o,d){var i=e.css("backgroundClip"),t=[];switch(i){case"content-box":case"padding-box":p(t,o[0],o[1],n.topLeftInner,n.topRightInner,d.left+f[3].width,d.top+f[0].width),p(t,o[1],o[2],n.topRightInner,n.bottomRightInner,d.left+d.width-f[1].width,d.top+f[0].width),p(t,o[2],o[3],n.bottomRightInner,n.bottomLeftInner,d.left+d.width-f[1].width,d.top+d.height-f[2].width),p(t,o[3],o[0],n.bottomLeftInner,n.topLeftInner,d.left+f[3].width,d.top+d.height-f[2].width);break;default:p(t,o[0],o[1],n.topLeftOuter,n.topRightOuter,d.left,d.top),p(t,o[1],o[2],n.topRightOuter,n.bottomRightOuter,d.left+d.width,d.top),p(t,o[2],o[3],n.bottomRightOuter,n.bottomLeftOuter,d.left+d.width,d.top+d.height),p(t,o[3],o[0],n.bottomLeftOuter,n.topLeftOuter,d.left,d.top+d.height)}return t},n.exports=f},{"./color":5,"./fontmetrics":9,"./log":15,"./nodecontainer":16,"./promise":18,"./pseudoelementcontainer":21,"./stackingcontext":24,"./textcontainer":28,"./utils":29,punycode:3}],18:[function(e,n){n.exports=e("es6-promise").Promise},{"es6-promise":1}],19:[function(e,n,f){function o(e,n,f){var o="withCredentials"in new XMLHttpRequest;if(!n)return a.reject("No proxy configured");var d=t(o),s=l(n,e,d);return o?p(s):i(f,s,d).then(function(e){return r(e.content)})}function d(e,n,f){var o="crossOrigin"in new Image,d=t(o),s=l(n,e,d);return o?a.resolve(s):i(f,s,d).then(function(e){return"data:"+e.type+";base64,"+e.content})}function i(e,n,f){return new a(function(o,d){var i=e.createElement("script"),t=function(){delete window.html2canvas.proxy[f],e.body.removeChild(i)};window.html2canvas.proxy[f]=function(e){t(),o(e)},i.src=n,i.onerror=function(e){t(),d(e)},e.body.appendChild(i)})}function t(e){return e?"":"html2canvas_"+Date.now()+"_"+ ++v+"_"+Math.round(1e5*Math.random())}function l(e,n,f){return e+"?url="+encodeURIComponent(n)+(f.length?"&callback=html2canvas.proxy."+f:"")}function s(e){return function(n){var f,o=new DOMParser;try{f=o.parseFromString(n,"text/html")}catch(d){y("DOMParser not supported, falling back to createHTMLDocument"),f=document.implementation.createHTMLDocument("");try{f.open(),f.write(n),f.close()}catch(i){y("createHTMLDocument write not supported, falling back to document.body.innerHTML"),f.body.innerHTML=n}}var t=f.querySelector("base");if(!t||!t.href.host){var l=f.createElement("base");l.href=e,f.head.insertBefore(l,f.head.firstChild)}return f}}function u(e,n,f,d,i,t){return new o(e,n,window.document).then(s(e)).then(function(e){return m(e,f,d,i,t,0,0)})}var a=e("./promise"),p=e("./xhr"),c=e("./utils"),y=e("./log"),m=e("./clone"),r=c.decode64,v=0;f.Proxy=o,f.ProxyURL=d,f.loadUrlDocument=u},{"./clone":4,"./log":15,"./promise":18,"./utils":29,"./xhr":31}],20:[function(e,n){function f(e,n){var f=document.createElement("a");f.href=e,e=f.href,this.src=e,this.image=new Image;var i=this;this.promise=new d(function(f,d){i.image.crossOrigin="Anonymous",i.image.onload=f,i.image.onerror=d,new o(e,n,document).then(function(e){i.image.src=e})["catch"](d)})}var o=e("./proxy").ProxyURL,d=e("./promise");n.exports=f},{"./promise":18,"./proxy":19}],21:[function(e,n){function f(e,n,f){o.call(this,e,n),this.isPseudoElement=!0,this.before=":before"===f}var o=e("./nodecontainer");f.prototype.cloneTo=function(e){f.prototype.cloneTo.call(this,e),e.isPseudoElement=!0,e.before=this.before},f.prototype=Object.create(o.prototype),f.prototype.appendToDOM=function(){this.before?this.parent.node.insertBefore(this.node,this.parent.node.firstChild):this.parent.node.appendChild(this.node),this.parent.node.className+=" "+this.getHideClass()},f.prototype.cleanDOM=function(){this.node.parentNode.removeChild(this.node),this.parent.node.className=this.parent.node.className.replace(this.getHideClass(),"")},f.prototype.getHideClass=function(){return this["PSEUDO_HIDE_ELEMENT_CLASS_"+(this.before?"BEFORE":"AFTER")]},f.prototype.PSEUDO_HIDE_ELEMENT_CLASS_BEFORE="___html2canvas___pseudoelement_before",f.prototype.PSEUDO_HIDE_ELEMENT_CLASS_AFTER="___html2canvas___pseudoelement_after",n.exports=f},{"./nodecontainer":16}],22:[function(e,n){function f(e,n,f,o,d){this.width=e,this.height=n,this.images=f,this.options=o,this.document=d}var o=e("./log");f.prototype.renderImage=function(e,n,f,o){var d=e.cssInt("paddingLeft"),i=e.cssInt("paddingTop"),t=e.cssInt("paddingRight"),l=e.cssInt("paddingBottom"),s=f.borders,u=n.width-(s[1].width+s[3].width+d+t),a=n.height-(s[0].width+s[2].width+i+l);this.drawImage(o,0,0,o.image.width||u,o.image.height||a,n.left+d+s[3].width,n.top+i+s[0].width,u,a)},f.prototype.renderBackground=function(e,n,f){n.height>0&&n.width>0&&(this.renderBackgroundColor(e,n),this.renderBackgroundImage(e,n,f))},f.prototype.renderBackgroundColor=function(e,n){var f=e.color("backgroundColor");f.isTransparent()||this.rectangle(n.left,n.top,n.width,n.height,f)},f.prototype.renderBorders=function(e){e.forEach(this.renderBorder,this)},f.prototype.renderBorder=function(e){e.color.isTransparent()||null===e.args||this.drawShape(e.args,e.color)},f.prototype.renderBackgroundImage=function(e,n,f){var d=e.parseBackgroundImages();d.reverse().forEach(function(d,i,t){switch(d.method){case"url":var l=this.images.get(d.args[0]);l?this.renderBackgroundRepeating(e,n,l,t.length-(i+1),f):o("Error loading background-image",d.args[0]);break;case"linear-gradient":case"gradient":var s=this.images.get(d.value);s?this.renderBackgroundGradient(s,n,f):o("Error loading background-image",d.args[0]);break;case"none":break;default:o("Unknown background-image type",d.args[0])}},this)},f.prototype.renderBackgroundRepeating=function(e,n,f,o,d){var i=e.parseBackgroundSize(n,f.image,o),t=e.parseBackgroundPosition(n,f.image,o,i),l=e.parseBackgroundRepeat(o);switch(l){case"repeat-x":case"repeat no-repeat":this.backgroundRepeatShape(f,t,i,n,n.left+d[3],n.top+t.top+d[0],99999,i.height,d);break;case"repeat-y":case"no-repeat repeat":this.backgroundRepeatShape(f,t,i,n,n.left+t.left+d[3],n.top+d[0],i.width,99999,d);break;case"no-repeat":this.backgroundRepeatShape(f,t,i,n,n.left+t.left+d[3],n.top+t.top+d[0],i.width,i.height,d);break;default:this.renderBackgroundRepeat(f,t,i,{top:n.top,left:n.left},d[3],d[0])}},n.exports=f},{"./log":15}],23:[function(e,n){function f(e,n){d.apply(this,arguments),this.canvas=this.options.canvas||this.document.createElement("canvas"),this.options.canvas||(this.canvas.width=e,this.canvas.height=n),this.ctx=this.canvas.getContext("2d"),this.taintCtx=this.document.createElement("canvas").getContext("2d"),this.ctx.textBaseline="bottom",this.variables={},t("Initialized CanvasRenderer with size",e,"x",n)}function o(e){return e.length>0}var d=e("../renderer"),i=e("../lineargradientcontainer"),t=e("../log");f.prototype=Object.create(d.prototype),f.prototype.setFillStyle=function(e){return this.ctx.fillStyle="object"==typeof e&&e.isColor?e.toString():e,this.ctx},f.prototype.rectangle=function(e,n,f,o,d){this.setFillStyle(d).fillRect(e,n,f,o)},f.prototype.circle=function(e,n,f,o){this.setFillStyle(o),this.ctx.beginPath(),this.ctx.arc(e+f/2,n+f/2,f/2,0,2*Math.PI,!0),this.ctx.closePath(),this.ctx.fill()},f.prototype.circleStroke=function(e,n,f,o,d,i){this.circle(e,n,f,o),this.ctx.strokeStyle=i.toString(),this.ctx.stroke()},f.prototype.drawShape=function(e,n){this.shape(e),this.setFillStyle(n).fill()},f.prototype.taints=function(e){if(null===e.tainted){this.taintCtx.drawImage(e.image,0,0);try{this.taintCtx.getImageData(0,0,1,1),e.tainted=!1}catch(n){this.taintCtx=document.createElement("canvas").getContext("2d"),e.tainted=!0}}return e.tainted},f.prototype.drawImage=function(e,n,f,o,d,i,t,l,s){(!this.taints(e)||this.options.allowTaint)&&this.ctx.drawImage(e.image,n,f,o,d,i,t,l,s)},f.prototype.clip=function(e,n,f){this.ctx.save(),e.filter(o).forEach(function(e){this.shape(e).clip()},this),n.call(f),this.ctx.restore()},f.prototype.shape=function(e){return this.ctx.beginPath(),e.forEach(function(e,n){"rect"===e[0]?this.ctx.rect.apply(this.ctx,e.slice(1)):this.ctx[0===n?"moveTo":e[0]+"To"].apply(this.ctx,e.slice(1))},this),this.ctx.closePath(),this.ctx},f.prototype.font=function(e,n,f,o,d,i){this.setFillStyle(e).font=[n,f,o,d,i].join(" ").split(",")[0]},f.prototype.fontShadow=function(e,n,f,o){this.setVariable("shadowColor",e.toString()).setVariable("shadowOffsetY",n).setVariable("shadowOffsetX",f).setVariable("shadowBlur",o)},f.prototype.clearShadow=function(){this.setVariable("shadowColor","rgba(0,0,0,0)")},f.prototype.setOpacity=function(e){this.ctx.globalAlpha=e},f.prototype.setTransform=function(e){this.ctx.translate(e.origin[0],e.origin[1]),this.ctx.transform.apply(this.ctx,e.matrix),this.ctx.translate(-e.origin[0],-e.origin[1])},f.prototype.setVariable=function(e,n){return this.variables[e]!==n&&(this.variables[e]=this.ctx[e]=n),this},f.prototype.text=function(e,n,f){this.ctx.fillText(e,n,f)},f.prototype.backgroundRepeatShape=function(e,n,f,o,d,i,t,l,s){var u=[["line",Math.round(d),Math.round(i)],["line",Math.round(d+t),Math.round(i)],["line",Math.round(d+t),Math.round(l+i)],["line",Math.round(d),Math.round(l+i)]];this.clip([u],function(){this.renderBackgroundRepeat(e,n,f,o,s[3],s[0])},this)},f.prototype.renderBackgroundRepeat=function(e,n,f,o,d,i){var t=Math.round(o.left+n.left+d),l=Math.round(o.top+n.top+i);this.setFillStyle(this.ctx.createPattern(this.resizeImage(e,f),"repeat")),this.ctx.translate(t,l),this.ctx.fill(),this.ctx.translate(-t,-l)},f.prototype.renderBackgroundGradient=function(e,n){if(e instanceof i){var f=this.ctx.createLinearGradient(n.left+n.width*e.x0,n.top+n.height*e.y0,n.left+n.width*e.x1,n.top+n.height*e.y1);e.colorStops.forEach(function(e){f.addColorStop(e.stop,e.color.toString())}),this.rectangle(n.left,n.top,n.width,n.height,f)}},f.prototype.resizeImage=function(e,n){var f=e.image;if(f.width===n.width&&f.height===n.height)return f;var o,d=document.createElement("canvas");return d.width=n.width,d.height=n.height,o=d.getContext("2d"),o.drawImage(f,0,0,f.width,f.height,0,0,n.width,n.height),d},n.exports=f},{"../lineargradientcontainer":14,"../log":15,"../renderer":22}],24:[function(e,n){function f(e,n,f,d){o.call(this,f,d),this.ownStacking=e,this.contexts=[],this.children=[],this.opacity=(this.parent?this.parent.stack.opacity:1)*n}var o=e("./nodecontainer");f.prototype=Object.create(o.prototype),f.prototype.getParentStack=function(e){var n=this.parent?this.parent.stack:null;return n?n.ownStacking?n:n.getParentStack(e):e.stack},n.exports=f},{"./nodecontainer":16}],25:[function(e,n){function f(e){this.rangeBounds=this.testRangeBounds(e),this.cors=this.testCORS(),this.svg=this.testSVG()}f.prototype.testRangeBounds=function(e){var n,f,o,d,i=!1;return e.createRange&&(n=e.createRange(),n.getBoundingClientRect&&(f=e.createElement("boundtest"),f.style.height="123px",f.style.display="block",e.body.appendChild(f),n.selectNode(f),o=n.getBoundingClientRect(),d=o.height,123===d&&(i=!0),e.body.removeChild(f))),i},f.prototype.testCORS=function(){return"undefined"!=typeof(new Image).crossOrigin},f.prototype.testSVG=function(){var e=new Image,n=document.createElement("canvas"),f=n.getContext("2d");e.src="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg'></svg>";try{f.drawImage(e,0,0),n.toDataURL()}catch(o){return!1}return!0},n.exports=f},{}],26:[function(e,n){function f(e){this.src=e,this.image=null;var n=this;this.promise=this.hasFabric().then(function(){return n.isInline(e)?o.resolve(n.inlineFormatting(e)):d(e)}).then(function(e){return new o(function(f){window.html2canvas.svg.fabric.loadSVGFromString(e,n.createCanvas.call(n,f))})})}var o=e("./promise"),d=e("./xhr"),i=e("./utils").decode64;f.prototype.hasFabric=function(){return window.html2canvas.svg&&window.html2canvas.svg.fabric?o.resolve():o.reject(new Error("html2canvas.svg.js is not loaded, cannot render svg"))},f.prototype.inlineFormatting=function(e){return/^data:image\/svg\+xml;base64,/.test(e)?this.decode64(this.removeContentType(e)):this.removeContentType(e)},f.prototype.removeContentType=function(e){return e.replace(/^data:image\/svg\+xml(;base64)?,/,"")},f.prototype.isInline=function(e){return/^data:image\/svg\+xml/i.test(e)},f.prototype.createCanvas=function(e){var n=this;return function(f,o){var d=new window.html2canvas.svg.fabric.StaticCanvas("c");n.image=d.lowerCanvasEl,d.setWidth(o.width).setHeight(o.height).add(window.html2canvas.svg.fabric.util.groupSVGElements(f,o)).renderAll(),e(d.lowerCanvasEl)}},f.prototype.decode64=function(e){return"function"==typeof window.atob?window.atob(e):i(e)},n.exports=f},{"./promise":18,"./utils":29,"./xhr":31}],27:[function(e,n){function f(e,n){this.src=e,this.image=null;var f=this;this.promise=n?new d(function(n,o){f.image=new Image,f.image.onload=n,f.image.onerror=o,f.image.src="data:image/svg+xml,"+(new XMLSerializer).serializeToString(e),f.image.complete===!0&&n(f.image) +}):this.hasFabric().then(function(){return new d(function(n){window.html2canvas.svg.fabric.parseSVGDocument(e,f.createCanvas.call(f,n))})})}var o=e("./svgcontainer"),d=e("./promise");f.prototype=Object.create(o.prototype),n.exports=f},{"./promise":18,"./svgcontainer":26}],28:[function(e,n){function f(e,n){d.call(this,e,n)}function o(e,n,f){return e.length>0?n+f.toUpperCase():void 0}var d=e("./nodecontainer");f.prototype=Object.create(d.prototype),f.prototype.applyTextTransform=function(){this.node.data=this.transform(this.parent.css("textTransform"))},f.prototype.transform=function(e){var n=this.node.data;switch(e){case"lowercase":return n.toLowerCase();case"capitalize":return n.replace(/(^|\s|:|-|\(|\))([a-z])/g,o);case"uppercase":return n.toUpperCase();default:return n}},n.exports=f},{"./nodecontainer":16}],29:[function(e,n,f){f.smallImage=function(){return"data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7"},f.bind=function(e,n){return function(){return e.apply(n,arguments)}},f.decode64=function(e){var n,f,o,d,i,t,l,s,u="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",a=e.length,p="";for(n=0;a>n;n+=4)f=u.indexOf(e[n]),o=u.indexOf(e[n+1]),d=u.indexOf(e[n+2]),i=u.indexOf(e[n+3]),t=f<<2|o>>4,l=(15&o)<<4|d>>2,s=(3&d)<<6|i,p+=64===d?String.fromCharCode(t):64===i||-1===i?String.fromCharCode(t,l):String.fromCharCode(t,l,s);return p},f.getBounds=function(e){if(e.getBoundingClientRect){var n=e.getBoundingClientRect(),f=null==e.offsetWidth?n.width:e.offsetWidth;return{top:n.top,bottom:n.bottom||n.top+n.height,right:n.left+f,left:n.left,width:f,height:null==e.offsetHeight?n.height:e.offsetHeight}}return{}},f.offsetBounds=function(e){var n=e.offsetParent?f.offsetBounds(e.offsetParent):{top:0,left:0};return{top:e.offsetTop+n.top,bottom:e.offsetTop+e.offsetHeight+n.top,right:e.offsetLeft+n.left+e.offsetWidth,left:e.offsetLeft+n.left,width:e.offsetWidth,height:e.offsetHeight}},f.parseBackgrounds=function(e){var n,f,o,d,i,t,l,s=" \r\n ",u=[],a=0,p=0,c=function(){n&&('"'===f.substr(0,1)&&(f=f.substr(1,f.length-2)),f&&l.push(f),"-"===n.substr(0,1)&&(d=n.indexOf("-",1)+1)>0&&(o=n.substr(0,d),n=n.substr(d)),u.push({prefix:o,method:n.toLowerCase(),value:i,args:l,image:null})),l=[],n=o=f=i=""};return l=[],n=o=f=i="",e.split("").forEach(function(e){if(!(0===a&&s.indexOf(e)>-1)){switch(e){case'"':t?t===e&&(t=null):t=e;break;case"(":if(t)break;if(0===a)return a=1,void(i+=e);p++;break;case")":if(t)break;if(1===a){if(0===p)return a=0,i+=e,void c();p--}break;case",":if(t)break;if(0===a)return void c();if(1===a&&0===p&&!n.match(/^url$/i))return l.push(f),f="",void(i+=e)}i+=e,0===a?n+=e:f+=e}}),c(),u}},{}],30:[function(e,n){function f(e){o.apply(this,arguments),this.type="linear"===e.args[0]?this.TYPES.LINEAR:this.TYPES.RADIAL}var o=e("./gradientcontainer");f.prototype=Object.create(o.prototype),n.exports=f},{"./gradientcontainer":11}],31:[function(e,n){function f(e){return new o(function(n,f){var o=new XMLHttpRequest;o.open("GET",e),o.onload=function(){200===o.status?n(o.responseText):f(new Error(o.statusText))},o.onerror=function(){f(new Error("Network Error"))},o.send()})}var o=e("./promise");n.exports=f},{"./promise":18}]},{},[6])(6)}); \ No newline at end of file diff --git a/public/assets/js/libs/jsPDF-AutoTable/LICENSE.txt b/public/assets/js/libs/jsPDF-AutoTable/LICENSE.txt new file mode 100644 index 0000000000..2d5ec87f38 --- /dev/null +++ b/public/assets/js/libs/jsPDF-AutoTable/LICENSE.txt @@ -0,0 +1,20 @@ +Copyright (c) 2014 Simon Bengtsson, https://github.com/someatoms/jspdf-autotable + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/public/assets/js/libs/jsPDF-AutoTable/jspdf.plugin.autotable.js b/public/assets/js/libs/jsPDF-AutoTable/jspdf.plugin.autotable.js new file mode 100644 index 0000000000..71c2aad6aa --- /dev/null +++ b/public/assets/js/libs/jsPDF-AutoTable/jspdf.plugin.autotable.js @@ -0,0 +1,418 @@ +/** + * jsPDF AutoTable plugin + * Copyright (c) 2014 Simon Bengtsson, https://github.com/someatoms/jsPDF-AutoTable + * + * Licensed under the MIT License. + * http://opensource.org/licenses/mit-license + */ +(function (API) { + 'use strict'; + + // On every new jsPDF object, clear variables + API.events.push(['initialized', function () { + doc = undefined; + cellPos = undefined; + pageCount = 1; + settings = undefined; + }], false); + + var MIN_COLUMN_WIDTH = 25; + + var doc, cellPos, pageCount = 1, settings; + + // See README.md or examples for documentation of the options + // return a new instance every time to avoid references issues + var defaultOptions = function () { + return { + padding: 5, + fontSize: 10, + lineHeight: 20, + renderHeader: function (doc, pageNumber, settings) { + }, + renderFooter: function (doc, lastCellPos, pageNumber, settings) { + }, + renderHeaderCell: function (x, y, width, height, key, value, settings) { + doc.setFillColor(52, 73, 94); // Asphalt + doc.setTextColor(255, 255, 255); + doc.setFontStyle('bold'); + doc.rect(x, y, width, height, 'F'); + y += settings.lineHeight / 2 + API.autoTableTextHeight() / 2; + doc.text(value, x + settings.padding, y); + }, + renderCell: function (x, y, width, height, key, value, row, settings) { + doc.setFillColor(row % 2 === 0 ? 245 : 255); + doc.setTextColor(50); + doc.rect(x, y, width, height, 'F'); + y += settings.lineHeight / 2 + API.autoTableTextHeight() / 2 - 2.5; + doc.text(value, x + settings.padding, y); + }, + margins: {right: 40, left: 40, top: 50, bottom: 40}, + startY: false, + overflow: 'ellipsize', // false, ellipsize or linebreak (false passes the raw text to renderCell) + overflowColumns: false, // Specify which colums that gets subjected to the overflow method chosen. false indicates all + avoidPageSplit: false, + extendWidth: true + } + }; + + /** + * Create a table from a set of rows and columns. + * + * @param {Object[]|String[]} columns Either as an array of objects or array of strings + * @param {Object[][]|String[][]} data Either as an array of objects or array of strings + * @param {Object} [options={}] Options that will override the default ones (above) + */ + API.autoTable = function (columns, data, options) { + options = options || {}; + columns = columns || []; + doc = this; + + var userFontSize = doc.internal.getFontSize(); + + initData({columns: columns, data: data}); + initOptions(options); + + cellPos = { + x: settings.margins.left, + y: settings.startY === false ? settings.margins.top : settings.startY + }; + + var tableHeight = settings.margins.bottom + settings.margins.top + settings.lineHeight * (data.length + 1) + 5 + settings.startY; + if (settings.startY !== false && settings.avoidPageSplit && tableHeight > doc.internal.pageSize.height) { + pageCount++; + doc.addPage(); + cellPos.y = settings.margins.top; + } + + settings.renderHeader(doc, pageCount, settings); + var columnWidths = calculateColumnWidths(data, columns); + printHeader(columns, columnWidths); + printRows(columns, data, columnWidths); + settings.renderFooter(doc, cellPos, pageCount, settings); + + doc.setFontSize(userFontSize); + + return this; + }; + + /** + * Returns the Y position of the last drawn cell + * @returns int + */ + API.autoTableEndPosY = function () { + // If cellPos is not set, autoTable() has probably not been called + return cellPos ? cellPos.y : false; + }; + + /** + * @deprecated Use autoTableEndPosY() + */ + API.autoTableEndPos = function () { + return cellPos; + }; + + /** + * Parses an html table. To draw a table, use it like this: + * `doc.autoTable(false, doc.autoTableHtmlToJson(tableDomElem))` + * + * @param table Html table element + * @param indexBased Boolean flag if result should be returned as seperate cols and data + * @returns []|{} Array of objects with object keys as headers or based on indexes if indexBased is set to true + */ + API.autoTableHtmlToJson = function (table, indexBased) { + var data = [], headers = {}, header = table.rows[0], i, tableRow, rowData, j; + if (indexBased) { + headers = []; + for (i = 0; i < header.cells.length; i++) { + headers.push(header.cells[i] ? header.cells[i].textContent : ''); + } + + for (i = 1; i < table.rows.length; i++) { + tableRow = table.rows[i]; + rowData = []; + for (j = 0; j < header.cells.length; j++) { + rowData.push(tableRow.cells[j] ? tableRow.cells[j].textContent : ''); + } + data.push(rowData); + } + return {columns: headers, data: data}; + } else { + for (i = 0; i < header.cells.length; i++) { + headers[i] = header.cells[i] ? header.cells[i].textContent : ''; + } + + for (i = 1; i < table.rows.length; i++) { + tableRow = table.rows[i]; + rowData = {}; + for (j = 0; j < header.cells.length; j++) { + rowData[headers[j]] = tableRow.cells[j] ? tableRow.cells[j].textContent : ''; + } + data.push(rowData); + } + + return data; + } + }; + + /** + * Basically the same as getLineHeight() in 1.0+ versions of jsPDF, however + * added here for backwards compatibility with version 0.9 + * + * Export it to make it available in drawCell and drawHeaderCell + */ + API.autoTableTextHeight = function() { + // The value 1.15 comes from from the jsPDF source code and looks about right + return doc.internal.getFontSize() * 1.15; + }; + + /** + * Transform all to the object initialization form + * @param params + */ + function initData(params) { + + // Object only initial + if (!params.columns || params.columns.length === 0) { + var keys = Object.keys(params.data[0]); + Array.prototype.push.apply(params.columns, keys); + params.columns.forEach(function (title, i) { + params.columns[i] = {title: title, key: keys[i]}; + }); + } + // Array initialization form + else if (typeof params.columns[0] === 'string') { + params.data.forEach(function (row, i) { + var obj = {}; + for (var j = 0; j < row.length; j++) { + obj[j] = params.data[i][j]; + } + params.data[i] = obj; + }); + params.columns.forEach(function (title, i) { + params.columns[i] = {title: title, key: i}; + }); + } else { + // Use options as is + } + } + + function initOptions(raw) { + settings = defaultOptions(); + Object.keys(raw).forEach(function (key) { + settings[key] = raw[key]; + }); + doc.setFontSize(settings.fontSize); + + // Backwards compatibility + if(settings.margins.horizontal !== undefined) { + settings.margins.left = settings.margins.horizontal; + settings.margins.right = settings.margins.horizontal; + } else { + settings.margins.horizontal = settings.margins.left; + } + } + + function calculateColumnWidths(rows, columns) { + var widths = {}; + + // Optimal widths + var optimalTableWidth = 0; + columns.forEach(function (header) { + var widest = getStringWidth(header.title || '', true); + if(typeof header.width == "number") { + widest = header.width; + } else { + rows.forEach(function (row) { + if (!header.hasOwnProperty('key')) + throw new Error("The key attribute is required in every header"); + var w = getStringWidth(stringify(row, header.key)); + if (w > widest) { + widest = w; + } + }); + } + widths[header.key] = widest; + optimalTableWidth += widest; + }); + + var paddingAndMargin = settings.padding * 2 * columns.length + settings.margins.left + settings.margins.right; + var spaceDiff = doc.internal.pageSize.width - optimalTableWidth - paddingAndMargin; + + var keys = Object.keys(widths); + if (spaceDiff < 0) { + // Shrink columns + var shrinkableColumns = []; + var shrinkableColumnWidths = 0; + if (settings.overflowColumns === false) { + keys.forEach(function (key) { + if (widths[key] > MIN_COLUMN_WIDTH) { + shrinkableColumns.push(key); + shrinkableColumnWidths += widths[key]; + } + }); + } else { + shrinkableColumns = settings.overflowColumns; + shrinkableColumns.forEach(function (col) { + shrinkableColumnWidths += widths[col]; + }); + } + + shrinkableColumns.forEach(function (key) { + widths[key] += spaceDiff * (widths[key] / shrinkableColumnWidths); + }); + } else if (spaceDiff > 0 && settings.extendWidth) { + // Fill page horizontally + keys.forEach(function (key) { + widths[key] += spaceDiff / keys.length; + }); + } + + return widths; + } + + function printHeader(headers, columnWidths) { + if (!headers) return; + + // First calculate the height of the row + // (to do that the maxium amount of rows first need to be found) + var maxRows = 1; + if (settings.overflow === 'linebreak') { + // Font style must be the same as in function renderHeaderCell() + doc.setFontStyle('bold'); + + headers.forEach(function (header) { + if (isOverflowColumn(header)) { + var value = header.title || ''; + var arr = doc.splitTextToSize(value, columnWidths[header.key]); + if (arr.length > maxRows) { + maxRows = arr.length; + } + } + }); + } + var rowHeight = settings.lineHeight + (maxRows - 1) * API.autoTableTextHeight() + 5; + + // Avoid isolated table headers when drawing multiple tables. Add a new page + // if cellpos would be at the end of page after drawing the header row + var newPage = (cellPos.y + settings.margins.bottom + rowHeight * 2) >= doc.internal.pageSize.height; + if (newPage) { + settings.renderFooter(doc, cellPos, pageCount, settings); + doc.addPage(); + cellPos = {x: settings.margins.left, y: settings.margins.top}; + pageCount++; + settings.renderHeader(doc, pageCount, settings); + } + + headers.forEach(function (header) { + var width = columnWidths[header.key] + settings.padding * 2; + var value = header.title || ''; + if (settings.overflow === 'linebreak') { + if (isOverflowColumn(header)) { + value = doc.splitTextToSize(value, columnWidths[header.key]); + } + } else if (settings.overflow === 'ellipsize') { + value = ellipsize(columnWidths[header.key], value); + } + settings.renderHeaderCell(cellPos.x, cellPos.y, width, rowHeight, header.key, value, settings); + cellPos.x += width; + }); + doc.setTextColor(70, 70, 70); + doc.setFontStyle('normal'); + + cellPos.y += rowHeight; + cellPos.x = settings.margins.left; + } + + function printRows(headers, rows, columnWidths) { + for (var i = 0; i < rows.length; i++) { + var row = rows[i]; + + // First calculate the height of the row + // (to do that the maxium amount of rows first need to be found) + var maxRows = 1; + if (settings.overflow === 'linebreak') { + headers.forEach(function (header) { + if (isOverflowColumn(header)) { + var value = stringify(row, header.key); + var arr = doc.splitTextToSize(value, columnWidths[header.key]); + if (arr.length > maxRows) { + maxRows = arr.length; + } + } + }); + } + var rowHeight = settings.lineHeight + (maxRows - 1) * API.autoTableTextHeight(); + + + // Render the cell + headers.forEach(function (header) { + var value = stringify(row, header.key); + if (settings.overflow === 'linebreak') { + if (isOverflowColumn(header)) { + value = doc.splitTextToSize(value, columnWidths[header.key]); + } + } else if (settings.overflow === 'ellipsize') { + value = ellipsize(columnWidths[header.key], value); + } + var width = columnWidths[header.key] + settings.padding * 2; + settings.renderCell(cellPos.x, cellPos.y, width, rowHeight, header.key, value, i, settings); + cellPos.x = cellPos.x + columnWidths[header.key] + settings.padding * 2; + }); + + // Add a new page if cellpos is at the end of page + var newPage = (cellPos.y + settings.margins.bottom + rowHeight * 2) >= doc.internal.pageSize.height; + if (newPage) { + if (i+1 < rows.length) { + settings.renderFooter(doc, cellPos, pageCount, settings); + doc.addPage(); + cellPos = {x: settings.margins.left, y: settings.margins.top}; + pageCount++; + settings.renderHeader(doc, pageCount, settings); + printHeader(headers, columnWidths); + } + } else { + cellPos.y += rowHeight; + cellPos.x = settings.margins.left; + } + } + } + + function isOverflowColumn(header) { + return settings.overflowColumns === false || settings.overflowColumns.indexOf(header.key) !== -1; + } + + /** + * Ellipsize the text to fit in the width + * @param width + * @param text + */ + function ellipsize(width, text) { + if (width >= getStringWidth(text)) { + return text; + } + while (width < getStringWidth(text + "...")) { + if (text.length < 2) { + break; + } + text = text.substring(0, text.length - 1); + } + text += "..."; + return text; + } + + function stringify(row, key) { + return row.hasOwnProperty(key) ? '' + row[key] : ''; + } + + function getStringWidth(txt, isBold) { + if(isBold) { + doc.setFontStyle('bold'); + } + var strWidth = doc.getStringUnitWidth(txt) * doc.internal.getFontSize(); + if(isBold) { + doc.setFontStyle('normal'); + } + return strWidth; + } + +})(jsPDF.API); diff --git a/public/assets/js/libs/jsPDF/MIT-LICENSE.txt b/public/assets/js/libs/jsPDF/MIT-LICENSE.txt new file mode 100644 index 0000000000..2e06d0a1f2 --- /dev/null +++ b/public/assets/js/libs/jsPDF/MIT-LICENSE.txt @@ -0,0 +1,20 @@ +Copyright (c) 2010-2014 James Hall, https://github.com/MrRio/jsPDF + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/public/assets/js/libs/jsPDF/jspdf.min.js b/public/assets/js/libs/jsPDF/jspdf.min.js new file mode 100644 index 0000000000..c72711a95f --- /dev/null +++ b/public/assets/js/libs/jsPDF/jspdf.min.js @@ -0,0 +1,171 @@ +/** + * jsPDF - PDF Document creation from JavaScript + * Version 1.0.272-git Built on 2014-09-29T15:09 + * CommitID d4770725ca + * + * Copyright (c) 2010-2014 James Hall, https://github.com/MrRio/jsPDF + * 2010 Aaron Spike, https://github.com/acspike + * 2012 Willow Systems Corporation, willow-systems.com + * 2012 Pablo Hess, https://github.com/pablohess + * 2012 Florian Jenett, https://github.com/fjenett + * 2013 Warren Weckesser, https://github.com/warrenweckesser + * 2013 Youssef Beddad, https://github.com/lifof + * 2013 Lee Driscoll, https://github.com/lsdriscoll + * 2013 Stefan Slonevskiy, https://github.com/stefslon + * 2013 Jeremy Morel, https://github.com/jmorel + * 2013 Christoph Hartmann, https://github.com/chris-rock + * 2014 Juan Pablo Gaviria, https://github.com/juanpgaviria + * 2014 James Makes, https://github.com/dollaruw + * 2014 Diego Casorran, https://github.com/diegocr + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Contributor(s): + * siefkenj, ahwolf, rickygu, Midnith, saintclair, eaparango, + * kim3er, mfo, alnorth, + */ +/** + * jsPDF addHTML PlugIn + * Copyright (c) 2014 Diego Casorran + * Licensed under the MIT License. + * http://opensource.org/licenses/mit-license + */ +/** + * jsPDF addImage plugin + * Copyright (c) 2012 Jason Siefken, https://github.com/siefkenj/ + * 2013 Chris Dowling, https://github.com/gingerchris + * 2013 Trinh Ho, https://github.com/ineedfat + * 2013 Edwin Alejandro Perez, https://github.com/eaparango + * 2013 Norah Smith, https://github.com/burnburnrocket + * 2014 Diego Casorran, https://github.com/diegocr + * 2014 James Robb, https://github.com/jamesbrobb + */ +/** + * jsPDF Cell plugin + * Copyright (c) 2013 Youssef Beddad, youssef.beddad@gmail.com + * 2013 Eduardo Menezes de Morais, eduardo.morais@usp.br + * 2013 Lee Driscoll, https://github.com/lsdriscoll + * 2014 Juan Pablo Gaviria, https://github.com/juanpgaviria + * 2014 James Hall, james@parall.ax + * 2014 Diego Casorran, https://github.com/diegocr + */ +/** + * jsPDF fromHTML plugin. BETA stage. API subject to change. Needs browser + * Copyright (c) 2012 Willow Systems Corporation, willow-systems.com + * 2014 Juan Pablo Gaviria, https://github.com/juanpgaviria + * 2014 Diego Casorran, https://github.com/diegocr + * 2014 Daniel Husar, https://github.com/danielhusar + * 2014 Wolfgang Gassler, https://github.com/woolfg + */ +/** + * jsPDF JavaScript plugin + * Copyright (c) 2013 Youssef Beddad, youssef.beddad@gmail.com + */ +/** + * jsPDF PNG PlugIn + * Copyright (c) 2014 James Robb, https://github.com/jamesbrobb + */ +/** +jsPDF Silly SVG plugin +Copyright (c) 2012 Willow Systems Corporation, willow-systems.com +*/ +/** + * jsPDF split_text_to_size plugin - MIT license. + * Copyright (c) 2012 Willow Systems Corporation, willow-systems.com + * 2014 Diego Casorran, https://github.com/diegocr + */ +/** +jsPDF standard_fonts_metrics plugin +Copyright (c) 2012 Willow Systems Corporation, willow-systems.com +MIT license. +*/ +/** + * jsPDF total_pages plugin + * Copyright (c) 2013 Eduardo Menezes de Morais, eduardo.morais@usp.br + */ +/* Blob.js + * A Blob implementation. + * 2014-07-24 + * By Eli Grey, http://eligrey.com + * By Devin Samarin, https://github.com/dsamarin + * License: X11/MIT + * See https://github.com/eligrey/Blob.js/blob/master/LICENSE.md + */ +/* FileSaver.js + * A saveAs() FileSaver implementation. + * 2014-08-29 + * By Eli Grey, http://eligrey.com + * License: X11/MIT + * See https://github.com/eligrey/FileSaver.js/blob/master/LICENSE.md + */ +/* + * Copyright (c) 2012 chick307 <chick307@gmail.com> + * Licensed under the MIT License. + * http://opensource.org/licenses/mit-license + */ +/* + Deflate.js - https://github.com/gildas-lormeau/zip.js + Copyright (c) 2013 Gildas Lormeau. All rights reserved. + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, + INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* +# PNG.js +# Copyright (c) 2011 Devon Govett +# MIT LICENSE +# +*/ +/* + * Extracted from pdf.js + * https://github.com/andreasgal/pdf.js + * Copyright (c) 2011 Mozilla Foundation + * Contributors: Andreas Gal <gal@mozilla.com> + * Chris G Jones <cjones@mozilla.com> + * Shaon Barman <shaon.barman@gmail.com> + * Vivien Nicolas <21@vingtetun.org> + * Justin D'Arcangelo <justindarc@gmail.com> + * Yury Delendik + */ +/** + * JavaScript Polyfill functions for jsPDF + * Collected from public resources by + * https://github.com/diegocr + */ +!function(t,e){e["true"]=t;var n=function(t){"use strict";function e(e){var n={};this.subscribe=function(t,e,r){if("function"!=typeof e)return!1;n.hasOwnProperty(t)||(n[t]={});var s=Math.random().toString(35);return n[t][s]=[e,!!r],s},this.unsubscribe=function(t){for(var e in n)if(n[e][t])return delete n[e][t],!0;return!1},this.publish=function(r){if(n.hasOwnProperty(r)){var s=Array.prototype.slice.call(arguments,1),i=[];for(var o in n[r]){var a=n[r][o];try{a[0].apply(e,s)}catch(u){t.console&&console.error("jsPDF PubSub Error",u.message,u)}a[1]&&i.push(o)}i.length&&i.forEach(this.unsubscribe)}}}function n(a,u,c,l){var f={};"object"==typeof a&&(f=a,a=f.orientation,u=f.unit||u,c=f.format||c,l=f.compress||f.compressPdf||l),u=u||"mm",c=c||"a4",a=(""+(a||"P")).toLowerCase();var d,h,p,m,w,g,y,v,b,q=((""+c).toLowerCase(),!!l&&"function"==typeof Uint8Array),x=f.textColor||"0 g",k=f.drawColor||"0 G",_=f.fontSize||16,A=f.lineHeight||1.15,C=f.lineWidth||.200025,S=2,E=!1,z=[],T={},I={},B=0,O=[],P={},R=[],F=0,D=0,U=0,N={title:"",subject:"",author:"",keywords:"",creator:""},L={},j=new e(L),M=function(t){return t.toFixed(2)},H=function(t){return t.toFixed(3)},G=function(t){return("0"+parseInt(t)).slice(-2)},W=function(t){E?O[m].push(t):(U+=t.length+1,R.push(t))},V=function(){return S++,z[S]=U,W(S+" 0 obj"),S},J=function(t){W("stream"),W(t),W("endstream")},X=function(){var e,r,i,o,a,u,c,l,f;for(c=t.adler32cs||n.adler32cs,q&&"undefined"==typeof c&&(q=!1),e=1;B>=e;e++){if(V(),l=(w=P[e].width)*h,f=(g=P[e].height)*h,W("<</Type /Page"),W("/Parent 1 0 R"),W("/Resources 2 0 R"),W("/MediaBox [0 0 "+M(l)+" "+M(f)+"]"),W("/Contents "+(S+1)+" 0 R>>"),W("endobj"),r=O[e].join("\n"),V(),q){for(i=[],o=r.length;o--;)i[o]=r.charCodeAt(o);u=c.from(r),a=new s(6),a.append(new Uint8Array(i)),r=a.flush(),i=new Uint8Array(r.length+6),i.set(new Uint8Array([120,156])),i.set(r,2),i.set(new Uint8Array([255&u,u>>8&255,u>>16&255,u>>24&255]),r.length+2),r=String.fromCharCode.apply(null,i),W("<</Length "+r.length+" /Filter [/FlateDecode]>>")}else W("<</Length "+r.length+">>");J(r),W("endobj")}z[1]=U,W("1 0 obj"),W("<</Type /Pages");var d="/Kids [";for(o=0;B>o;o++)d+=3+2*o+" 0 R ";W(d+"]"),W("/Count "+B),W(">>"),W("endobj")},Y=function(t){t.objectNumber=V(),W("<</BaseFont/"+t.PostScriptName+"/Type/Font"),"string"==typeof t.encoding&&W("/Encoding/"+t.encoding),W("/Subtype/Type1>>"),W("endobj")},K=function(){for(var t in T)T.hasOwnProperty(t)&&Y(T[t])},Q=function(){j.publish("putXobjectDict")},$=function(){W("/ProcSet [/PDF /Text /ImageB /ImageC /ImageI]"),W("/Font <<");for(var t in T)T.hasOwnProperty(t)&&W("/"+t+" "+T[t].objectNumber+" 0 R");W(">>"),W("/XObject <<"),Q(),W(">>")},Z=function(){K(),j.publish("putResources"),z[2]=U,W("2 0 obj"),W("<<"),$(),W(">>"),W("endobj"),j.publish("postPutResources")},te=function(t,e,n){I.hasOwnProperty(e)||(I[e]={}),I[e][n]=t},ee=function(t,e,n,r){var s="F"+(Object.keys(T).length+1).toString(10),i=T[s]={id:s,PostScriptName:t,fontName:e,fontStyle:n,encoding:r,metadata:{}};return te(s,e,n),j.publish("addFont",i),s},ne=function(){for(var t="helvetica",e="times",n="courier",r="normal",s="bold",i="italic",o="bolditalic",a="StandardEncoding",u=[["Helvetica",t,r],["Helvetica-Bold",t,s],["Helvetica-Oblique",t,i],["Helvetica-BoldOblique",t,o],["Courier",n,r],["Courier-Bold",n,s],["Courier-Oblique",n,i],["Courier-BoldOblique",n,o],["Times-Roman",e,r],["Times-Bold",e,s],["Times-Italic",e,i],["Times-BoldItalic",e,o]],c=0,l=u.length;l>c;c++){var f=ee(u[c][0],u[c][1],u[c][2],a),d=u[c][0].split("-");te(f,d[0],d[1]||"")}j.publish("addFonts",{fonts:T,dictionary:I})},re=function(e){return e.foo=function(){try{return e.apply(this,arguments)}catch(n){var r=n.stack||"";~r.indexOf(" at ")&&(r=r.split(" at ")[1]);var s="Error in function "+r.split("\n")[0].split("<")[0]+": "+n.message;if(!t.console)throw new Error(s);t.console.error(s,n),t.alert&&alert(s)}},e.foo.bar=e,e.foo},se=function(t,e){var n,r,s,i,o,a,u,c,l;if(e=e||{},s=e.sourceEncoding||"Unicode",o=e.outputEncoding,(e.autoencode||o)&&T[d].metadata&&T[d].metadata[s]&&T[d].metadata[s].encoding&&(i=T[d].metadata[s].encoding,!o&&T[d].encoding&&(o=T[d].encoding),!o&&i.codePages&&(o=i.codePages[0]),"string"==typeof o&&(o=i[o]),o)){for(u=!1,a=[],n=0,r=t.length;r>n;n++)c=o[t.charCodeAt(n)],a.push(c?String.fromCharCode(c):t[n]),a[n].charCodeAt(0)>>8&&(u=!0);t=a.join("")}for(n=t.length;void 0===u&&0!==n;)t.charCodeAt(n-1)>>8&&(u=!0),n--;if(!u)return t;for(a=e.noBOM?[]:[254,255],n=0,r=t.length;r>n;n++){if(c=t.charCodeAt(n),l=c>>8,l>>8)throw new Error("Character at position "+n+" of string '"+t+"' exceeds 16bits. Cannot be encoded into UCS-2 BE");a.push(l),a.push(c-(l<<8))}return String.fromCharCode.apply(void 0,a)},ie=function(t,e){return se(t,e).replace(/\\/g,"\\\\").replace(/\(/g,"\\(").replace(/\)/g,"\\)")},oe=function(){W("/Producer (jsPDF "+n.version+")");for(var t in N)N.hasOwnProperty(t)&&N[t]&&W("/"+t.substr(0,1).toUpperCase()+t.substr(1)+" ("+ie(N[t])+")");var e=new Date,r=e.getTimezoneOffset(),s=0>r?"+":"-",i=Math.floor(Math.abs(r/60)),o=Math.abs(r%60),a=[s,G(i),"'",G(o),"'"].join("");W(["/CreationDate (D:",e.getFullYear(),G(e.getMonth()+1),G(e.getDate()),G(e.getHours()),G(e.getMinutes()),G(e.getSeconds()),a,")"].join(""))},ae=function(){switch(W("/Type /Catalog"),W("/Pages 1 0 R"),v||(v="fullwidth"),v){case"fullwidth":W("/OpenAction [3 0 R /FitH null]");break;case"fullheight":W("/OpenAction [3 0 R /FitV null]");break;case"fullpage":W("/OpenAction [3 0 R /Fit]");break;case"original":W("/OpenAction [3 0 R /XYZ null null 1]");break;default:var t=""+v;"%"===t.substr(t.length-1)&&(v=parseInt(v)/100),"number"==typeof v&&W("/OpenAction [3 0 R /XYZ null null "+M(v)+"]")}switch(b||(b="continuous"),b){case"continuous":W("/PageLayout /OneColumn");break;case"single":W("/PageLayout /SinglePage");break;case"two":case"twoleft":W("/PageLayout /TwoColumnLeft");break;case"tworight":W("/PageLayout /TwoColumnRight")}y&&W("/PageMode /"+y),j.publish("putCatalog")},ue=function(){W("/Size "+(S+1)),W("/Root "+S+" 0 R"),W("/Info "+(S-1)+" 0 R")},ce=function(t,e){var n="string"==typeof e&&e.toLowerCase();if("string"==typeof t){var r=t.toLowerCase();o.hasOwnProperty(r)&&(t=o[r][0]/h,e=o[r][1]/h)}if(Array.isArray(t)&&(e=t[1],t=t[0]),n){switch(n.substr(0,1)){case"l":e>t&&(n="s");break;case"p":t>e&&(n="s")}"s"===n&&(p=t,t=e,e=p)}E=!0,O[++B]=[],P[B]={width:Number(t)||w,height:Number(e)||g},fe(B)},le=function(){ce.apply(this,arguments),W(M(C*h)+" w"),W(k),0!==F&&W(F+" J"),0!==D&&W(D+" j"),j.publish("addPage",{pageNumber:B})},fe=function(t){t>0&&B>=t&&(m=t,w=P[t].width,g=P[t].height)},de=function(t,e){var n;t=void 0!==t?t:T[d].fontName,e=void 0!==e?e:T[d].fontStyle;try{n=I[t][e]}catch(r){}if(!n)throw new Error("Unable to look up font label for font '"+t+"', '"+e+"'. Refer to getFontList() for available fonts.");return n},he=function(){E=!1,S=2,R=[],z=[],W("%PDF-"+i),X(),Z(),V(),W("<<"),oe(),W(">>"),W("endobj"),V(),W("<<"),ae(),W(">>"),W("endobj");var t,e=U,n="0000000000";for(W("xref"),W("0 "+(S+1)),W(n+" 65535 f "),t=1;S>=t;t++)W((n+z[t]).slice(-10)+" 00000 n ");return W("trailer"),W("<<"),ue(),W(">>"),W("startxref"),W(e),W("%%EOF"),E=!0,R.join("\n")},pe=function(t){var e="S";return"F"===t?e="f":"FD"===t||"DF"===t?e="B":("f"===t||"f*"===t||"B"===t||"B*"===t)&&(e=t),e},me=function(){for(var t=he(),e=t.length,n=new ArrayBuffer(e),r=new Uint8Array(n);e--;)r[e]=t.charCodeAt(e);return n},we=function(){return new Blob([me()],{type:"application/pdf"})},ge=re(function(e,n){var s="dataur"===(""+e).substr(0,6)?"data:application/pdf;base64,"+btoa(he()):0;switch(e){case void 0:return he();case"save":if(navigator.getUserMedia&&(void 0===t.URL||void 0===t.URL.createObjectURL))return L.output("dataurlnewwindow");r(we(),n),"function"==typeof r.unload&&t.setTimeout&&setTimeout(r.unload,911);break;case"arraybuffer":return me();case"blob":return we();case"bloburi":case"bloburl":return t.URL&&t.URL.createObjectURL(we())||void 0;case"datauristring":case"dataurlstring":return s;case"dataurlnewwindow":var i=t.open(s);if(i||"undefined"==typeof safari)return i;case"datauri":case"dataurl":return t.document.location.href=s;default:throw new Error('Output type "'+e+'" is not supported.')}});switch(u){case"pt":h=1;break;case"mm":h=72/25.4;break;case"cm":h=72/2.54;break;case"in":h=72;break;case"px":h=96/72;break;case"pc":h=12;break;case"em":h=12;break;case"ex":h=6;break;default:throw"Invalid unit: "+u}L.internal={pdfEscape:ie,getStyle:pe,getFont:function(){return T[de.apply(L,arguments)]},getFontSize:function(){return _},getLineHeight:function(){return _*A},write:function(t){W(1===arguments.length?t:Array.prototype.join.call(arguments," "))},getCoordinateString:function(t){return M(t*h)},getVerticalCoordinateString:function(t){return M((g-t)*h)},collections:{},newObject:V,putStream:J,events:j,scaleFactor:h,pageSize:{get width(){return w},get height(){return g}},output:function(t,e){return ge(t,e)},getNumberOfPages:function(){return O.length-1},pages:O},L.addPage=function(){return le.apply(this,arguments),this},L.setPage=function(){return fe.apply(this,arguments),this},L.setDisplayMode=function(t,e,n){return v=t,b=e,y=n,this},L.text=function(t,e,n,r,s){function i(t){return t=t.split(" ").join(Array(f.TabLen||9).join(" ")),ie(t,r)}"number"==typeof t&&(p=n,n=e,e=t,t=p),"string"==typeof t&&t.match(/[\n\r]/)&&(t=t.split(/\r\n|\r|\n/g)),"number"==typeof r&&(s=r,r=null);var o,a="",u="Td";if(s){s*=Math.PI/180;var c=Math.cos(s),l=Math.sin(s);a=[M(c),M(l),M(-1*l),M(c),""].join(" "),u="Tm"}if(r=r||{},"noBOM"in r||(r.noBOM=!0),"autoencode"in r||(r.autoencode=!0),"string"==typeof t)t=i(t);else{if(!(t instanceof Array))throw new Error('Type of text must be string or Array. "'+t+'" is not recognized.');for(var m=t.concat(),w=[],y=m.length;y--;)w.push(i(m.shift()));var v=Math.ceil((g-n)*h/(_*A));v>=0&&v<w.length+1&&(o=w.splice(v-1)),t=w.join(") Tj\nT* (")}return W("BT\n/"+d+" "+_+" Tf\n"+_*A+" TL\n"+x+"\n"+a+M(e*h)+" "+M((g-n)*h)+" "+u+"\n("+t+") Tj\nET"),o&&(this.addPage(),this.text(o,e,1.7*_/h)),this},L.lstext=function(t,e,n,r){for(var s=0,i=t.length;i>s;s++,e+=r)this.text(t[s],e,n)},L.line=function(t,e,n,r){return this.lines([[n-t,r-e]],t,e)},L.clip=function(){W("W"),W("S")},L.lines=function(t,e,n,r,s,i){var o,a,u,c,l,f,d,m,w,y,v;for("number"==typeof t&&(p=n,n=e,e=t,t=p),r=r||[1,1],W(H(e*h)+" "+H((g-n)*h)+" m "),o=r[0],a=r[1],c=t.length,y=e,v=n,u=0;c>u;u++)l=t[u],2===l.length?(y=l[0]*o+y,v=l[1]*a+v,W(H(y*h)+" "+H((g-v)*h)+" l")):(f=l[0]*o+y,d=l[1]*a+v,m=l[2]*o+y,w=l[3]*a+v,y=l[4]*o+y,v=l[5]*a+v,W(H(f*h)+" "+H((g-d)*h)+" "+H(m*h)+" "+H((g-w)*h)+" "+H(y*h)+" "+H((g-v)*h)+" c"));return i&&W(" h"),null!==s&&W(pe(s)),this},L.rect=function(t,e,n,r,s){pe(s);return W([M(t*h),M((g-e)*h),M(n*h),M(-r*h),"re"].join(" ")),null!==s&&W(pe(s)),this},L.triangle=function(t,e,n,r,s,i,o){return this.lines([[n-t,r-e],[s-n,i-r],[t-s,e-i]],t,e,[1,1],o,!0),this},L.roundedRect=function(t,e,n,r,s,i,o){var a=4/3*(Math.SQRT2-1);return this.lines([[n-2*s,0],[s*a,0,s,i-i*a,s,i],[0,r-2*i],[0,i*a,-(s*a),i,-s,i],[-n+2*s,0],[-(s*a),0,-s,-(i*a),-s,-i],[0,-r+2*i],[0,-(i*a),s*a,-i,s,-i]],t+s,e,[1,1],o),this},L.ellipse=function(t,e,n,r,s){var i=4/3*(Math.SQRT2-1)*n,o=4/3*(Math.SQRT2-1)*r;return W([M((t+n)*h),M((g-e)*h),"m",M((t+n)*h),M((g-(e-o))*h),M((t+i)*h),M((g-(e-r))*h),M(t*h),M((g-(e-r))*h),"c"].join(" ")),W([M((t-i)*h),M((g-(e-r))*h),M((t-n)*h),M((g-(e-o))*h),M((t-n)*h),M((g-e)*h),"c"].join(" ")),W([M((t-n)*h),M((g-(e+o))*h),M((t-i)*h),M((g-(e+r))*h),M(t*h),M((g-(e+r))*h),"c"].join(" ")),W([M((t+i)*h),M((g-(e+r))*h),M((t+n)*h),M((g-(e+o))*h),M((t+n)*h),M((g-e)*h),"c"].join(" ")),null!==s&&W(pe(s)),this},L.circle=function(t,e,n,r){return this.ellipse(t,e,n,n,r)},L.setProperties=function(t){for(var e in N)N.hasOwnProperty(e)&&t[e]&&(N[e]=t[e]);return this},L.setFontSize=function(t){return _=t,this},L.setFont=function(t,e){return d=de(t,e),this},L.setFontStyle=L.setFontType=function(t){return d=de(void 0,t),this},L.getFontList=function(){var t,e,n,r={};for(t in I)if(I.hasOwnProperty(t)){r[t]=n=[];for(e in I[t])I[t].hasOwnProperty(e)&&n.push(e)}return r},L.setLineWidth=function(t){return W((t*h).toFixed(2)+" w"),this},L.setDrawColor=function(t,e,n,r){var s;return s=void 0===e||void 0===r&&t===e===n?"string"==typeof t?t+" G":M(t/255)+" G":void 0===r?"string"==typeof t?[t,e,n,"RG"].join(" "):[M(t/255),M(e/255),M(n/255),"RG"].join(" "):"string"==typeof t?[t,e,n,r,"K"].join(" "):[M(t),M(e),M(n),M(r),"K"].join(" "),W(s),this},L.setFillColor=function(t,e,n,r){var s;return s=void 0===e||void 0===r&&t===e===n?"string"==typeof t?t+" g":M(t/255)+" g":void 0===r?"string"==typeof t?[t,e,n,"rg"].join(" "):[M(t/255),M(e/255),M(n/255),"rg"].join(" "):"string"==typeof t?[t,e,n,r,"k"].join(" "):[M(t),M(e),M(n),M(r),"k"].join(" "),W(s),this},L.setTextColor=function(t,e,n){if("string"==typeof t&&/^#[0-9A-Fa-f]{6}$/.test(t)){var r=parseInt(t.substr(1),16);t=r>>16&255,e=r>>8&255,n=255&r}return x=0===t&&0===e&&0===n||"undefined"==typeof e?H(t/255)+" g":[H(t/255),H(e/255),H(n/255),"rg"].join(" "),this},L.CapJoinStyles={0:0,butt:0,but:0,miter:0,1:1,round:1,rounded:1,circle:1,2:2,projecting:2,project:2,square:2,bevel:2},L.setLineCap=function(t){var e=this.CapJoinStyles[t];if(void 0===e)throw new Error("Line cap style of '"+t+"' is not recognized. See or extend .CapJoinStyles property for valid styles");return F=e,W(e+" J"),this},L.setLineJoin=function(t){var e=this.CapJoinStyles[t];if(void 0===e)throw new Error("Line join style of '"+t+"' is not recognized. See or extend .CapJoinStyles property for valid styles");return D=e,W(e+" j"),this},L.output=ge,L.save=function(t){L.output("save",t)};for(var ye in n.API)n.API.hasOwnProperty(ye)&&("events"===ye&&n.API.events.length?!function(t,e){var n,r,s;for(s=e.length-1;-1!==s;s--)n=e[s][0],r=e[s][1],t.subscribe.apply(t,[n].concat("function"==typeof r?[r]:r))}(j,n.API.events):L[ye]=n.API[ye]);return ne(),d="F1",le(c,a),j.publish("initialized"),L}var i="1.3",o={a0:[2383.94,3370.39],a1:[1683.78,2383.94],a2:[1190.55,1683.78],a3:[841.89,1190.55],a4:[595.28,841.89],a5:[419.53,595.28],a6:[297.64,419.53],a7:[209.76,297.64],a8:[147.4,209.76],a9:[104.88,147.4],a10:[73.7,104.88],b0:[2834.65,4008.19],b1:[2004.09,2834.65],b2:[1417.32,2004.09],b3:[1000.63,1417.32],b4:[708.66,1000.63],b5:[498.9,708.66],b6:[354.33,498.9],b7:[249.45,354.33],b8:[175.75,249.45],b9:[124.72,175.75],b10:[87.87,124.72],c0:[2599.37,3676.54],c1:[1836.85,2599.37],c2:[1298.27,1836.85],c3:[918.43,1298.27],c4:[649.13,918.43],c5:[459.21,649.13],c6:[323.15,459.21],c7:[229.61,323.15],c8:[161.57,229.61],c9:[113.39,161.57],c10:[79.37,113.39],dl:[311.81,623.62],letter:[612,792],"government-letter":[576,756],legal:[612,1008],"junior-legal":[576,360],ledger:[1224,792],tabloid:[792,1224],"credit-card":[153,243]};return n.API={events:[]},n.version="1.0.272-git 2014-09-29T15:09:diegocr","function"==typeof define&&define.amd?define("jsPDF",function(){return n}):t.jsPDF=n,n}("undefined"!=typeof self&&self||"undefined"!=typeof window&&window||this);!function(t){"use strict";t.addHTML=function(t,e,n,r,s){if("undefined"==typeof html2canvas&&"undefined"==typeof rasterizeHTML)throw new Error("You need either https://github.com/niklasvh/html2canvas or https://github.com/cburgmer/rasterizeHTML.js");"number"!=typeof e&&(r=e,s=n),"function"==typeof r&&(s=r,r=null);var i=this.internal,o=i.scaleFactor,a=i.pageSize.width,u=i.pageSize.height;if(r=r||{},r.onrendered=function(t){e=parseInt(e)||0,n=parseInt(n)||0;var i=r.dim||{},c=i.h||0,l=i.w||Math.min(a,t.width/o)-e,f="JPEG";if(r.format&&(f=r.format),t.height>u&&r.pagesplit){var d=function(){for(var r=0;;){var i=document.createElement("canvas");i.width=Math.min(a*o,t.width),i.height=Math.min(u*o,t.height-r);var c=i.getContext("2d");c.drawImage(t,0,r,t.width,i.height,0,0,i.width,i.height);var d=[i,e,r?0:n,i.width/o,i.height/o,f,null,"SLOW"];if(this.addImage.apply(this,d),r+=i.height,r>=t.height)break;this.addPage()}s(l,r,null,d)}.bind(this);if("CANVAS"===t.nodeName){var h=new Image;h.onload=d,h.src=t.toDataURL("image/png"),t=h}else d()}else{var p=Math.random().toString(35),m=[t,e,n,l,c,f,p,"SLOW"];this.addImage.apply(this,m),s(l,c,p,m)}}.bind(this),"undefined"!=typeof html2canvas&&!r.rstz)return html2canvas(t,r);if("undefined"!=typeof rasterizeHTML){var c="drawDocument";return"string"==typeof t&&(c=/^http/.test(t)?"drawURL":"drawHTML"),r.width=r.width||a*o,rasterizeHTML[c](t,void 0,r).then(function(t){r.onrendered(t.image)},function(t){s(null,t)})}return null}}(n.API),function(t){"use strict";var e="addImage_",n=["jpeg","jpg","png"],r=function(t){var e=this.internal.newObject(),n=this.internal.write,s=this.internal.putStream;if(t.n=e,n("<</Type /XObject"),n("/Subtype /Image"),n("/Width "+t.w),n("/Height "+t.h),t.cs===this.color_spaces.INDEXED?n("/ColorSpace [/Indexed /DeviceRGB "+(t.pal.length/3-1)+" "+("smask"in t?e+2:e+1)+" 0 R]"):(n("/ColorSpace /"+t.cs),t.cs===this.color_spaces.DEVICE_CMYK&&n("/Decode [1 0 1 0 1 0 1 0]")),n("/BitsPerComponent "+t.bpc),"f"in t&&n("/Filter /"+t.f),"dp"in t&&n("/DecodeParms <<"+t.dp+">>"),"trns"in t&&t.trns.constructor==Array){for(var i="",o=0,a=t.trns.length;a>o;o++)i+=t.trns[o]+" "+t.trns[o]+" ";n("/Mask ["+i+"]")}if("smask"in t&&n("/SMask "+(e+1)+" 0 R"),n("/Length "+t.data.length+">>"),s(t.data),n("endobj"),"smask"in t){var u="/Predictor 15 /Colors 1 /BitsPerComponent "+t.bpc+" /Columns "+t.w,c={w:t.w,h:t.h,cs:"DeviceGray",bpc:t.bpc,dp:u,data:t.smask};"f"in t&&(c.f=t.f),r.call(this,c)}t.cs===this.color_spaces.INDEXED&&(this.internal.newObject(),n("<< /Length "+t.pal.length+">>"),s(this.arrayBufferToBinaryString(new Uint8Array(t.pal))),n("endobj"))},s=function(){var t=this.internal.collections[e+"images"];for(var n in t)r.call(this,t[n])},i=function(){var t,n=this.internal.collections[e+"images"],r=this.internal.write;for(var s in n)t=n[s],r("/I"+t.i,t.n,"0","R")},o=function(e){return e&&"string"==typeof e&&(e=e.toUpperCase()),e in t.image_compression?e:t.image_compression.NONE},a=function(){var t=this.internal.collections[e+"images"];return t||(this.internal.collections[e+"images"]=t={},this.internal.events.subscribe("putResources",s),this.internal.events.subscribe("putXobjectDict",i)),t},u=function(t){var e=0;return t&&(e=Object.keys?Object.keys(t).length:function(t){var e=0;for(var n in t)t.hasOwnProperty(n)&&e++;return e}(t)),e},c=function(t){return"undefined"==typeof t||null===t},l=function(e){return"string"==typeof e&&t.sHashCode(e)},f=function(t){return-1===n.indexOf(t)},d=function(e){return"function"!=typeof t["process"+e.toUpperCase()]},h=function(t){return"object"==typeof t&&1===t.nodeType},p=function(t,e,n){if("IMG"===t.nodeName&&t.hasAttribute("src")){var r=""+t.getAttribute("src");if(!n&&0===r.indexOf("data:image/"))return r;!e&&/\.png(?:[?#].*)?$/i.test(r)&&(e="png")}if("CANVAS"===t.nodeName)var s=t;else{var s=document.createElement("canvas");s.width=t.clientWidth||t.width,s.height=t.clientHeight||t.height;var i=s.getContext("2d");if(!i)throw"addImage requires canvas to be supported by browser.";if(n){var o,a,u,c,l,f,d,h,p=Math.PI/180;"object"==typeof n&&(o=n.x,a=n.y,u=n.bg,n=n.angle),h=n*p,c=Math.abs(Math.cos(h)),l=Math.abs(Math.sin(h)),f=s.width,d=s.height,s.width=d*l+f*c,s.height=d*c+f*l,isNaN(o)&&(o=s.width/2),isNaN(a)&&(a=s.height/2),i.clearRect(0,0,s.width,s.height),i.fillStyle=u||"white",i.fillRect(0,0,s.width,s.height),i.save(),i.translate(o,a),i.rotate(h),i.drawImage(t,-(f/2),-(d/2)),i.rotate(-h),i.translate(-o,-a),i.restore()}else i.drawImage(t,0,0,s.width,s.height)}return s.toDataURL("png"==(""+e).toLowerCase()?"image/png":"image/jpeg")},m=function(t,e){var n;if(e)for(var r in e)if(t===e[r].alias){n=e[r];break}return n},w=function(t,e,n){return t||e||(t=-96,e=-96),0>t&&(t=-1*n.w*72/t/this.internal.scaleFactor),0>e&&(e=-1*n.h*72/e/this.internal.scaleFactor),0===t&&(t=e*n.w/n.h),0===e&&(e=t*n.h/n.w),[t,e]},g=function(t,e,n,r,s,i,o){var a=w.call(this,n,r,s),u=this.internal.getCoordinateString,c=this.internal.getVerticalCoordinateString;n=a[0],r=a[1],o[i]=s,this.internal.write("q",u(n),"0 0",u(r),u(t),c(e+r),"cm /I"+s.i,"Do Q")};t.color_spaces={DEVICE_RGB:"DeviceRGB",DEVICE_GRAY:"DeviceGray",DEVICE_CMYK:"DeviceCMYK",CAL_GREY:"CalGray",CAL_RGB:"CalRGB",LAB:"Lab",ICC_BASED:"ICCBased",INDEXED:"Indexed",PATTERN:"Pattern",SEPERATION:"Seperation",DEVICE_N:"DeviceN"},t.decode={DCT_DECODE:"DCTDecode",FLATE_DECODE:"FlateDecode",LZW_DECODE:"LZWDecode",JPX_DECODE:"JPXDecode",JBIG2_DECODE:"JBIG2Decode",ASCII85_DECODE:"ASCII85Decode",ASCII_HEX_DECODE:"ASCIIHexDecode",RUN_LENGTH_DECODE:"RunLengthDecode",CCITT_FAX_DECODE:"CCITTFaxDecode"},t.image_compression={NONE:"NONE",FAST:"FAST",MEDIUM:"MEDIUM",SLOW:"SLOW"},t.sHashCode=function(t){return Array.prototype.reduce&&t.split("").reduce(function(t,e){return t=(t<<5)-t+e.charCodeAt(0),t&t},0)},t.isString=function(t){return"string"==typeof t},t.extractInfoFromBase64DataURI=function(t){return/^data:([\w]+?\/([\w]+?));base64,(.+?)$/g.exec(t)},t.supportsArrayBuffer=function(){return"undefined"!=typeof ArrayBuffer&&"undefined"!=typeof Uint8Array},t.isArrayBuffer=function(t){return this.supportsArrayBuffer()?t instanceof ArrayBuffer:!1},t.isArrayBufferView=function(t){return this.supportsArrayBuffer()?"undefined"==typeof Uint32Array?!1:t instanceof Int8Array||t instanceof Uint8Array||"undefined"!=typeof Uint8ClampedArray&&t instanceof Uint8ClampedArray||t instanceof Int16Array||t instanceof Uint16Array||t instanceof Int32Array||t instanceof Uint32Array||t instanceof Float32Array||t instanceof Float64Array:!1},t.binaryStringToUint8Array=function(t){for(var e=t.length,n=new Uint8Array(e),r=0;e>r;r++)n[r]=t.charCodeAt(r);return n},t.arrayBufferToBinaryString=function(t){this.isArrayBuffer(t)&&(t=new Uint8Array(t));for(var e="",n=t.byteLength,r=0;n>r;r++)e+=String.fromCharCode(t[r]);return e},t.arrayBufferToBase64=function(t){for(var e,n,r,s,i,o="",a="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",u=new Uint8Array(t),c=u.byteLength,l=c%3,f=c-l,d=0;f>d;d+=3)i=u[d]<<16|u[d+1]<<8|u[d+2],e=(16515072&i)>>18,n=(258048&i)>>12,r=(4032&i)>>6,s=63&i,o+=a[e]+a[n]+a[r]+a[s];return 1==l?(i=u[f],e=(252&i)>>2,n=(3&i)<<4,o+=a[e]+a[n]+"=="):2==l&&(i=u[f]<<8|u[f+1],e=(64512&i)>>10,n=(1008&i)>>4,r=(15&i)<<2,o+=a[e]+a[n]+a[r]+"="),o},t.createImageInfo=function(t,e,n,r,s,i,o,a,u,c,l,f){var d={alias:a,w:e,h:n,cs:r,bpc:s,i:o,data:t};return i&&(d.f=i),u&&(d.dp=u),c&&(d.trns=c),l&&(d.pal=l),f&&(d.smask=f),d},t.addImage=function(t,e,r,s,i,w,y,v,b){if("string"!=typeof e){var q=w;w=i,i=s,s=r,r=e,e=q}if("object"==typeof t&&!h(t)&&"imageData"in t){var x=t;t=x.imageData,e=x.format||e,r=x.x||r||0,s=x.y||s||0,i=x.w||i,w=x.h||w,y=x.alias||y,v=x.compression||v,b=x.rotation||x.angle||b}if(isNaN(r)||isNaN(s))throw console.error("jsPDF.addImage: Invalid coordinates",arguments),new Error("Invalid coordinates passed to jsPDF.addImage");var k,_=a.call(this);if(!(k=m(t,_))){var A;if(h(t)&&(t=p(t,e,b)),c(y)&&(y=l(t)),!(k=m(y,_))){if(this.isString(t)){var C=this.extractInfoFromBase64DataURI(t);C?(e=C[2],t=atob(C[3])):137===t.charCodeAt(0)&&80===t.charCodeAt(1)&&78===t.charCodeAt(2)&&71===t.charCodeAt(3)&&(e="png")}if(e=(e||"JPEG").toLowerCase(),f(e))throw new Error("addImage currently only supports formats "+n+", not '"+e+"'");if(d(e))throw new Error("please ensure that the plugin for '"+e+"' support is added");if(this.supportsArrayBuffer()&&(A=t,t=this.binaryStringToUint8Array(t)),k=this["process"+e.toUpperCase()](t,u(_),y,o(v),A),!k)throw new Error("An unkwown error occurred whilst processing the image")}}return g.call(this,r,s,i,w,k,k.i,_),this};var y=function(t){var e,n,r;if(255===!t.charCodeAt(0)||216===!t.charCodeAt(1)||255===!t.charCodeAt(2)||224===!t.charCodeAt(3)||!t.charCodeAt(6)==="J".charCodeAt(0)||!t.charCodeAt(7)==="F".charCodeAt(0)||!t.charCodeAt(8)==="I".charCodeAt(0)||!t.charCodeAt(9)==="F".charCodeAt(0)||0===!t.charCodeAt(10))throw new Error("getJpegSize requires a binary string jpeg file");for(var s=256*t.charCodeAt(4)+t.charCodeAt(5),i=4,o=t.length;o>i;){if(i+=s,255!==t.charCodeAt(i))throw new Error("getJpegSize could not find the size of the image");if(192===t.charCodeAt(i+1)||193===t.charCodeAt(i+1)||194===t.charCodeAt(i+1)||195===t.charCodeAt(i+1)||196===t.charCodeAt(i+1)||197===t.charCodeAt(i+1)||198===t.charCodeAt(i+1)||199===t.charCodeAt(i+1))return n=256*t.charCodeAt(i+5)+t.charCodeAt(i+6),e=256*t.charCodeAt(i+7)+t.charCodeAt(i+8),r=t.charCodeAt(i+9),[e,n,r];i+=2,s=256*t.charCodeAt(i)+t.charCodeAt(i+1)}},v=function(t){var e=t[0]<<8|t[1];if(65496!==e)throw new Error("Supplied data is not a JPEG");for(var n,r,s,i,o=t.length,a=(t[4]<<8)+t[5],u=4;o>u;){if(u+=a,n=b(t,u),a=(n[2]<<8)+n[3],(192===n[1]||194===n[1])&&255===n[0]&&a>7)return n=b(t,u+5),r=(n[2]<<8)+n[3],s=(n[0]<<8)+n[1],i=n[4],{width:r,height:s,numcomponents:i};u+=2}throw new Error("getJpegSizeFromBytes could not find the size of the image")},b=function(t,e){return t.subarray(e,e+5)};t.processJPEG=function(t,e,n,r,s){var i,o=this.color_spaces.DEVICE_RGB,a=this.decode.DCT_DECODE,u=8;return this.isString(t)?(i=y(t),this.createImageInfo(t,i[0],i[1],1==i[3]?this.color_spaces.DEVICE_GRAY:o,u,a,e,n)):(this.isArrayBuffer(t)&&(t=new Uint8Array(t)),this.isArrayBufferView(t)?(i=v(t),t=s||this.arrayBufferToBinaryString(t),this.createImageInfo(t,i.width,i.height,1==i.numcomponents?this.color_spaces.DEVICE_GRAY:o,u,a,e,n)):null)},t.processJPG=function(){return this.processJPEG.apply(this,arguments)}}(n.API),function(t){"use strict";t.autoPrint=function(){var t;return this.internal.events.subscribe("postPutResources",function(){t=this.internal.newObject(),this.internal.write("<< /S/Named /Type/Action /N/Print >>","endobj")}),this.internal.events.subscribe("putCatalog",function(){this.internal.write("/OpenAction "+t+" 0 R")}),this}}(n.API),function(t){"use strict";var e,n,r,s,i=3,o=13,a={x:void 0,y:void 0,w:void 0,h:void 0,ln:void 0},u=1,c=function(t,e,n,r,s){a={x:t,y:e,w:n,h:r,ln:s}},l=function(){return a},f={left:0,top:0,bottom:0};t.setHeaderFunction=function(t){s=t},t.getTextDimensions=function(t){e=this.internal.getFont().fontName,n=this.table_font_size||this.internal.getFontSize(),r=this.internal.getFont().fontStyle;var s,i,o=19.049976/25.4;return i=document.createElement("font"),i.id="jsPDFCell",i.style.fontStyle=r,i.style.fontName=e,i.style.fontSize=n+"pt",i.textContent=t,document.body.appendChild(i),s={w:(i.offsetWidth+1)*o,h:(i.offsetHeight+1)*o},document.body.removeChild(i),s},t.cellAddPage=function(){var t=this.margins||f;this.addPage(),c(t.left,t.top,void 0,void 0),u+=1},t.cellInitialize=function(){a={x:void 0,y:void 0,w:void 0,h:void 0,ln:void 0},u=1},t.cell=function(t,e,n,r,s,a,u){var d=l();if(void 0!==d.ln)if(d.ln===a)t=d.x+d.w,e=d.y;else{var h=this.margins||f;d.y+d.h+r+o>=this.internal.pageSize.height-h.bottom&&(this.cellAddPage(),this.printHeaders&&this.tableHeaderRow&&this.printHeaderRow(a,!0)),e=l().y+l().h}if(void 0!==s[0])if(this.printingHeaderRow?this.rect(t,e,n,r,"FD"):this.rect(t,e,n,r),"right"===u){if(s instanceof Array)for(var p=0;p<s.length;p++){var m=s[p],w=this.getStringUnitWidth(m)*this.internal.getFontSize();this.text(m,t+n-w-i,e+this.internal.getLineHeight()*(p+1))}}else this.text(s,t+i,e+this.internal.getLineHeight());return c(t,e,n,r,a),this},t.arrayMax=function(t,e){var n,r,s,i=t[0];for(n=0,r=t.length;r>n;n+=1)s=t[n],e?-1===e(i,s)&&(i=s):s>i&&(i=s);return i},t.table=function(e,n,r,s,i){if(!r)throw"No data for PDF table";var o,c,l,d,h,p,m,w,g,y,v=[],b=[],q={},x={},k=[],_=[],A=!1,C=!0,S=12,E=f;if(E.width=this.internal.pageSize.width,i&&(i.autoSize===!0&&(A=!0),i.printHeaders===!1&&(C=!1),i.fontSize&&(S=i.fontSize),i.margins&&(E=i.margins)),this.lnMod=0,a={x:void 0,y:void 0,w:void 0,h:void 0,ln:void 0},u=1,this.printHeaders=C,this.margins=E,this.setFontSize(S),this.table_font_size=S,void 0===s||null===s)v=Object.keys(r[0]);else if(s[0]&&"string"!=typeof s[0]){var z=19.049976/25.4;for(c=0,l=s.length;l>c;c+=1)o=s[c],v.push(o.name),b.push(o.prompt),x[o.name]=o.width*z}else v=s;if(A)for(y=function(t){return t[o]},c=0,l=v.length;l>c;c+=1){for(o=v[c],q[o]=r.map(y),k.push(this.getTextDimensions(b[c]||o).w),p=q[o],m=0,d=p.length;d>m;m+=1)h=p[m],k.push(this.getTextDimensions(h).w);x[o]=t.arrayMax(k)}if(C){var T=this.calculateLineHeight(v,x,b.length?b:v);for(c=0,l=v.length;l>c;c+=1)o=v[c],_.push([e,n,x[o],T,String(b.length?b[c]:o)]);this.setTableHeaderRow(_),this.printHeaderRow(1,!1)}for(c=0,l=r.length;l>c;c+=1){var T;for(w=r[c],T=this.calculateLineHeight(v,x,w),m=0,g=v.length;g>m;m+=1)o=v[m],this.cell(e,n,x[o],T,w[o],c+2,o.align)}return this.lastCellPos=a,this.table_x=e,this.table_y=n,this},t.calculateLineHeight=function(t,e,n){for(var r,s=0,o=0;o<t.length;o++){r=t[o],n[r]=this.splitTextToSize(String(n[r]),e[r]-i);var a=this.internal.getLineHeight()*n[r].length+i;a>s&&(s=a)}return s},t.setTableHeaderRow=function(t){this.tableHeaderRow=t},t.printHeaderRow=function(t,e){if(!this.tableHeaderRow)throw"Property tableHeaderRow does not exist.";var n,r,i,o;if(this.printingHeaderRow=!0,void 0!==s){var a=s(this,u);c(a[0],a[1],a[2],a[3],-1)}this.setFontStyle("bold");var l=[];for(i=0,o=this.tableHeaderRow.length;o>i;i+=1)this.setFillColor(200,200,200),n=this.tableHeaderRow[i],e&&(n[1]=this.margins&&this.margins.top||0,l.push(n)),r=[].concat(n),this.cell.apply(this,r.concat(t));l.length>0&&this.setTableHeaderRow(l),this.setFontStyle("normal"),this.printingHeaderRow=!1}}(n.API),function(t){var e,n,r,s,i,o,a,u,c,l,f,d,h,p,m,w,g,y,v;e=function(){function t(){}return function(e){return t.prototype=e,new t}}(),c=function(t){var e,n,r,s,i,o,a;for(n=0,r=t.length,e=void 0,s=!1,o=!1;!s&&n!==r;)e=t[n]=t[n].trimLeft(),e&&(s=!0),n++;for(n=r-1;r&&!o&&-1!==n;)e=t[n]=t[n].trimRight(),e&&(o=!0),n--;for(i=/\s+$/g,a=!0,n=0;n!==r;)e=t[n].replace(/\s+/g," "),a&&(e=e.trimLeft()),e&&(a=i.test(e)),t[n]=e,n++;return t},l=function(t,e,n,r){return this.pdf=t,this.x=e,this.y=n,this.settings=r,this.watchFunctions=[],this.init(),this},f=function(t){var e,n,s;for(e=void 0,s=t.split(","),n=s.shift();!e&&n;)e=r[n.trim().toLowerCase()],n=s.shift();return e},d=function(t){t="auto"===t?"0px":t,t.indexOf("em")>-1&&!isNaN(Number(t.replace("em","")))&&(t=18.719*Number(t.replace("em",""))+"px"),t.indexOf("pt")>-1&&!isNaN(Number(t.replace("pt","")))&&(t=1.333*Number(t.replace("pt",""))+"px");var e,n,r;return n=void 0,e=16,(r=h[t])?r:(r={"xx-small":9,"x-small":11,small:13,medium:16,large:19,"x-large":23,"xx-large":28,auto:0}[{css_line_height_string:t}],r!==n?h[t]=r/e:(r=parseFloat(t))?h[t]=r/e:(r=t.match(/([\d\.]+)(px)/),h[t]=3===r.length?parseFloat(r[1])/e:1))},u=function(t){var e,n,r;return r=function(t){var e;return e=function(t){return document.defaultView&&document.defaultView.getComputedStyle?document.defaultView.getComputedStyle(t,null):t.currentStyle?t.currentStyle:t.style}(t),function(t){return t=t.replace(/-\D/g,function(t){return t.charAt(1).toUpperCase()}),e[t]}}(t),e={},n=void 0,e["font-family"]=f(r("font-family"))||"times",e["font-style"]=s[r("font-style")]||"normal",e["text-align"]=TextAlignMap[r("text-align")]||"left",n=i[r("font-weight")]||"normal","bold"===n&&(e["font-style"]="normal"===e["font-style"]?n:n+e["font-style"]),e["font-size"]=d(r("font-size"))||1,e["line-height"]=d(r("line-height"))||1,e.display="inline"===r("display")?"inline":"block",n="block"===e.display,e["margin-top"]=n&&d(r("margin-top"))||0,e["margin-bottom"]=n&&d(r("margin-bottom"))||0,e["padding-top"]=n&&d(r("padding-top"))||0,e["padding-bottom"]=n&&d(r("padding-bottom"))||0,e["margin-left"]=n&&d(r("margin-left"))||0,e["margin-right"]=n&&d(r("margin-right"))||0,e["padding-left"]=n&&d(r("padding-left"))||0,e["padding-right"]=n&&d(r("padding-right"))||0,e["float"]=o[r("cssFloat")]||"none",e.clear=a[r("clear")]||"none",e},p=function(t,e,n){var r,s,i,o,a;if(i=!1,s=void 0,o=void 0,a=void 0,r=n["#"+t.id])if("function"==typeof r)i=r(t,e);else for(s=0,o=r.length;!i&&s!==o;)i=r[s](t,e),s++;if(r=n[t.nodeName],!i&&r)if("function"==typeof r)i=r(t,e);else for(s=0,o=r.length;!i&&s!==o;)i=r[s](t,e),s++;return i},v=function(t,e){var n,r,s,i,o,a,u,c,l,f; +for(n=[],r=[],s=0,f=t.rows[0].cells.length,c=t.clientWidth;f>s;)l=t.rows[0].cells[s],r[s]={name:l.textContent.toLowerCase().replace(/\s+/g,""),prompt:l.textContent.replace(/\r?\n/g,""),width:l.clientWidth/c*e.pdf.internal.pageSize.width},s++;for(s=1;s<t.rows.length;){for(a=t.rows[s],o={},i=0;i<a.cells.length;)o[r[i].name]=a.cells[i].textContent.replace(/\r?\n/g,""),i++;n.push(o),s++}return u={rows:n,headers:r}};var b={SCRIPT:1,STYLE:1,NOSCRIPT:1,OBJECT:1,EMBED:1,SELECT:1},q=1;n=function(t,e,r){var s,i,o,a,c,l,f,d,h;for(i=t.childNodes,s=void 0,o=u(t),c="block"===o.display,c&&(e.setBlockBoundary(),e.setBlockStyle(o)),f=19.049976/25.4,a=0,l=i.length;l>a;){if(s=i[a],"object"==typeof s){if(e.executeWatchFunctions(s),1===s.nodeType&&"HEADER"===s.nodeName){var w=s,g=e.pdf.margins_doc.top;e.pdf.internal.events.subscribe("addPage",function(){e.y=g,n(w,e,r),e.pdf.margins_doc.top=e.y+10,e.y+=10},!1)}if(8===s.nodeType&&"#comment"===s.nodeName)~s.textContent.indexOf("ADD_PAGE")&&(e.pdf.addPage(),e.y=e.pdf.margins_doc.top);else if(1!==s.nodeType||b[s.nodeName])if(3===s.nodeType){var y=s.nodeValue;if(s.nodeValue&&"LI"===s.parentNode.nodeName)if("OL"===s.parentNode.parentNode.nodeName)y=q++ +". "+y;else{var x=16*o["font-size"],k=2;x>20&&(k=3),h=function(t,e){this.pdf.circle(t,e,k,"FD")}}e.addText(y,o)}else"string"==typeof s&&e.addText(s,o);else{var _;if("IMG"===s.nodeName){var A=s.getAttribute("src");_=m[e.pdf.sHashCode(A)||A]}if(_){e.pdf.internal.pageSize.height-e.pdf.margins_doc.bottom<e.y+s.height&&e.y>e.pdf.margins_doc.top&&(e.pdf.addPage(),e.y=e.pdf.margins_doc.top,e.executeWatchFunctions(s));var C=u(s),S=e.x,E=12/e.pdf.internal.scaleFactor,z=(C["margin-left"]+C["padding-left"])*E,T=(C["margin-right"]+C["padding-right"])*E,I=(C["margin-top"]+C["padding-top"])*E,B=(C["margin-bottom"]+C["padding-bottom"])*E;S+=void 0!==C["float"]&&"right"===C["float"]?e.settings.width-s.width-T:z,e.pdf.addImage(_,S,e.y+I,s.width,s.height),_=void 0,"right"===C["float"]||"left"===C["float"]?(e.watchFunctions.push(function(t,n,r,s){return e.y>=n?(e.x+=t,e.settings.width+=r,!0):s&&1===s.nodeType&&!b[s.nodeName]&&e.x+s.width>e.pdf.margins_doc.left+e.pdf.margins_doc.width?(e.x+=t,e.y=n,e.settings.width+=r,!0):!1}.bind(this,"left"===C["float"]?-s.width-z-T:0,e.y+s.height+I+B,s.width)),e.watchFunctions.push(function(t,n,r){return e.y<t&&n===e.pdf.internal.getNumberOfPages()?1===r.nodeType&&"both"===u(r).clear?(e.y=t,!0):!1:!0}.bind(this,e.y+s.height,e.pdf.internal.getNumberOfPages())),e.settings.width-=s.width+z+T,"left"===C["float"]&&(e.x+=s.width+z+T)):e.y+=s.height+B}else if("TABLE"===s.nodeName)d=v(s,e),e.y+=10,e.pdf.table(e.x,e.y,d.rows,d.headers,{autoSize:!1,printHeaders:!0,margins:e.pdf.margins_doc}),e.y=e.pdf.lastCellPos.y+e.pdf.lastCellPos.h+20;else if("OL"===s.nodeName||"UL"===s.nodeName)q=1,p(s,e,r)||n(s,e,r),e.y+=10;else if("LI"===s.nodeName){var O=e.x;e.x+="UL"===s.parentNode.nodeName?22:10,e.y+=3,p(s,e,r)||n(s,e,r),e.x=O}else"BR"===s.nodeName?e.y+=o["font-size"]*e.pdf.internal.scaleFactor:p(s,e,r)||n(s,e,r)}}a++}return c?e.setBlockBoundary(h):void 0},m={},w=function(t,e,n,r){function s(){e.pdf.internal.events.publish("imagesLoaded"),r(o)}function i(t,n,r){if(t){var i=new Image;o=++c,i.crossOrigin="",i.onerror=i.onload=function(){if(i.complete&&(0===i.src.indexOf("data:image/")&&(i.width=n||i.width||0,i.height=r||i.height||0),i.width+i.height)){var o=e.pdf.sHashCode(t)||t;m[o]=m[o]||i}--c||s()},i.src=t}}for(var o,a=t.getElementsByTagName("img"),u=a.length,c=0;u--;)i(a[u].getAttribute("src"),a[u].width,a[u].height);return c||s()},g=function(t,e,r){var s=t.getElementsByTagName("footer");if(s.length>0){s=s[0];var i=e.pdf.internal.write,o=e.y;e.pdf.internal.write=function(){},n(s,e,r);var a=Math.ceil(e.y-o)+5;e.y=o,e.pdf.internal.write=i,e.pdf.margins_doc.bottom+=a;for(var u=function(t){var i=void 0!==t?t.pageNumber:1,o=e.y;e.y=e.pdf.internal.pageSize.height-e.pdf.margins_doc.bottom,e.pdf.margins_doc.bottom-=a;for(var u=s.getElementsByTagName("span"),c=0;c<u.length;++c)(" "+u[c].className+" ").replace(/[\n\t]/g," ").indexOf(" pageCounter ")>-1&&(u[c].innerHTML=i),(" "+u[c].className+" ").replace(/[\n\t]/g," ").indexOf(" totalPages ")>-1&&(u[c].innerHTML="###jsPDFVarTotalPages###");n(s,e,r),e.pdf.margins_doc.bottom+=a,e.y=o},c=s.getElementsByTagName("span"),l=0;l<c.length;++l)(" "+c[l].className+" ").replace(/[\n\t]/g," ").indexOf(" totalPages ")>-1&&e.pdf.internal.events.subscribe("htmlRenderingFinished",e.pdf.putTotalPages.bind(e.pdf,"###jsPDFVarTotalPages###"),!0);e.pdf.internal.events.subscribe("addPage",u,!1),u(),b.FOOTER=1}},y=function(t,e,r,s,i,o){if(!e)return!1;"string"==typeof e||e.parentNode||(e=""+e.innerHTML),"string"==typeof e&&(e=function(t){var e,n,r,s;return r="jsPDFhtmlText"+Date.now().toString()+(1e3*Math.random()).toFixed(0),s="position: absolute !important;clip: rect(1px 1px 1px 1px); /* IE6, IE7 */clip: rect(1px, 1px, 1px, 1px);padding:0 !important;border:0 !important;height: 1px !important;width: 1px !important; top:auto;left:-100px;overflow: hidden;",n=document.createElement("div"),n.style.cssText=s,n.innerHTML='<iframe style="height:1px;width:1px" name="'+r+'" />',document.body.appendChild(n),e=window.frames[r],e.document.body.innerHTML=t,e.document.body}(e.replace(/<\/?script[^>]*?>/gi,"")));var a,u=new l(t,r,s,i);return w.call(this,e,u,i.elementHandlers,function(t){g(e,u,i.elementHandlers),n(e,u,i.elementHandlers),u.pdf.internal.events.publish("htmlRenderingFinished"),a=u.dispose(),"function"==typeof o?o(a):t&&console.error("jsPDF Warning: rendering issues? provide a callback to fromHTML!")}),a||{x:u.x,y:u.y}},l.prototype.init=function(){return this.paragraph={text:[],style:[]},this.pdf.internal.write("q")},l.prototype.dispose=function(){return this.pdf.internal.write("Q"),{x:this.x,y:this.y,ready:!0}},l.prototype.executeWatchFunctions=function(t){var e=!1,n=[];if(this.watchFunctions.length>0){for(var r=0;r<this.watchFunctions.length;++r)this.watchFunctions[r](t)===!0?e=!0:n.push(this.watchFunctions[r]);this.watchFunctions=n}return e},l.prototype.splitFragmentsIntoLines=function(t,n){var r,s,i,o,a,u,c,l,f,d,h,p,m,w,g;for(s=12,h=this.pdf.internal.scaleFactor,a={},i=void 0,d=void 0,o=void 0,u=void 0,g=void 0,f=void 0,l=void 0,c=void 0,p=[],m=[p],r=0,w=this.settings.width;t.length;)if(u=t.shift(),g=n.shift(),u)if(i=g["font-family"],d=g["font-style"],o=a[i+d],o||(o=this.pdf.internal.getFont(i,d).metadata.Unicode,a[i+d]=o),f={widths:o.widths,kerning:o.kerning,fontSize:g["font-size"]*s,textIndent:r},l=this.pdf.getStringUnitWidth(u,f)*f.fontSize/h,r+l>w){for(c=this.pdf.splitTextToSize(u,w,f),p.push([c.shift(),g]);c.length;)p=[[c.shift(),g]],m.push(p);r=this.pdf.getStringUnitWidth(p[0][0],f)*f.fontSize/h}else p.push([u,g]),r+=l;if(void 0!==g["text-align"]&&("center"===g["text-align"]||"right"===g["text-align"]||"justify"===g["text-align"]))for(var y=0;y<m.length;++y){var v=this.pdf.getStringUnitWidth(m[y][0][0],f)*f.fontSize/h;y>0&&(m[y][0][1]=e(m[y][0][1]));var b=w-v;if("right"===g["text-align"])m[y][0][1]["margin-left"]=b;else if("center"===g["text-align"])m[y][0][1]["margin-left"]=b/2;else if("justify"===g["text-align"]){var q=m[y][0][0].split(" ").length-1;m[y][0][1]["word-spacing"]=b/q,y===m.length-1&&(m[y][0][1]["word-spacing"]=0)}}return m},l.prototype.RenderTextFragment=function(t,e){var n,r,s;s=0,n=12,this.pdf.internal.pageSize.height-this.pdf.margins_doc.bottom<this.y+this.pdf.internal.getFontSize()&&(this.pdf.internal.write("ET","Q"),this.pdf.addPage(),this.y=this.pdf.margins_doc.top,this.pdf.internal.write("q","BT 0 g",this.pdf.internal.getCoordinateString(this.x),this.pdf.internal.getVerticalCoordinateString(this.y),"Td"),s=Math.max(s,e["line-height"],e["font-size"]),this.pdf.internal.write(0,(-1*n*s).toFixed(2),"Td")),r=this.pdf.internal.getFont(e["font-family"],e["font-style"]),void 0!==e["word-spacing"]&&e["word-spacing"]>0&&this.pdf.internal.write(e["word-spacing"].toFixed(2),"Tw"),this.pdf.internal.write("/"+r.id,(n*e["font-size"]).toFixed(2),"Tf","("+this.pdf.internal.pdfEscape(t)+") Tj"),void 0!==e["word-spacing"]&&this.pdf.internal.write(0,"Tw")},l.prototype.renderParagraph=function(t){var e,n,r,s,i,o,a,u,l,f,d,h,p,m,w;if(s=c(this.paragraph.text),m=this.paragraph.style,e=this.paragraph.blockstyle,p=this.paragraph.blockstyle||{},this.paragraph={text:[],style:[],blockstyle:{},priorblockstyle:e},s.join("").trim()){u=this.splitFragmentsIntoLines(s,m),a=void 0,l=void 0,n=12,r=n/this.pdf.internal.scaleFactor,h=(Math.max((e["margin-top"]||0)-(p["margin-bottom"]||0),0)+(e["padding-top"]||0))*r,d=((e["margin-bottom"]||0)+(e["padding-bottom"]||0))*r,f=this.pdf.internal.write,i=void 0,o=void 0,this.y+=h,f("q","BT 0 g",this.pdf.internal.getCoordinateString(this.x),this.pdf.internal.getVerticalCoordinateString(this.y),"Td");for(var g=0;u.length;){for(a=u.shift(),l=0,i=0,o=a.length;i!==o;)a[i][0].trim()&&(l=Math.max(l,a[i][1]["line-height"],a[i][1]["font-size"]),w=7*a[i][1]["font-size"]),i++;var y=0;for(void 0!==a[0][1]["margin-left"]&&a[0][1]["margin-left"]>0&&(wantedIndent=this.pdf.internal.getCoordinateString(a[0][1]["margin-left"]),y=wantedIndent-g,g=wantedIndent),f(y,(-1*n*l).toFixed(2),"Td"),i=0,o=a.length;i!==o;)a[i][0]&&this.RenderTextFragment(a[i][0],a[i][1]),i++;if(this.y+=l*r,this.executeWatchFunctions(a[0][1])&&u.length>0){var v=[],b=[];u.forEach(function(t){for(var e=0,n=t.length;e!==n;)t[e][0]&&(v.push(t[e][0]+" "),b.push(t[e][1])),++e}),u=this.splitFragmentsIntoLines(c(v),b),f("ET","Q"),f("q","BT 0 g",this.pdf.internal.getCoordinateString(this.x),this.pdf.internal.getVerticalCoordinateString(this.y),"Td")}}return t&&"function"==typeof t&&t.call(this,this.x-9,this.y-w/2),f("ET","Q"),this.y+=d}},l.prototype.setBlockBoundary=function(t){return this.renderParagraph(t)},l.prototype.setBlockStyle=function(t){return this.paragraph.blockstyle=t},l.prototype.addText=function(t,e){return this.paragraph.text.push(t),this.paragraph.style.push(e)},r={helvetica:"helvetica","sans-serif":"helvetica","times new roman":"times",serif:"times",times:"times",monospace:"courier",courier:"courier"},i={100:"normal",200:"normal",300:"normal",400:"normal",500:"bold",600:"bold",700:"bold",800:"bold",900:"bold",normal:"normal",bold:"bold",bolder:"bold",lighter:"normal"},s={normal:"normal",italic:"italic",oblique:"italic"},TextAlignMap={left:"left",right:"right",center:"center",justify:"justify"},o={none:"none",right:"right",left:"left"},a={none:"none",both:"both"},h={normal:1},t.fromHTML=function(t,e,n,r,s,i){"use strict";return this.margins_doc=i||{top:0,bottom:0},r||(r={}),r.elementHandlers||(r.elementHandlers={}),y(this,t,isNaN(e)?4:e,isNaN(n)?4:n,r,s)}}(n.API),function(t){"use strict";var e,n,r;t.addJS=function(t){return r=t,this.internal.events.subscribe("postPutResources",function(){e=this.internal.newObject(),this.internal.write("<< /Names [(EmbeddedJS) "+(e+1)+" 0 R] >>","endobj"),n=this.internal.newObject(),this.internal.write("<< /S /JavaScript /JS (",r,") >>","endobj")}),this.internal.events.subscribe("putCatalog",function(){void 0!==e&&void 0!==n&&this.internal.write("/Names <</JavaScript "+e+" 0 R>>")}),this}}(n.API),function(t){"use strict";var e=function(){return"function"!=typeof PNG||"function"!=typeof o},n=function(e){return e!==t.image_compression.NONE&&r()},r=function(){var t="function"==typeof s;if(!t)throw new Error("requires deflate.js for compression");return t},i=function(e,n,r,i){var o=5,l=d;switch(i){case t.image_compression.FAST:o=3,l=f;break;case t.image_compression.MEDIUM:o=6,l=h;break;case t.image_compression.SLOW:o=9,l=p}e=c(e,n,r,l);var m=new Uint8Array(a(o)),w=u(e),g=new s(o),y=g.append(e),v=g.flush(),b=m.length+y.length+v.length,q=new Uint8Array(b+4);return q.set(m),q.set(y,m.length),q.set(v,m.length+y.length),q[b++]=w>>>24&255,q[b++]=w>>>16&255,q[b++]=w>>>8&255,q[b++]=255&w,t.arrayBufferToBinaryString(q)},a=function(t,e){var n=8,r=Math.LOG2E*Math.log(32768)-8,s=r<<4|n,i=s<<8,o=Math.min(3,(e-1&255)>>1);return i|=o<<6,i|=0,i+=31-i%31,[s,255&i&255]},u=function(t,e){for(var n,r=1,s=65535&r,i=r>>>16&65535,o=t.length,a=0;o>0;){n=o>e?e:o,o-=n;do s+=t[a++],i+=s;while(--n);s%=65521,i%=65521}return(i<<16|s)>>>0},c=function(t,e,n,r){for(var s,i,o,a=t.length/e,u=new Uint8Array(t.length+a),c=w(),l=0;a>l;l++){if(o=l*e,s=t.subarray(o,o+e),r)u.set(r(s,n,i),o+l);else{for(var f=0,d=c.length,h=[];d>f;f++)h[f]=c[f](s,n,i);var p=g(h.concat());u.set(h[p],o+l)}i=s}return u},l=function(t){var e=Array.apply([],t);return e.unshift(0),e},f=function(t,e){var n,r=[],s=0,i=t.length;for(r[0]=1;i>s;s++)n=t[s-e]||0,r[s+1]=t[s]-n+256&255;return r},d=function(t,e,n){var r,s=[],i=0,o=t.length;for(s[0]=2;o>i;i++)r=n&&n[i]||0,s[i+1]=t[i]-r+256&255;return s},h=function(t,e,n){var r,s,i=[],o=0,a=t.length;for(i[0]=3;a>o;o++)r=t[o-e]||0,s=n&&n[o]||0,i[o+1]=t[o]+256-(r+s>>>1)&255;return i},p=function(t,e,n){var r,s,i,o,a=[],u=0,c=t.length;for(a[0]=4;c>u;u++)r=t[u-e]||0,s=n&&n[u]||0,i=n&&n[u-e]||0,o=m(r,s,i),a[u+1]=t[u]-o+256&255;return a},m=function(t,e,n){var r=t+e-n,s=Math.abs(r-t),i=Math.abs(r-e),o=Math.abs(r-n);return i>=s&&o>=s?t:o>=i?e:n},w=function(){return[l,f,d,h,p]},g=function(t){for(var e,n,r,s=0,i=t.length;i>s;)e=y(t[s].slice(1)),(n>e||!n)&&(n=e,r=s),s++;return r},y=function(t){for(var e=0,n=t.length,r=0;n>e;)r+=Math.abs(t[e++]);return r};t.processPNG=function(t,r,s,o){var a,u,c,l,f,d,h=this.color_spaces.DEVICE_RGB,p=this.decode.FLATE_DECODE,m=8;if(this.isArrayBuffer(t)&&(t=new Uint8Array(t)),this.isArrayBufferView(t)){if(e())throw new Error("PNG support requires png.js and zlib.js");if(a=new PNG(t),t=a.imgData,m=a.bits,h=a.colorSpace,l=a.colors,-1!==[4,6].indexOf(a.colorType)){if(8===a.bits)for(var w,g,y=window["Uint"+a.pixelBitlength+"Array"],v=new y(a.decodePixels().buffer),b=v.length,q=new Uint8Array(b*a.colors),x=new Uint8Array(b),k=a.pixelBitlength-a.bits,_=0,A=0;b>_;_++){for(w=v[_],g=0;k>g;)q[A++]=w>>>g&255,g+=a.bits;x[_]=w>>>g&255}if(16===a.bits){for(var w,v=new Uint32Array(a.decodePixels().buffer),b=v.length,q=new Uint8Array(b*(32/a.pixelBitlength)*a.colors),x=new Uint8Array(b*(32/a.pixelBitlength)),C=a.colors>1,_=0,A=0,S=0;b>_;)w=v[_++],q[A++]=w>>>0&255,C&&(q[A++]=w>>>16&255,w=v[_++],q[A++]=w>>>0&255),x[S++]=w>>>16&255;m=8}n(o)?(t=i(q,a.width*a.colors,a.colors,o),d=i(x,a.width,1,o)):(t=q,d=x,p=null)}if(3===a.colorType&&(h=this.color_spaces.INDEXED,f=a.palette,a.transparency.indexed)){for(var E=a.transparency.indexed,z=0,_=0,b=E.length;b>_;++_)z+=E[_];if(z/=255,z===b-1&&-1!==E.indexOf(0))c=[E.indexOf(0)];else if(z!==b){for(var v=a.decodePixels(),x=new Uint8Array(v.length),_=0,b=v.length;b>_;_++)x[_]=E[v[_]];d=i(x,a.width,1)}}return u=p===this.decode.FLATE_DECODE?"/Predictor 15 /Colors "+l+" /BitsPerComponent "+m+" /Columns "+a.width:"/Colors "+l+" /BitsPerComponent "+m+" /Columns "+a.width,(this.isArrayBuffer(t)||this.isArrayBufferView(t))&&(t=this.arrayBufferToBinaryString(t)),(d&&this.isArrayBuffer(d)||this.isArrayBufferView(d))&&(d=this.arrayBufferToBinaryString(d)),this.createImageInfo(t,a.width,a.height,h,m,p,r,s,u,c,f,d)}throw new Error("Unsupported PNG image data, try using JPEG instead.")}}(n.API),function(t){"use strict";t.addSVG=function(t,e,n,r,s){function i(t,e){var n=e.createElement("style");n.type="text/css",n.styleSheet?n.styleSheet.cssText=t:n.appendChild(e.createTextNode(t)),e.getElementsByTagName("head")[0].appendChild(n)}function o(t){var e="childframe",n=t.createElement("iframe");return i(".jsPDF_sillysvg_iframe {display:none;position:absolute;}",t),n.name=e,n.setAttribute("width",0),n.setAttribute("height",0),n.setAttribute("frameborder","0"),n.setAttribute("scrolling","no"),n.setAttribute("seamless","seamless"),n.setAttribute("class","jsPDF_sillysvg_iframe"),t.body.appendChild(n),n}function a(t,e){var n=(e.contentWindow||e.contentDocument).document;return n.write(t),n.close(),n.getElementsByTagName("svg")[0]}function u(t){for(var e=parseFloat(t[1]),n=parseFloat(t[2]),r=[],s=3,i=t.length;i>s;)"c"===t[s]?(r.push([parseFloat(t[s+1]),parseFloat(t[s+2]),parseFloat(t[s+3]),parseFloat(t[s+4]),parseFloat(t[s+5]),parseFloat(t[s+6])]),s+=7):"l"===t[s]?(r.push([parseFloat(t[s+1]),parseFloat(t[s+2])]),s+=3):s+=1;return[e,n,r]}var c;if(e===c||n===c)throw new Error("addSVG needs values for 'x' and 'y'");var l=o(document),f=a(t,l),d=[1,1],h=parseFloat(f.getAttribute("width")),p=parseFloat(f.getAttribute("height"));h&&p&&(r&&s?d=[r/h,s/p]:r?d=[r/h,r/h]:s&&(d=[s/p,s/p]));var m,w,g,y,v=f.childNodes;for(m=0,w=v.length;w>m;m++)g=v[m],g.tagName&&"PATH"===g.tagName.toUpperCase()&&(y=u(g.getAttribute("d").split(" ")),y[0]=y[0]*d[0]+e,y[1]=y[1]*d[1]+n,this.lines.call(this,y[2],y[0],y[1],d));return this}}(n.API),function(t){"use strict";var e=t.getCharWidthsArray=function(t,e){e||(e={});var n,r,s,i=e.widths?e.widths:this.internal.getFont().metadata.Unicode.widths,o=i.fof?i.fof:1,a=e.kerning?e.kerning:this.internal.getFont().metadata.Unicode.kerning,u=a.fof?a.fof:1,c=0,l=i[0]||o,f=[];for(n=0,r=t.length;r>n;n++)s=t.charCodeAt(n),f.push((i[s]||l)/o+(a[s]&&a[s][c]||0)/u),c=s;return f},n=function(t){for(var e=t.length,n=0;e;)e--,n+=t[e];return n},r=t.getStringUnitWidth=function(t,r){return n(e.call(this,t,r))},s=function(t,e,n,r){for(var s=[],i=0,o=t.length,a=0;i!==o&&a+e[i]<n;)a+=e[i],i++;s.push(t.slice(0,i));var u=i;for(a=0;i!==o;)a+e[i]>r&&(s.push(t.slice(u,i)),a=0,u=i),a+=e[i],i++;return u!==i&&s.push(t.slice(u,i)),s},i=function(t,i,o){o||(o={});var a,u,c,l,f,d,h=[],p=[h],m=o.textIndent||0,w=0,g=0,y=t.split(" "),v=e(" ",o)[0];if(d=-1===o.lineIndent?y[0].length+2:o.lineIndent||0){var b=Array(d).join(" "),q=[];y.map(function(t){t=t.split(/\s*\n/),t.length>1?q=q.concat(t.map(function(t,e){return(e&&t.length?"\n":"")+t})):q.push(t[0])}),y=q,d=r(b,o)}for(c=0,l=y.length;l>c;c++){var x=0;if(a=y[c],d&&"\n"==a[0]&&(a=a.substr(1),x=1),u=e(a,o),g=n(u),m+w+g>i||x){if(g>i){for(f=s(a,u,i-(m+w),i),h.push(f.shift()),h=[f.pop()];f.length;)p.push([f.shift()]);g=n(u.slice(a.length-h[0].length))}else h=[a];p.push(h),m=g+d,w=v}else h.push(a),m+=w+g,w=v}if(d)var k=function(t,e){return(e?b:"")+t.join(" ")};else var k=function(t){return t.join(" ")};return p.map(k)};t.splitTextToSize=function(t,e,n){n||(n={});var r,s=n.fontSize||this.internal.getFontSize(),o=function(t){var e={0:1},n={};if(t.widths&&t.kerning)return{widths:t.widths,kerning:t.kerning};var r=this.internal.getFont(t.fontName,t.fontStyle),s="Unicode";return r.metadata[s]?{widths:r.metadata[s].widths||e,kerning:r.metadata[s].kerning||n}:{widths:e,kerning:n}}.call(this,n);r=Array.isArray(t)?t:t.split(/\r?\n/);var a=1*this.internal.scaleFactor*e/s;o.textIndent=n.textIndent?1*n.textIndent*this.internal.scaleFactor/s:0,o.lineIndent=n.lineIndent;var u,c,l=[];for(u=0,c=r.length;c>u;u++)l=l.concat(i(r[u],a,o));return l}}(n.API),function(t){"use strict";var e=function(t){for(var e="0123456789abcdef",n="klmnopqrstuvwxyz",r={},s=0;s<n.length;s++)r[n[s]]=e[s];var i,o,a,u,c,l={},f=1,d=l,h=[],p="",m="",w=t.length-1;for(s=1;s!=w;)c=t[s],s+=1,"'"==c?o?(u=o.join(""),o=i):o=[]:o?o.push(c):"{"==c?(h.push([d,u]),d={},u=i):"}"==c?(a=h.pop(),a[0][a[1]]=d,u=i,d=a[0]):"-"==c?f=-1:u===i?r.hasOwnProperty(c)?(p+=r[c],u=parseInt(p,16)*f,f=1,p=""):p+=c:r.hasOwnProperty(c)?(m+=r[c],d[u]=parseInt(m,16)*f,f=1,u=i,m=""):m+=c;return l},n={codePages:["WinAnsiEncoding"],WinAnsiEncoding:e("{19m8n201n9q201o9r201s9l201t9m201u8m201w9n201x9o201y8o202k8q202l8r202m9p202q8p20aw8k203k8t203t8v203u9v2cq8s212m9t15m8w15n9w2dw9s16k8u16l9u17s9z17x8y17y9y}")},r={Unicode:{Courier:n,"Courier-Bold":n,"Courier-BoldOblique":n,"Courier-Oblique":n,Helvetica:n,"Helvetica-Bold":n,"Helvetica-BoldOblique":n,"Helvetica-Oblique":n,"Times-Roman":n,"Times-Bold":n,"Times-BoldItalic":n,"Times-Italic":n}},s={Unicode:{"Courier-Oblique":e("{'widths'{k3w'fof'6o}'kerning'{'fof'-6o}}"),"Times-BoldItalic":e("{'widths'{k3o2q4ycx2r201n3m201o6o201s2l201t2l201u2l201w3m201x3m201y3m2k1t2l2r202m2n2n3m2o3m2p5n202q6o2r1w2s2l2t2l2u3m2v3t2w1t2x2l2y1t2z1w3k3m3l3m3m3m3n3m3o3m3p3m3q3m3r3m3s3m203t2l203u2l3v2l3w3t3x3t3y3t3z3m4k5n4l4m4m4m4n4m4o4s4p4m4q4m4r4s4s4y4t2r4u3m4v4m4w3x4x5t4y4s4z4s5k3x5l4s5m4m5n3r5o3x5p4s5q4m5r5t5s4m5t3x5u3x5v2l5w1w5x2l5y3t5z3m6k2l6l3m6m3m6n2w6o3m6p2w6q2l6r3m6s3r6t1w6u1w6v3m6w1w6x4y6y3r6z3m7k3m7l3m7m2r7n2r7o1w7p3r7q2w7r4m7s3m7t2w7u2r7v2n7w1q7x2n7y3t202l3mcl4mal2ram3man3mao3map3mar3mas2lat4uau1uav3maw3way4uaz2lbk2sbl3t'fof'6obo2lbp3tbq3mbr1tbs2lbu1ybv3mbz3mck4m202k3mcm4mcn4mco4mcp4mcq5ycr4mcs4mct4mcu4mcv4mcw2r2m3rcy2rcz2rdl4sdm4sdn4sdo4sdp4sdq4sds4sdt4sdu4sdv4sdw4sdz3mek3mel3mem3men3meo3mep3meq4ser2wes2wet2weu2wev2wew1wex1wey1wez1wfl3rfm3mfn3mfo3mfp3mfq3mfr3tfs3mft3rfu3rfv3rfw3rfz2w203k6o212m6o2dw2l2cq2l3t3m3u2l17s3x19m3m}'kerning'{cl{4qu5kt5qt5rs17ss5ts}201s{201ss}201t{cks4lscmscnscoscpscls2wu2yu201ts}201x{2wu2yu}2k{201ts}2w{4qx5kx5ou5qx5rs17su5tu}2x{17su5tu5ou}2y{4qx5kx5ou5qx5rs17ss5ts}'fof'-6ofn{17sw5tw5ou5qw5rs}7t{cksclscmscnscoscps4ls}3u{17su5tu5os5qs}3v{17su5tu5os5qs}7p{17su5tu}ck{4qu5kt5qt5rs17ss5ts}4l{4qu5kt5qt5rs17ss5ts}cm{4qu5kt5qt5rs17ss5ts}cn{4qu5kt5qt5rs17ss5ts}co{4qu5kt5qt5rs17ss5ts}cp{4qu5kt5qt5rs17ss5ts}6l{4qu5ou5qw5rt17su5tu}5q{ckuclucmucnucoucpu4lu}5r{ckuclucmucnucoucpu4lu}7q{cksclscmscnscoscps4ls}6p{4qu5ou5qw5rt17sw5tw}ek{4qu5ou5qw5rt17su5tu}el{4qu5ou5qw5rt17su5tu}em{4qu5ou5qw5rt17su5tu}en{4qu5ou5qw5rt17su5tu}eo{4qu5ou5qw5rt17su5tu}ep{4qu5ou5qw5rt17su5tu}es{17ss5ts5qs4qu}et{4qu5ou5qw5rt17sw5tw}eu{4qu5ou5qw5rt17ss5ts}ev{17ss5ts5qs4qu}6z{17sw5tw5ou5qw5rs}fm{17sw5tw5ou5qw5rs}7n{201ts}fo{17sw5tw5ou5qw5rs}fp{17sw5tw5ou5qw5rs}fq{17sw5tw5ou5qw5rs}7r{cksclscmscnscoscps4ls}fs{17sw5tw5ou5qw5rs}ft{17su5tu}fu{17su5tu}fv{17su5tu}fw{17su5tu}fz{cksclscmscnscoscps4ls}}}"),"Helvetica-Bold":e("{'widths'{k3s2q4scx1w201n3r201o6o201s1w201t1w201u1w201w3m201x3m201y3m2k1w2l2l202m2n2n3r2o3r2p5t202q6o2r1s2s2l2t2l2u2r2v3u2w1w2x2l2y1w2z1w3k3r3l3r3m3r3n3r3o3r3p3r3q3r3r3r3s3r203t2l203u2l3v2l3w3u3x3u3y3u3z3x4k6l4l4s4m4s4n4s4o4s4p4m4q3x4r4y4s4s4t1w4u3r4v4s4w3x4x5n4y4s4z4y5k4m5l4y5m4s5n4m5o3x5p4s5q4m5r5y5s4m5t4m5u3x5v2l5w1w5x2l5y3u5z3r6k2l6l3r6m3x6n3r6o3x6p3r6q2l6r3x6s3x6t1w6u1w6v3r6w1w6x5t6y3x6z3x7k3x7l3x7m2r7n3r7o2l7p3x7q3r7r4y7s3r7t3r7u3m7v2r7w1w7x2r7y3u202l3rcl4sal2lam3ran3rao3rap3rar3ras2lat4tau2pav3raw3uay4taz2lbk2sbl3u'fof'6obo2lbp3xbq3rbr1wbs2lbu2obv3rbz3xck4s202k3rcm4scn4sco4scp4scq6ocr4scs4mct4mcu4mcv4mcw1w2m2zcy1wcz1wdl4sdm4ydn4ydo4ydp4ydq4yds4ydt4sdu4sdv4sdw4sdz3xek3rel3rem3ren3reo3rep3req5ter3res3ret3reu3rev3rew1wex1wey1wez1wfl3xfm3xfn3xfo3xfp3xfq3xfr3ufs3xft3xfu3xfv3xfw3xfz3r203k6o212m6o2dw2l2cq2l3t3r3u2l17s4m19m3r}'kerning'{cl{4qs5ku5ot5qs17sv5tv}201t{2ww4wy2yw}201w{2ks}201x{2ww4wy2yw}2k{201ts201xs}2w{7qs4qu5kw5os5qw5rs17su5tu7tsfzs}2x{5ow5qs}2y{7qs4qu5kw5os5qw5rs17su5tu7tsfzs}'fof'-6o7p{17su5tu5ot}ck{4qs5ku5ot5qs17sv5tv}4l{4qs5ku5ot5qs17sv5tv}cm{4qs5ku5ot5qs17sv5tv}cn{4qs5ku5ot5qs17sv5tv}co{4qs5ku5ot5qs17sv5tv}cp{4qs5ku5ot5qs17sv5tv}6l{17st5tt5os}17s{2kwclvcmvcnvcovcpv4lv4wwckv}5o{2kucltcmtcntcotcpt4lt4wtckt}5q{2ksclscmscnscoscps4ls4wvcks}5r{2ks4ws}5t{2kwclvcmvcnvcovcpv4lv4wwckv}eo{17st5tt5os}fu{17su5tu5ot}6p{17ss5ts}ek{17st5tt5os}el{17st5tt5os}em{17st5tt5os}en{17st5tt5os}6o{201ts}ep{17st5tt5os}es{17ss5ts}et{17ss5ts}eu{17ss5ts}ev{17ss5ts}6z{17su5tu5os5qt}fm{17su5tu5os5qt}fn{17su5tu5os5qt}fo{17su5tu5os5qt}fp{17su5tu5os5qt}fq{17su5tu5os5qt}fs{17su5tu5os5qt}ft{17su5tu5ot}7m{5os}fv{17su5tu5ot}fw{17su5tu5ot}}}"),Courier:e("{'widths'{k3w'fof'6o}'kerning'{'fof'-6o}}"),"Courier-BoldOblique":e("{'widths'{k3w'fof'6o}'kerning'{'fof'-6o}}"),"Times-Bold":e("{'widths'{k3q2q5ncx2r201n3m201o6o201s2l201t2l201u2l201w3m201x3m201y3m2k1t2l2l202m2n2n3m2o3m2p6o202q6o2r1w2s2l2t2l2u3m2v3t2w1t2x2l2y1t2z1w3k3m3l3m3m3m3n3m3o3m3p3m3q3m3r3m3s3m203t2l203u2l3v2l3w3t3x3t3y3t3z3m4k5x4l4s4m4m4n4s4o4s4p4m4q3x4r4y4s4y4t2r4u3m4v4y4w4m4x5y4y4s4z4y5k3x5l4y5m4s5n3r5o4m5p4s5q4s5r6o5s4s5t4s5u4m5v2l5w1w5x2l5y3u5z3m6k2l6l3m6m3r6n2w6o3r6p2w6q2l6r3m6s3r6t1w6u2l6v3r6w1w6x5n6y3r6z3m7k3r7l3r7m2w7n2r7o2l7p3r7q3m7r4s7s3m7t3m7u2w7v2r7w1q7x2r7y3o202l3mcl4sal2lam3man3mao3map3mar3mas2lat4uau1yav3maw3tay4uaz2lbk2sbl3t'fof'6obo2lbp3rbr1tbs2lbu2lbv3mbz3mck4s202k3mcm4scn4sco4scp4scq6ocr4scs4mct4mcu4mcv4mcw2r2m3rcy2rcz2rdl4sdm4ydn4ydo4ydp4ydq4yds4ydt4sdu4sdv4sdw4sdz3rek3mel3mem3men3meo3mep3meq4ser2wes2wet2weu2wev2wew1wex1wey1wez1wfl3rfm3mfn3mfo3mfp3mfq3mfr3tfs3mft3rfu3rfv3rfw3rfz3m203k6o212m6o2dw2l2cq2l3t3m3u2l17s4s19m3m}'kerning'{cl{4qt5ks5ot5qy5rw17sv5tv}201t{cks4lscmscnscoscpscls4wv}2k{201ts}2w{4qu5ku7mu5os5qx5ru17su5tu}2x{17su5tu5ou5qs}2y{4qv5kv7mu5ot5qz5ru17su5tu}'fof'-6o7t{cksclscmscnscoscps4ls}3u{17su5tu5os5qu}3v{17su5tu5os5qu}fu{17su5tu5ou5qu}7p{17su5tu5ou5qu}ck{4qt5ks5ot5qy5rw17sv5tv}4l{4qt5ks5ot5qy5rw17sv5tv}cm{4qt5ks5ot5qy5rw17sv5tv}cn{4qt5ks5ot5qy5rw17sv5tv}co{4qt5ks5ot5qy5rw17sv5tv}cp{4qt5ks5ot5qy5rw17sv5tv}6l{17st5tt5ou5qu}17s{ckuclucmucnucoucpu4lu4wu}5o{ckuclucmucnucoucpu4lu4wu}5q{ckzclzcmzcnzcozcpz4lz4wu}5r{ckxclxcmxcnxcoxcpx4lx4wu}5t{ckuclucmucnucoucpu4lu4wu}7q{ckuclucmucnucoucpu4lu}6p{17sw5tw5ou5qu}ek{17st5tt5qu}el{17st5tt5ou5qu}em{17st5tt5qu}en{17st5tt5qu}eo{17st5tt5qu}ep{17st5tt5ou5qu}es{17ss5ts5qu}et{17sw5tw5ou5qu}eu{17sw5tw5ou5qu}ev{17ss5ts5qu}6z{17sw5tw5ou5qu5rs}fm{17sw5tw5ou5qu5rs}fn{17sw5tw5ou5qu5rs}fo{17sw5tw5ou5qu5rs}fp{17sw5tw5ou5qu5rs}fq{17sw5tw5ou5qu5rs}7r{cktcltcmtcntcotcpt4lt5os}fs{17sw5tw5ou5qu5rs}ft{17su5tu5ou5qu}7m{5os}fv{17su5tu5ou5qu}fw{17su5tu5ou5qu}fz{cksclscmscnscoscps4ls}}}"),Helvetica:e("{'widths'{k3p2q4mcx1w201n3r201o6o201s1q201t1q201u1q201w2l201x2l201y2l2k1w2l1w202m2n2n3r2o3r2p5t202q6o2r1n2s2l2t2l2u2r2v3u2w1w2x2l2y1w2z1w3k3r3l3r3m3r3n3r3o3r3p3r3q3r3r3r3s3r203t2l203u2l3v1w3w3u3x3u3y3u3z3r4k6p4l4m4m4m4n4s4o4s4p4m4q3x4r4y4s4s4t1w4u3m4v4m4w3r4x5n4y4s4z4y5k4m5l4y5m4s5n4m5o3x5p4s5q4m5r5y5s4m5t4m5u3x5v1w5w1w5x1w5y2z5z3r6k2l6l3r6m3r6n3m6o3r6p3r6q1w6r3r6s3r6t1q6u1q6v3m6w1q6x5n6y3r6z3r7k3r7l3r7m2l7n3m7o1w7p3r7q3m7r4s7s3m7t3m7u3m7v2l7w1u7x2l7y3u202l3rcl4mal2lam3ran3rao3rap3rar3ras2lat4tau2pav3raw3uay4taz2lbk2sbl3u'fof'6obo2lbp3rbr1wbs2lbu2obv3rbz3xck4m202k3rcm4mcn4mco4mcp4mcq6ocr4scs4mct4mcu4mcv4mcw1w2m2ncy1wcz1wdl4sdm4ydn4ydo4ydp4ydq4yds4ydt4sdu4sdv4sdw4sdz3xek3rel3rem3ren3reo3rep3req5ter3mes3ret3reu3rev3rew1wex1wey1wez1wfl3rfm3rfn3rfo3rfp3rfq3rfr3ufs3xft3rfu3rfv3rfw3rfz3m203k6o212m6o2dw2l2cq2l3t3r3u1w17s4m19m3r}'kerning'{5q{4wv}cl{4qs5kw5ow5qs17sv5tv}201t{2wu4w1k2yu}201x{2wu4wy2yu}17s{2ktclucmucnu4otcpu4lu4wycoucku}2w{7qs4qz5k1m17sy5ow5qx5rsfsu5ty7tufzu}2x{17sy5ty5oy5qs}2y{7qs4qz5k1m17sy5ow5qx5rsfsu5ty7tufzu}'fof'-6o7p{17sv5tv5ow}ck{4qs5kw5ow5qs17sv5tv}4l{4qs5kw5ow5qs17sv5tv}cm{4qs5kw5ow5qs17sv5tv}cn{4qs5kw5ow5qs17sv5tv}co{4qs5kw5ow5qs17sv5tv}cp{4qs5kw5ow5qs17sv5tv}6l{17sy5ty5ow}do{17st5tt}4z{17st5tt}7s{fst}dm{17st5tt}dn{17st5tt}5o{ckwclwcmwcnwcowcpw4lw4wv}dp{17st5tt}dq{17st5tt}7t{5ow}ds{17st5tt}5t{2ktclucmucnu4otcpu4lu4wycoucku}fu{17sv5tv5ow}6p{17sy5ty5ow5qs}ek{17sy5ty5ow}el{17sy5ty5ow}em{17sy5ty5ow}en{5ty}eo{17sy5ty5ow}ep{17sy5ty5ow}es{17sy5ty5qs}et{17sy5ty5ow5qs}eu{17sy5ty5ow5qs}ev{17sy5ty5ow5qs}6z{17sy5ty5ow5qs}fm{17sy5ty5ow5qs}fn{17sy5ty5ow5qs}fo{17sy5ty5ow5qs}fp{17sy5ty5qs}fq{17sy5ty5ow5qs}7r{5ow}fs{17sy5ty5ow5qs}ft{17sv5tv5ow}7m{5ow}fv{17sv5tv5ow}fw{17sv5tv5ow}}}"),"Helvetica-BoldOblique":e("{'widths'{k3s2q4scx1w201n3r201o6o201s1w201t1w201u1w201w3m201x3m201y3m2k1w2l2l202m2n2n3r2o3r2p5t202q6o2r1s2s2l2t2l2u2r2v3u2w1w2x2l2y1w2z1w3k3r3l3r3m3r3n3r3o3r3p3r3q3r3r3r3s3r203t2l203u2l3v2l3w3u3x3u3y3u3z3x4k6l4l4s4m4s4n4s4o4s4p4m4q3x4r4y4s4s4t1w4u3r4v4s4w3x4x5n4y4s4z4y5k4m5l4y5m4s5n4m5o3x5p4s5q4m5r5y5s4m5t4m5u3x5v2l5w1w5x2l5y3u5z3r6k2l6l3r6m3x6n3r6o3x6p3r6q2l6r3x6s3x6t1w6u1w6v3r6w1w6x5t6y3x6z3x7k3x7l3x7m2r7n3r7o2l7p3x7q3r7r4y7s3r7t3r7u3m7v2r7w1w7x2r7y3u202l3rcl4sal2lam3ran3rao3rap3rar3ras2lat4tau2pav3raw3uay4taz2lbk2sbl3u'fof'6obo2lbp3xbq3rbr1wbs2lbu2obv3rbz3xck4s202k3rcm4scn4sco4scp4scq6ocr4scs4mct4mcu4mcv4mcw1w2m2zcy1wcz1wdl4sdm4ydn4ydo4ydp4ydq4yds4ydt4sdu4sdv4sdw4sdz3xek3rel3rem3ren3reo3rep3req5ter3res3ret3reu3rev3rew1wex1wey1wez1wfl3xfm3xfn3xfo3xfp3xfq3xfr3ufs3xft3xfu3xfv3xfw3xfz3r203k6o212m6o2dw2l2cq2l3t3r3u2l17s4m19m3r}'kerning'{cl{4qs5ku5ot5qs17sv5tv}201t{2ww4wy2yw}201w{2ks}201x{2ww4wy2yw}2k{201ts201xs}2w{7qs4qu5kw5os5qw5rs17su5tu7tsfzs}2x{5ow5qs}2y{7qs4qu5kw5os5qw5rs17su5tu7tsfzs}'fof'-6o7p{17su5tu5ot}ck{4qs5ku5ot5qs17sv5tv}4l{4qs5ku5ot5qs17sv5tv}cm{4qs5ku5ot5qs17sv5tv}cn{4qs5ku5ot5qs17sv5tv}co{4qs5ku5ot5qs17sv5tv}cp{4qs5ku5ot5qs17sv5tv}6l{17st5tt5os}17s{2kwclvcmvcnvcovcpv4lv4wwckv}5o{2kucltcmtcntcotcpt4lt4wtckt}5q{2ksclscmscnscoscps4ls4wvcks}5r{2ks4ws}5t{2kwclvcmvcnvcovcpv4lv4wwckv}eo{17st5tt5os}fu{17su5tu5ot}6p{17ss5ts}ek{17st5tt5os}el{17st5tt5os}em{17st5tt5os}en{17st5tt5os}6o{201ts}ep{17st5tt5os}es{17ss5ts}et{17ss5ts}eu{17ss5ts}ev{17ss5ts}6z{17su5tu5os5qt}fm{17su5tu5os5qt}fn{17su5tu5os5qt}fo{17su5tu5os5qt}fp{17su5tu5os5qt}fq{17su5tu5os5qt}fs{17su5tu5os5qt}ft{17su5tu5ot}7m{5os}fv{17su5tu5ot}fw{17su5tu5ot}}}"),"Courier-Bold":e("{'widths'{k3w'fof'6o}'kerning'{'fof'-6o}}"),"Times-Italic":e("{'widths'{k3n2q4ycx2l201n3m201o5t201s2l201t2l201u2l201w3r201x3r201y3r2k1t2l2l202m2n2n3m2o3m2p5n202q5t2r1p2s2l2t2l2u3m2v4n2w1t2x2l2y1t2z1w3k3m3l3m3m3m3n3m3o3m3p3m3q3m3r3m3s3m203t2l203u2l3v2l3w4n3x4n3y4n3z3m4k5w4l3x4m3x4n4m4o4s4p3x4q3x4r4s4s4s4t2l4u2w4v4m4w3r4x5n4y4m4z4s5k3x5l4s5m3x5n3m5o3r5p4s5q3x5r5n5s3x5t3r5u3r5v2r5w1w5x2r5y2u5z3m6k2l6l3m6m3m6n2w6o3m6p2w6q1w6r3m6s3m6t1w6u1w6v2w6w1w6x4s6y3m6z3m7k3m7l3m7m2r7n2r7o1w7p3m7q2w7r4m7s2w7t2w7u2r7v2s7w1v7x2s7y3q202l3mcl3xal2ram3man3mao3map3mar3mas2lat4wau1vav3maw4nay4waz2lbk2sbl4n'fof'6obo2lbp3mbq3obr1tbs2lbu1zbv3mbz3mck3x202k3mcm3xcn3xco3xcp3xcq5tcr4mcs3xct3xcu3xcv3xcw2l2m2ucy2lcz2ldl4mdm4sdn4sdo4sdp4sdq4sds4sdt4sdu4sdv4sdw4sdz3mek3mel3mem3men3meo3mep3meq4mer2wes2wet2weu2wev2wew1wex1wey1wez1wfl3mfm3mfn3mfo3mfp3mfq3mfr4nfs3mft3mfu3mfv3mfw3mfz2w203k6o212m6m2dw2l2cq2l3t3m3u2l17s3r19m3m}'kerning'{cl{5kt4qw}201s{201sw}201t{201tw2wy2yy6q-t}201x{2wy2yy}2k{201tw}2w{7qs4qy7rs5ky7mw5os5qx5ru17su5tu}2x{17ss5ts5os}2y{7qs4qy7rs5ky7mw5os5qx5ru17su5tu}'fof'-6o6t{17ss5ts5qs}7t{5os}3v{5qs}7p{17su5tu5qs}ck{5kt4qw}4l{5kt4qw}cm{5kt4qw}cn{5kt4qw}co{5kt4qw}cp{5kt4qw}6l{4qs5ks5ou5qw5ru17su5tu}17s{2ks}5q{ckvclvcmvcnvcovcpv4lv}5r{ckuclucmucnucoucpu4lu}5t{2ks}6p{4qs5ks5ou5qw5ru17su5tu}ek{4qs5ks5ou5qw5ru17su5tu}el{4qs5ks5ou5qw5ru17su5tu}em{4qs5ks5ou5qw5ru17su5tu}en{4qs5ks5ou5qw5ru17su5tu}eo{4qs5ks5ou5qw5ru17su5tu}ep{4qs5ks5ou5qw5ru17su5tu}es{5ks5qs4qs}et{4qs5ks5ou5qw5ru17su5tu}eu{4qs5ks5qw5ru17su5tu}ev{5ks5qs4qs}ex{17ss5ts5qs}6z{4qv5ks5ou5qw5ru17su5tu}fm{4qv5ks5ou5qw5ru17su5tu}fn{4qv5ks5ou5qw5ru17su5tu}fo{4qv5ks5ou5qw5ru17su5tu}fp{4qv5ks5ou5qw5ru17su5tu}fq{4qv5ks5ou5qw5ru17su5tu}7r{5os}fs{4qv5ks5ou5qw5ru17su5tu}ft{17su5tu5qs}fu{17su5tu5qs}fv{17su5tu5qs}fw{17su5tu5qs}}}"),"Times-Roman":e("{'widths'{k3n2q4ycx2l201n3m201o6o201s2l201t2l201u2l201w2w201x2w201y2w2k1t2l2l202m2n2n3m2o3m2p5n202q6o2r1m2s2l2t2l2u3m2v3s2w1t2x2l2y1t2z1w3k3m3l3m3m3m3n3m3o3m3p3m3q3m3r3m3s3m203t2l203u2l3v1w3w3s3x3s3y3s3z2w4k5w4l4s4m4m4n4m4o4s4p3x4q3r4r4s4s4s4t2l4u2r4v4s4w3x4x5t4y4s4z4s5k3r5l4s5m4m5n3r5o3x5p4s5q4s5r5y5s4s5t4s5u3x5v2l5w1w5x2l5y2z5z3m6k2l6l2w6m3m6n2w6o3m6p2w6q2l6r3m6s3m6t1w6u1w6v3m6w1w6x4y6y3m6z3m7k3m7l3m7m2l7n2r7o1w7p3m7q3m7r4s7s3m7t3m7u2w7v3k7w1o7x3k7y3q202l3mcl4sal2lam3man3mao3map3mar3mas2lat4wau1vav3maw3say4waz2lbk2sbl3s'fof'6obo2lbp3mbq2xbr1tbs2lbu1zbv3mbz2wck4s202k3mcm4scn4sco4scp4scq5tcr4mcs3xct3xcu3xcv3xcw2l2m2tcy2lcz2ldl4sdm4sdn4sdo4sdp4sdq4sds4sdt4sdu4sdv4sdw4sdz3mek2wel2wem2wen2weo2wep2weq4mer2wes2wet2weu2wev2wew1wex1wey1wez1wfl3mfm3mfn3mfo3mfp3mfq3mfr3sfs3mft3mfu3mfv3mfw3mfz3m203k6o212m6m2dw2l2cq2l3t3m3u1w17s4s19m3m}'kerning'{cl{4qs5ku17sw5ou5qy5rw201ss5tw201ws}201s{201ss}201t{ckw4lwcmwcnwcowcpwclw4wu201ts}2k{201ts}2w{4qs5kw5os5qx5ru17sx5tx}2x{17sw5tw5ou5qu}2y{4qs5kw5os5qx5ru17sx5tx}'fof'-6o7t{ckuclucmucnucoucpu4lu5os5rs}3u{17su5tu5qs}3v{17su5tu5qs}7p{17sw5tw5qs}ck{4qs5ku17sw5ou5qy5rw201ss5tw201ws}4l{4qs5ku17sw5ou5qy5rw201ss5tw201ws}cm{4qs5ku17sw5ou5qy5rw201ss5tw201ws}cn{4qs5ku17sw5ou5qy5rw201ss5tw201ws}co{4qs5ku17sw5ou5qy5rw201ss5tw201ws}cp{4qs5ku17sw5ou5qy5rw201ss5tw201ws}6l{17su5tu5os5qw5rs}17s{2ktclvcmvcnvcovcpv4lv4wuckv}5o{ckwclwcmwcnwcowcpw4lw4wu}5q{ckyclycmycnycoycpy4ly4wu5ms}5r{cktcltcmtcntcotcpt4lt4ws}5t{2ktclvcmvcnvcovcpv4lv4wuckv}7q{cksclscmscnscoscps4ls}6p{17su5tu5qw5rs}ek{5qs5rs}el{17su5tu5os5qw5rs}em{17su5tu5os5qs5rs}en{17su5qs5rs}eo{5qs5rs}ep{17su5tu5os5qw5rs}es{5qs}et{17su5tu5qw5rs}eu{17su5tu5qs5rs}ev{5qs}6z{17sv5tv5os5qx5rs}fm{5os5qt5rs}fn{17sv5tv5os5qx5rs}fo{17sv5tv5os5qx5rs}fp{5os5qt5rs}fq{5os5qt5rs}7r{ckuclucmucnucoucpu4lu5os}fs{17sv5tv5os5qx5rs}ft{17ss5ts5qs}fu{17sw5tw5qs}fv{17sw5tw5qs}fw{17ss5ts5qs}fz{ckuclucmucnucoucpu4lu5os5rs}}}"),"Helvetica-Oblique":e("{'widths'{k3p2q4mcx1w201n3r201o6o201s1q201t1q201u1q201w2l201x2l201y2l2k1w2l1w202m2n2n3r2o3r2p5t202q6o2r1n2s2l2t2l2u2r2v3u2w1w2x2l2y1w2z1w3k3r3l3r3m3r3n3r3o3r3p3r3q3r3r3r3s3r203t2l203u2l3v1w3w3u3x3u3y3u3z3r4k6p4l4m4m4m4n4s4o4s4p4m4q3x4r4y4s4s4t1w4u3m4v4m4w3r4x5n4y4s4z4y5k4m5l4y5m4s5n4m5o3x5p4s5q4m5r5y5s4m5t4m5u3x5v1w5w1w5x1w5y2z5z3r6k2l6l3r6m3r6n3m6o3r6p3r6q1w6r3r6s3r6t1q6u1q6v3m6w1q6x5n6y3r6z3r7k3r7l3r7m2l7n3m7o1w7p3r7q3m7r4s7s3m7t3m7u3m7v2l7w1u7x2l7y3u202l3rcl4mal2lam3ran3rao3rap3rar3ras2lat4tau2pav3raw3uay4taz2lbk2sbl3u'fof'6obo2lbp3rbr1wbs2lbu2obv3rbz3xck4m202k3rcm4mcn4mco4mcp4mcq6ocr4scs4mct4mcu4mcv4mcw1w2m2ncy1wcz1wdl4sdm4ydn4ydo4ydp4ydq4yds4ydt4sdu4sdv4sdw4sdz3xek3rel3rem3ren3reo3rep3req5ter3mes3ret3reu3rev3rew1wex1wey1wez1wfl3rfm3rfn3rfo3rfp3rfq3rfr3ufs3xft3rfu3rfv3rfw3rfz3m203k6o212m6o2dw2l2cq2l3t3r3u1w17s4m19m3r}'kerning'{5q{4wv}cl{4qs5kw5ow5qs17sv5tv}201t{2wu4w1k2yu}201x{2wu4wy2yu}17s{2ktclucmucnu4otcpu4lu4wycoucku}2w{7qs4qz5k1m17sy5ow5qx5rsfsu5ty7tufzu}2x{17sy5ty5oy5qs}2y{7qs4qz5k1m17sy5ow5qx5rsfsu5ty7tufzu}'fof'-6o7p{17sv5tv5ow}ck{4qs5kw5ow5qs17sv5tv}4l{4qs5kw5ow5qs17sv5tv}cm{4qs5kw5ow5qs17sv5tv}cn{4qs5kw5ow5qs17sv5tv}co{4qs5kw5ow5qs17sv5tv}cp{4qs5kw5ow5qs17sv5tv}6l{17sy5ty5ow}do{17st5tt}4z{17st5tt}7s{fst}dm{17st5tt}dn{17st5tt}5o{ckwclwcmwcnwcowcpw4lw4wv}dp{17st5tt}dq{17st5tt}7t{5ow}ds{17st5tt}5t{2ktclucmucnu4otcpu4lu4wycoucku}fu{17sv5tv5ow}6p{17sy5ty5ow5qs}ek{17sy5ty5ow}el{17sy5ty5ow}em{17sy5ty5ow}en{5ty}eo{17sy5ty5ow}ep{17sy5ty5ow}es{17sy5ty5qs}et{17sy5ty5ow5qs}eu{17sy5ty5ow5qs}ev{17sy5ty5ow5qs}6z{17sy5ty5ow5qs}fm{17sy5ty5ow5qs}fn{17sy5ty5ow5qs}fo{17sy5ty5ow5qs}fp{17sy5ty5qs}fq{17sy5ty5ow5qs}7r{5ow}fs{17sy5ty5ow5qs}ft{17sv5tv5ow}7m{5ow}fv{17sv5tv5ow}fw{17sv5tv5ow}}}")}}; +t.events.push(["addFonts",function(t){var e,n,i,o,a,u="Unicode";for(n in t.fonts)t.fonts.hasOwnProperty(n)&&(e=t.fonts[n],i=s[u][e.PostScriptName],i&&(o=e.metadata[u]?e.metadata[u]:e.metadata[u]={},o.widths=i.widths,o.kerning=i.kerning),a=r[u][e.PostScriptName],a&&(o=e.metadata[u]?e.metadata[u]:e.metadata[u]={},o.encoding=a,a.codePages&&a.codePages.length&&(e.encoding=a.codePages[0])))}])}(n.API),function(t){"use strict";t.putTotalPages=function(t){for(var e=new RegExp(t,"g"),n=1;n<=this.internal.getNumberOfPages();n++)for(var r=0;r<this.internal.pages[n].length;r++)this.internal.pages[n][r]=this.internal.pages[n][r].replace(e,this.internal.getNumberOfPages());return this}}(n.API),function(t){"use strict";if(t.URL=t.URL||t.webkitURL,t.Blob&&t.URL)try{return void new Blob}catch(e){}var n=t.BlobBuilder||t.WebKitBlobBuilder||t.MozBlobBuilder||function(t){var e=function(t){return Object.prototype.toString.call(t).match(/^\[object\s(.*)\]$/)[1]},n=function(){this.data=[]},r=function(t,e,n){this.data=t,this.size=t.length,this.type=e,this.encoding=n},s=n.prototype,i=r.prototype,o=t.FileReaderSync,a=function(t){this.code=this[this.name=t]},u="NOT_FOUND_ERR SECURITY_ERR ABORT_ERR NOT_READABLE_ERR ENCODING_ERR NO_MODIFICATION_ALLOWED_ERR INVALID_STATE_ERR SYNTAX_ERR".split(" "),c=u.length,l=t.URL||t.webkitURL||t,f=l.createObjectURL,d=l.revokeObjectURL,h=l,p=t.btoa,m=t.atob,w=t.ArrayBuffer,g=t.Uint8Array,y=/^[\w-]+:\/*\[?[\w\.:-]+\]?(?::[0-9]+)?/;for(r.fake=i.fake=!0;c--;)a.prototype[u[c]]=c+1;return l.createObjectURL||(h=t.URL=function(t){var e,n=document.createElementNS("http://www.w3.org/1999/xhtml","a");return n.href=t,"origin"in n||("data:"===n.protocol.toLowerCase()?n.origin=null:(e=t.match(y),n.origin=e&&e[1])),n}),h.createObjectURL=function(t){var e,n=t.type;return null===n&&(n="application/octet-stream"),t instanceof r?(e="data:"+n,"base64"===t.encoding?e+";base64,"+t.data:"URI"===t.encoding?e+","+decodeURIComponent(t.data):p?e+";base64,"+p(t.data):e+","+encodeURIComponent(t.data)):f?f.call(l,t):void 0},h.revokeObjectURL=function(t){"data:"!==t.substring(0,5)&&d&&d.call(l,t)},s.append=function(t){var n=this.data;if(g&&(t instanceof w||t instanceof g)){for(var s="",i=new g(t),u=0,c=i.length;c>u;u++)s+=String.fromCharCode(i[u]);n.push(s)}else if("Blob"===e(t)||"File"===e(t)){if(!o)throw new a("NOT_READABLE_ERR");var l=new o;n.push(l.readAsBinaryString(t))}else t instanceof r?"base64"===t.encoding&&m?n.push(m(t.data)):"URI"===t.encoding?n.push(decodeURIComponent(t.data)):"raw"===t.encoding&&n.push(t.data):("string"!=typeof t&&(t+=""),n.push(unescape(encodeURIComponent(t))))},s.getBlob=function(t){return arguments.length||(t=null),new r(this.data.join(""),t,"raw")},s.toString=function(){return"[object BlobBuilder]"},i.slice=function(t,e,n){var s=arguments.length;return 3>s&&(n=null),new r(this.data.slice(t,s>1?e:this.data.length),n,this.encoding)},i.toString=function(){return"[object Blob]"},i.close=function(){this.size=0,delete this.data},n}(t);t.Blob=function(t,e){var r=e?e.type||"":"",s=new n;if(t)for(var i=0,o=t.length;o>i;i++)s.append(t[i]);return s.getBlob(r)}}("undefined"!=typeof self&&self||"undefined"!=typeof window&&window||this.content||this);var r=r||"undefined"!=typeof navigator&&navigator.msSaveOrOpenBlob&&navigator.msSaveOrOpenBlob.bind(navigator)||function(t){"use strict";if("undefined"==typeof navigator||!/MSIE [1-9]\./.test(navigator.userAgent)){var e=t.document,n=function(){return t.URL||t.webkitURL||t},r=e.createElementNS("http://www.w3.org/1999/xhtml","a"),s="download"in r,i=function(n){var r=e.createEvent("MouseEvents");r.initMouseEvent("click",!0,!1,t,0,0,0,0,0,!1,!1,!1,!1,0,null),n.dispatchEvent(r)},o=t.webkitRequestFileSystem,a=t.requestFileSystem||o||t.mozRequestFileSystem,u=function(e){(t.setImmediate||t.setTimeout)(function(){throw e},0)},c="application/octet-stream",l=0,f=10,d=function(e){var r=function(){"string"==typeof e?n().revokeObjectURL(e):e.remove()};t.chrome?r():setTimeout(r,f)},h=function(t,e,n){e=[].concat(e);for(var r=e.length;r--;){var s=t["on"+e[r]];if("function"==typeof s)try{s.call(t,n||t)}catch(i){u(i)}}},p=function(e,u){var f,p,m,w=this,g=e.type,y=!1,v=function(){h(w,"writestart progress write writeend".split(" "))},b=function(){if((y||!f)&&(f=n().createObjectURL(e)),p)p.location.href=f;else{var r=t.open(f,"_blank");void 0==r&&"undefined"!=typeof safari&&(t.location.href=f)}w.readyState=w.DONE,v(),d(f)},q=function(t){return function(){return w.readyState!==w.DONE?t.apply(this,arguments):void 0}},x={create:!0,exclusive:!1};return w.readyState=w.INIT,u||(u="download"),s?(f=n().createObjectURL(e),r.href=f,r.download=u,i(r),w.readyState=w.DONE,v(),void d(f)):(t.chrome&&g&&g!==c&&(m=e.slice||e.webkitSlice,e=m.call(e,0,e.size,c),y=!0),o&&"download"!==u&&(u+=".download"),(g===c||o)&&(p=t),a?(l+=e.size,void a(t.TEMPORARY,l,q(function(t){t.root.getDirectory("saved",x,q(function(t){var n=function(){t.getFile(u,x,q(function(t){t.createWriter(q(function(n){n.onwriteend=function(e){p.location.href=t.toURL(),w.readyState=w.DONE,h(w,"writeend",e),d(t)},n.onerror=function(){var t=n.error;t.code!==t.ABORT_ERR&&b()},"writestart progress write abort".split(" ").forEach(function(t){n["on"+t]=w["on"+t]}),n.write(e),w.abort=function(){n.abort(),w.readyState=w.DONE},w.readyState=w.WRITING}),b)}),b)};t.getFile(u,{create:!1},q(function(t){t.remove(),n()}),q(function(t){t.code===t.NOT_FOUND_ERR?n():b()}))}),b)}),b)):void b())},m=p.prototype,w=function(t,e){return new p(t,e)};return m.abort=function(){var t=this;t.readyState=t.DONE,h(t,"abort")},m.readyState=m.INIT=0,m.WRITING=1,m.DONE=2,m.error=m.onwritestart=m.onprogress=m.onwrite=m.onabort=m.onerror=m.onwriteend=null,w}}("undefined"!=typeof self&&self||"undefined"!=typeof window&&window||this.content);"undefined"!=typeof module&&null!==module&&(module.exports=r),void function(t,e){"object"==typeof module?module.exports=e():t.adler32cs=e()}(n,function(){var t="function"==typeof ArrayBuffer&&"function"==typeof Uint8Array,e=null,n=function(){if(!t)return function(){return!1};try{var n=require("buffer");"function"==typeof n.Buffer&&(e=n.Buffer)}catch(r){}return function(t){return t instanceof ArrayBuffer||null!==e&&t instanceof e}}(),r=function(){return null!==e?function(t){return new e(t,"utf8").toString("binary")}:function(t){return unescape(encodeURIComponent(t))}}(),s=65521,i=function(t,e){for(var n=65535&t,r=t>>>16,i=0,o=e.length;o>i;i++)n=(n+(255&e.charCodeAt(i)))%s,r=(r+n)%s;return(r<<16|n)>>>0},o=function(t,e){for(var n=65535&t,r=t>>>16,i=0,o=e.length;o>i;i++)n=(n+e[i])%s,r=(r+n)%s;return(r<<16|n)>>>0},a={},u=a.Adler32=function(){var e=function(t){if(!(this instanceof e))throw new TypeError("Constructor cannot called be as a function.");if(!isFinite(t=null==t?1:+t))throw new Error("First arguments needs to be a finite number.");this.checksum=t>>>0},s=e.prototype={};return s.constructor=e,e.from=function(t){return t.prototype=s,t}(function(t){if(!(this instanceof e))throw new TypeError("Constructor cannot called be as a function.");if(null==t)throw new Error("First argument needs to be a string.");this.checksum=i(1,t.toString())}),e.fromUtf8=function(t){return t.prototype=s,t}(function(t){if(!(this instanceof e))throw new TypeError("Constructor cannot called be as a function.");if(null==t)throw new Error("First argument needs to be a string.");var n=r(t.toString());this.checksum=i(1,n)}),t&&(e.fromBuffer=function(t){return t.prototype=s,t}(function(t){if(!(this instanceof e))throw new TypeError("Constructor cannot called be as a function.");if(!n(t))throw new Error("First argument needs to be ArrayBuffer.");var r=new Uint8Array(t);return this.checksum=o(1,r)})),s.update=function(t){if(null==t)throw new Error("First argument needs to be a string.");return t=t.toString(),this.checksum=i(this.checksum,t)},s.updateUtf8=function(t){if(null==t)throw new Error("First argument needs to be a string.");var e=r(t.toString());return this.checksum=i(this.checksum,e)},t&&(s.updateBuffer=function(t){if(!n(t))throw new Error("First argument needs to be ArrayBuffer.");var e=new Uint8Array(t);return this.checksum=o(this.checksum,e)}),s.clone=function(){return new u(this.checksum)},e}();return a.from=function(t){if(null==t)throw new Error("First argument needs to be a string.");return i(1,t.toString())},a.fromUtf8=function(t){if(null==t)throw new Error("First argument needs to be a string.");var e=r(t.toString());return i(1,e)},t&&(a.fromBuffer=function(t){if(!n(t))throw new Error("First argument need to be ArrayBuffer.");var e=new Uint8Array(t);return o(1,e)}),a});var s=function(){function t(){function t(t){var e,n,s,i,a,u,c=r.dyn_tree,l=r.stat_desc.static_tree,f=r.stat_desc.extra_bits,h=r.stat_desc.extra_base,p=r.stat_desc.max_length,m=0;for(i=0;o>=i;i++)t.bl_count[i]=0;for(c[2*t.heap[t.heap_max]+1]=0,e=t.heap_max+1;d>e;e++)n=t.heap[e],i=c[2*c[2*n+1]+1]+1,i>p&&(i=p,m++),c[2*n+1]=i,n>r.max_code||(t.bl_count[i]++,a=0,n>=h&&(a=f[n-h]),u=c[2*n],t.opt_len+=u*(i+a),l&&(t.static_len+=u*(l[2*n+1]+a)));if(0!==m){do{for(i=p-1;0===t.bl_count[i];)i--;t.bl_count[i]--,t.bl_count[i+1]+=2,t.bl_count[p]--,m-=2}while(m>0);for(i=p;0!==i;i--)for(n=t.bl_count[i];0!==n;)s=t.heap[--e],s>r.max_code||(c[2*s+1]!=i&&(t.opt_len+=(i-c[2*s+1])*c[2*s],c[2*s+1]=i),n--)}}function e(t,e){var n=0;do n|=1&t,t>>>=1,n<<=1;while(--e>0);return n>>>1}function n(t,n,r){var s,i,a,u=[],c=0;for(s=1;o>=s;s++)u[s]=c=c+r[s-1]<<1;for(i=0;n>=i;i++)a=t[2*i+1],0!==a&&(t[2*i]=e(u[a]++,a))}var r=this;r.build_tree=function(e){var s,i,o,a=r.dyn_tree,u=r.stat_desc.static_tree,c=r.stat_desc.elems,l=-1;for(e.heap_len=0,e.heap_max=d,s=0;c>s;s++)0!==a[2*s]?(e.heap[++e.heap_len]=l=s,e.depth[s]=0):a[2*s+1]=0;for(;e.heap_len<2;)o=e.heap[++e.heap_len]=2>l?++l:0,a[2*o]=1,e.depth[o]=0,e.opt_len--,u&&(e.static_len-=u[2*o+1]);for(r.max_code=l,s=Math.floor(e.heap_len/2);s>=1;s--)e.pqdownheap(a,s);o=c;do s=e.heap[1],e.heap[1]=e.heap[e.heap_len--],e.pqdownheap(a,1),i=e.heap[1],e.heap[--e.heap_max]=s,e.heap[--e.heap_max]=i,a[2*o]=a[2*s]+a[2*i],e.depth[o]=Math.max(e.depth[s],e.depth[i])+1,a[2*s+1]=a[2*i+1]=o,e.heap[1]=o++,e.pqdownheap(a,1);while(e.heap_len>=2);e.heap[--e.heap_max]=e.heap[1],t(e),n(a,r.max_code,e.bl_count)}}function e(t,e,n,r,s){var i=this;i.static_tree=t,i.extra_bits=e,i.extra_base=n,i.elems=r,i.max_length=s}function n(t,e,n,r,s){var i=this;i.good_length=t,i.max_lazy=e,i.nice_length=n,i.max_chain=r,i.func=s}function r(t,e,n,r){var s=t[2*e],i=t[2*n];return i>s||s==i&&r[e]<=r[n]}function s(){function n(){var t;for(Te=2*Ce,Be[Pe-1]=0,t=0;Pe-1>t;t++)Be[t]=0;Je=N[Xe].max_lazy,Ke=N[Xe].good_length,Qe=N[Xe].nice_length,Ve=N[Xe].max_chain,Me=0,Ue=0,Ge=0,Ne=We=Z-1,je=0,Oe=0}function s(){var t;for(t=0;f>t;t++)$e[2*t]=0;for(t=0;a>t;t++)Ze[2*t]=0;for(t=0;u>t;t++)tn[2*t]=0;$e[2*h]=1,en.opt_len=en.static_len=0,un=ln=0}function i(){nn.dyn_tree=$e,nn.stat_desc=e.static_l_desc,rn.dyn_tree=Ze,rn.stat_desc=e.static_d_desc,sn.dyn_tree=tn,sn.stat_desc=e.static_bl_desc,dn=0,hn=0,fn=8,s()}function o(t,e){var n,r,s=-1,i=t[1],o=0,a=7,u=4;for(0===i&&(a=138,u=3),t[2*(e+1)+1]=65535,n=0;e>=n;n++)r=i,i=t[2*(n+1)+1],++o<a&&r==i||(u>o?tn[2*r]+=o:0!==r?(r!=s&&tn[2*r]++,tn[2*m]++):10>=o?tn[2*w]++:tn[2*g]++,o=0,s=r,0===i?(a=138,u=3):r==i?(a=6,u=3):(a=7,u=4))}function c(){var e;for(o($e,nn.max_code),o(Ze,rn.max_code),sn.build_tree(en),e=u-1;e>=3&&0===tn[2*t.bl_order[e]+1];e--);return en.opt_len+=3*(e+1)+5+5+4,e}function d(t){en.pending_buf[en.pending++]=t}function p(t){d(255&t),d(t>>>8&255)}function O(t){d(t>>8&255),d(255&t&255)}function ne(t,e){var n,r=e;hn>y-r?(n=t,dn|=n<<hn&65535,p(dn),dn=n>>>y-hn,hn+=r-y):(dn|=t<<hn&65535,hn+=r)}function re(t,e){var n=2*t;ne(65535&e[n],65535&e[n+1])}function se(t,e){var n,r,s=-1,i=t[1],o=0,a=7,u=4;for(0===i&&(a=138,u=3),n=0;e>=n;n++)if(r=i,i=t[2*(n+1)+1],!(++o<a&&r==i)){if(u>o){do re(r,tn);while(0!==--o)}else 0!==r?(r!=s&&(re(r,tn),o--),re(m,tn),ne(o-3,2)):10>=o?(re(w,tn),ne(o-3,3)):(re(g,tn),ne(o-11,7));o=0,s=r,0===i?(a=138,u=3):r==i?(a=6,u=3):(a=7,u=4)}}function ie(e,n,r){var s;for(ne(e-257,5),ne(n-1,5),ne(r-4,4),s=0;r>s;s++)ne(tn[2*t.bl_order[s]+1],3);se($e,e-1),se(Ze,n-1)}function oe(){16==hn?(p(dn),dn=0,hn=0):hn>=8&&(d(255&dn),dn>>>=8,hn-=8)}function ae(){ne(Q<<1,3),re(h,e.static_ltree),oe(),9>1+fn+10-hn&&(ne(Q<<1,3),re(h,e.static_ltree),oe()),fn=7}function ue(e,n){var r,s,i;if(en.pending_buf[cn+2*un]=e>>>8&255,en.pending_buf[cn+2*un+1]=255&e,en.pending_buf[on+un]=255&n,un++,0===e?$e[2*n]++:(ln++,e--,$e[2*(t._length_code[n]+l+1)]++,Ze[2*t.d_code(e)]++),0===(8191&un)&&Xe>2){for(r=8*un,s=Me-Ue,i=0;a>i;i++)r+=Ze[2*i]*(5+t.extra_dbits[i]);if(r>>>=3,ln<Math.floor(un/2)&&r<Math.floor(s/2))return!0}return un==an-1}function ce(e,n){var r,s,i,o,a=0;if(0!==un)do r=en.pending_buf[cn+2*a]<<8&65280|255&en.pending_buf[cn+2*a+1],s=255&en.pending_buf[on+a],a++,0===r?re(s,e):(i=t._length_code[s],re(i+l+1,e),o=t.extra_lbits[i],0!==o&&(s-=t.base_length[i],ne(s,o)),r--,i=t.d_code(r),re(i,n),o=t.extra_dbits[i],0!==o&&(r-=t.base_dist[i],ne(r,o)));while(un>a);re(h,e),fn=e[2*h+1]}function le(){hn>8?p(dn):hn>0&&d(255&dn),dn=0,hn=0}function fe(t,e,n){le(),fn=8,n&&(p(e),p(~e)),en.pending_buf.set(ze.subarray(t,t+e),en.pending),en.pending+=e}function de(t,e,n){ne((K<<1)+(n?1:0),3),fe(t,e,!0)}function he(t,n,r){var i,o,a=0;Xe>0?(nn.build_tree(en),rn.build_tree(en),a=c(),i=en.opt_len+3+7>>>3,o=en.static_len+3+7>>>3,i>=o&&(i=o)):i=o=n+5,i>=n+4&&-1!=t?de(t,n,r):o==i?(ne((Q<<1)+(r?1:0),3),ce(e.static_ltree,e.static_dtree)):(ne(($<<1)+(r?1:0),3),ie(nn.max_code+1,rn.max_code+1,a+1),ce($e,Ze)),s(),r&&le()}function pe(t){he(Ue>=0?Ue:-1,Me-Ue,t),Ue=Me,qe.flush_pending()}function me(){var t,e,n,r;do{if(r=Te-Ge-Me,0===r&&0===Me&&0===Ge)r=Ce;else if(-1==r)r--;else if(Me>=Ce+Ce-ee){ze.set(ze.subarray(Ce,Ce+Ce),0),He-=Ce,Me-=Ce,Ue-=Ce,t=Pe,n=t;do e=65535&Be[--n],Be[n]=e>=Ce?e-Ce:0;while(0!==--t);t=Ce,n=t;do e=65535&Ie[--n],Ie[n]=e>=Ce?e-Ce:0;while(0!==--t);r+=Ce}if(0===qe.avail_in)return;t=qe.read_buf(ze,Me+Ge,r),Ge+=t,Ge>=Z&&(Oe=255&ze[Me],Oe=(Oe<<De^255&ze[Me+1])&Fe)}while(ee>Ge&&0!==qe.avail_in)}function we(t){var e,n=65535;for(n>ke-5&&(n=ke-5);;){if(1>=Ge){if(me(),0===Ge&&t==k)return j;if(0===Ge)break}if(Me+=Ge,Ge=0,e=Ue+n,(0===Me||Me>=e)&&(Ge=Me-e,Me=e,pe(!1),0===qe.avail_out))return j;if(Me-Ue>=Ce-ee&&(pe(!1),0===qe.avail_out))return j}return pe(t==C),0===qe.avail_out?t==C?H:j:t==C?G:M}function ge(t){var e,n,r=Ve,s=Me,i=We,o=Me>Ce-ee?Me-(Ce-ee):0,a=Qe,u=Ee,c=Me+te,l=ze[s+i-1],f=ze[s+i];We>=Ke&&(r>>=2),a>Ge&&(a=Ge);do if(e=t,ze[e+i]==f&&ze[e+i-1]==l&&ze[e]==ze[s]&&ze[++e]==ze[s+1]){s+=2,e++;do;while(ze[++s]==ze[++e]&&ze[++s]==ze[++e]&&ze[++s]==ze[++e]&&ze[++s]==ze[++e]&&ze[++s]==ze[++e]&&ze[++s]==ze[++e]&&ze[++s]==ze[++e]&&ze[++s]==ze[++e]&&c>s);if(n=te-(c-s),s=c-te,n>i){if(He=t,i=n,n>=a)break;l=ze[s+i-1],f=ze[s+i]}}while((t=65535&Ie[t&u])>o&&0!==--r);return Ge>=i?i:Ge}function ye(t){for(var e,n=0;;){if(ee>Ge){if(me(),ee>Ge&&t==k)return j;if(0===Ge)break}if(Ge>=Z&&(Oe=(Oe<<De^255&ze[Me+(Z-1)])&Fe,n=65535&Be[Oe],Ie[Me&Ee]=Be[Oe],Be[Oe]=Me),0!==n&&Ce-ee>=(Me-n&65535)&&Ye!=q&&(Ne=ge(n)),Ne>=Z)if(e=ue(Me-He,Ne-Z),Ge-=Ne,Je>=Ne&&Ge>=Z){Ne--;do Me++,Oe=(Oe<<De^255&ze[Me+(Z-1)])&Fe,n=65535&Be[Oe],Ie[Me&Ee]=Be[Oe],Be[Oe]=Me;while(0!==--Ne);Me++}else Me+=Ne,Ne=0,Oe=255&ze[Me],Oe=(Oe<<De^255&ze[Me+1])&Fe;else e=ue(0,255&ze[Me]),Ge--,Me++;if(e&&(pe(!1),0===qe.avail_out))return j}return pe(t==C),0===qe.avail_out?t==C?H:j:t==C?G:M}function ve(t){for(var e,n,r=0;;){if(ee>Ge){if(me(),ee>Ge&&t==k)return j;if(0===Ge)break}if(Ge>=Z&&(Oe=(Oe<<De^255&ze[Me+(Z-1)])&Fe,r=65535&Be[Oe],Ie[Me&Ee]=Be[Oe],Be[Oe]=Me),We=Ne,Le=He,Ne=Z-1,0!==r&&Je>We&&Ce-ee>=(Me-r&65535)&&(Ye!=q&&(Ne=ge(r)),5>=Ne&&(Ye==b||Ne==Z&&Me-He>4096)&&(Ne=Z-1)),We>=Z&&We>=Ne){n=Me+Ge-Z,e=ue(Me-1-Le,We-Z),Ge-=We-1,We-=2;do++Me<=n&&(Oe=(Oe<<De^255&ze[Me+(Z-1)])&Fe,r=65535&Be[Oe],Ie[Me&Ee]=Be[Oe],Be[Oe]=Me);while(0!==--We);if(je=0,Ne=Z-1,Me++,e&&(pe(!1),0===qe.avail_out))return j}else if(0!==je){if(e=ue(0,255&ze[Me-1]),e&&pe(!1),Me++,Ge--,0===qe.avail_out)return j}else je=1,Me++,Ge--}return 0!==je&&(e=ue(0,255&ze[Me-1]),je=0),pe(t==C),0===qe.avail_out?t==C?H:j:t==C?G:M}function be(t){return t.total_in=t.total_out=0,t.msg=null,en.pending=0,en.pending_out=0,xe=J,Ae=k,i(),n(),S}var qe,xe,ke,_e,Ae,Ce,Se,Ee,ze,Te,Ie,Be,Oe,Pe,Re,Fe,De,Ue,Ne,Le,je,Me,He,Ge,We,Ve,Je,Xe,Ye,Ke,Qe,$e,Ze,tn,en=this,nn=new t,rn=new t,sn=new t;en.depth=[];var on,an,un,cn,ln,fn,dn,hn;en.bl_count=[],en.heap=[],$e=[],Ze=[],tn=[],en.pqdownheap=function(t,e){for(var n=en.heap,s=n[e],i=e<<1;i<=en.heap_len&&(i<en.heap_len&&r(t,n[i+1],n[i],en.depth)&&i++,!r(t,s,n[i],en.depth));)n[e]=n[i],e=i,i<<=1;n[e]=s},en.deflateInit=function(t,e,n,r,s,i){return r||(r=Y),s||(s=R),i||(i=x),t.msg=null,e==v&&(e=6),1>s||s>P||r!=Y||9>n||n>15||0>e||e>9||0>i||i>q?T:(t.dstate=en,Se=n,Ce=1<<Se,Ee=Ce-1,Re=s+7,Pe=1<<Re,Fe=Pe-1,De=Math.floor((Re+Z-1)/Z),ze=new Uint8Array(2*Ce),Ie=[],Be=[],an=1<<s+6,en.pending_buf=new Uint8Array(4*an),ke=4*an,cn=Math.floor(an/2),on=3*an,Xe=e,Ye=i,_e=255&r,be(t))},en.deflateEnd=function(){return xe!=V&&xe!=J&&xe!=X?T:(en.pending_buf=null,Be=null,Ie=null,ze=null,en.dstate=null,xe==J?I:S)},en.deflateParams=function(t,e,n){var r=S;return e==v&&(e=6),0>e||e>9||0>n||n>q?T:(N[Xe].func!=N[e].func&&0!==t.total_in&&(r=t.deflate(_)),Xe!=e&&(Xe=e,Je=N[Xe].max_lazy,Ke=N[Xe].good_length,Qe=N[Xe].nice_length,Ve=N[Xe].max_chain),Ye=n,r)},en.deflateSetDictionary=function(t,e,n){var r,s=n,i=0;if(!e||xe!=V)return T;if(Z>s)return S;for(s>Ce-ee&&(s=Ce-ee,i=n-s),ze.set(e.subarray(i,i+s),0),Me=s,Ue=s,Oe=255&ze[0],Oe=(Oe<<De^255&ze[1])&Fe,r=0;s-Z>=r;r++)Oe=(Oe<<De^255&ze[r+(Z-1)])&Fe,Ie[r&Ee]=Be[Oe],Be[Oe]=r;return S},en.deflate=function(t,e){var n,r,s,i,o;if(e>C||0>e)return T;if(!t.next_out||!t.next_in&&0!==t.avail_in||xe==X&&e!=C)return t.msg=L[z-T],T;if(0===t.avail_out)return t.msg=L[z-B],B;if(qe=t,i=Ae,Ae=e,xe==V&&(r=Y+(Se-8<<4)<<8,s=(Xe-1&255)>>1,s>3&&(s=3),r|=s<<6,0!==Me&&(r|=W),r+=31-r%31,xe=J,O(r)),0!==en.pending){if(qe.flush_pending(),0===qe.avail_out)return Ae=-1,S}else if(0===qe.avail_in&&i>=e&&e!=C)return qe.msg=L[z-B],B;if(xe==X&&0!==qe.avail_in)return t.msg=L[z-B],B;if(0!==qe.avail_in||0!==Ge||e!=k&&xe!=X){switch(o=-1,N[Xe].func){case F:o=we(e);break;case D:o=ye(e);break;case U:o=ve(e)}if((o==H||o==G)&&(xe=X),o==j||o==H)return 0===qe.avail_out&&(Ae=-1),S;if(o==M){if(e==_)ae();else if(de(0,0,!1),e==A)for(n=0;Pe>n;n++)Be[n]=0;if(qe.flush_pending(),0===qe.avail_out)return Ae=-1,S}}return e!=C?S:E}}function i(){var t=this;t.next_in_index=0,t.next_out_index=0,t.avail_in=0,t.total_in=0,t.avail_out=0,t.total_out=0}var o=15,a=30,u=19,c=29,l=256,f=l+1+c,d=2*f+1,h=256,p=7,m=16,w=17,g=18,y=16,v=-1,b=1,q=2,x=0,k=0,_=1,A=3,C=4,S=0,E=1,z=2,T=-2,I=-3,B=-5,O=[0,1,2,3,4,4,5,5,6,6,6,6,7,7,7,7,8,8,8,8,8,8,8,8,9,9,9,9,9,9,9,9,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,0,0,16,17,18,18,19,19,20,20,20,20,21,21,21,21,22,22,22,22,22,22,22,22,23,23,23,23,23,23,23,23,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29];t._length_code=[0,1,2,3,4,5,6,7,8,8,9,9,10,10,11,11,12,12,12,12,13,13,13,13,14,14,14,14,15,15,15,15,16,16,16,16,16,16,16,16,17,17,17,17,17,17,17,17,18,18,18,18,18,18,18,18,19,19,19,19,19,19,19,19,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,28],t.base_length=[0,1,2,3,4,5,6,7,8,10,12,14,16,20,24,28,32,40,48,56,64,80,96,112,128,160,192,224,0],t.base_dist=[0,1,2,3,4,6,8,12,16,24,32,48,64,96,128,192,256,384,512,768,1024,1536,2048,3072,4096,6144,8192,12288,16384,24576],t.d_code=function(t){return 256>t?O[t]:O[256+(t>>>7)]},t.extra_lbits=[0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0],t.extra_dbits=[0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13],t.extra_blbits=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7],t.bl_order=[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15],e.static_ltree=[12,8,140,8,76,8,204,8,44,8,172,8,108,8,236,8,28,8,156,8,92,8,220,8,60,8,188,8,124,8,252,8,2,8,130,8,66,8,194,8,34,8,162,8,98,8,226,8,18,8,146,8,82,8,210,8,50,8,178,8,114,8,242,8,10,8,138,8,74,8,202,8,42,8,170,8,106,8,234,8,26,8,154,8,90,8,218,8,58,8,186,8,122,8,250,8,6,8,134,8,70,8,198,8,38,8,166,8,102,8,230,8,22,8,150,8,86,8,214,8,54,8,182,8,118,8,246,8,14,8,142,8,78,8,206,8,46,8,174,8,110,8,238,8,30,8,158,8,94,8,222,8,62,8,190,8,126,8,254,8,1,8,129,8,65,8,193,8,33,8,161,8,97,8,225,8,17,8,145,8,81,8,209,8,49,8,177,8,113,8,241,8,9,8,137,8,73,8,201,8,41,8,169,8,105,8,233,8,25,8,153,8,89,8,217,8,57,8,185,8,121,8,249,8,5,8,133,8,69,8,197,8,37,8,165,8,101,8,229,8,21,8,149,8,85,8,213,8,53,8,181,8,117,8,245,8,13,8,141,8,77,8,205,8,45,8,173,8,109,8,237,8,29,8,157,8,93,8,221,8,61,8,189,8,125,8,253,8,19,9,275,9,147,9,403,9,83,9,339,9,211,9,467,9,51,9,307,9,179,9,435,9,115,9,371,9,243,9,499,9,11,9,267,9,139,9,395,9,75,9,331,9,203,9,459,9,43,9,299,9,171,9,427,9,107,9,363,9,235,9,491,9,27,9,283,9,155,9,411,9,91,9,347,9,219,9,475,9,59,9,315,9,187,9,443,9,123,9,379,9,251,9,507,9,7,9,263,9,135,9,391,9,71,9,327,9,199,9,455,9,39,9,295,9,167,9,423,9,103,9,359,9,231,9,487,9,23,9,279,9,151,9,407,9,87,9,343,9,215,9,471,9,55,9,311,9,183,9,439,9,119,9,375,9,247,9,503,9,15,9,271,9,143,9,399,9,79,9,335,9,207,9,463,9,47,9,303,9,175,9,431,9,111,9,367,9,239,9,495,9,31,9,287,9,159,9,415,9,95,9,351,9,223,9,479,9,63,9,319,9,191,9,447,9,127,9,383,9,255,9,511,9,0,7,64,7,32,7,96,7,16,7,80,7,48,7,112,7,8,7,72,7,40,7,104,7,24,7,88,7,56,7,120,7,4,7,68,7,36,7,100,7,20,7,84,7,52,7,116,7,3,8,131,8,67,8,195,8,35,8,163,8,99,8,227,8],e.static_dtree=[0,5,16,5,8,5,24,5,4,5,20,5,12,5,28,5,2,5,18,5,10,5,26,5,6,5,22,5,14,5,30,5,1,5,17,5,9,5,25,5,5,5,21,5,13,5,29,5,3,5,19,5,11,5,27,5,7,5,23,5],e.static_l_desc=new e(e.static_ltree,t.extra_lbits,l+1,f,o),e.static_d_desc=new e(e.static_dtree,t.extra_dbits,0,a,o),e.static_bl_desc=new e(null,t.extra_blbits,0,u,p);var P=9,R=8,F=0,D=1,U=2,N=[new n(0,0,0,0,F),new n(4,4,8,4,D),new n(4,5,16,8,D),new n(4,6,32,32,D),new n(4,4,16,16,U),new n(8,16,32,32,U),new n(8,16,128,128,U),new n(8,32,128,256,U),new n(32,128,258,1024,U),new n(32,258,258,4096,U)],L=["need dictionary","stream end","","","stream error","data error","","buffer error","",""],j=0,M=1,H=2,G=3,W=32,V=42,J=113,X=666,Y=8,K=0,Q=1,$=2,Z=3,te=258,ee=te+Z+1;return i.prototype={deflateInit:function(t,e){var n=this;return n.dstate=new s,e||(e=o),n.dstate.deflateInit(n,t,e)},deflate:function(t){var e=this;return e.dstate?e.dstate.deflate(e,t):T},deflateEnd:function(){var t=this;if(!t.dstate)return T;var e=t.dstate.deflateEnd();return t.dstate=null,e},deflateParams:function(t,e){var n=this;return n.dstate?n.dstate.deflateParams(n,t,e):T},deflateSetDictionary:function(t,e){var n=this;return n.dstate?n.dstate.deflateSetDictionary(n,t,e):T},read_buf:function(t,e,n){var r=this,s=r.avail_in;return s>n&&(s=n),0===s?0:(r.avail_in-=s,t.set(r.next_in.subarray(r.next_in_index,r.next_in_index+s),e),r.next_in_index+=s,r.total_in+=s,s)},flush_pending:function(){var t=this,e=t.dstate.pending;e>t.avail_out&&(e=t.avail_out),0!==e&&(t.next_out.set(t.dstate.pending_buf.subarray(t.dstate.pending_out,t.dstate.pending_out+e),t.next_out_index),t.next_out_index+=e,t.dstate.pending_out+=e,t.total_out+=e,t.avail_out-=e,t.dstate.pending-=e,0===t.dstate.pending&&(t.dstate.pending_out=0))}},function(t){var e=this,n=new i,r=512,s=k,o=new Uint8Array(r);"undefined"==typeof t&&(t=v),n.deflateInit(t),n.next_out=o,e.append=function(t,e){var i,a,u=[],c=0,l=0,f=0;if(t.length){n.next_in_index=0,n.next_in=t,n.avail_in=t.length;do{if(n.next_out_index=0,n.avail_out=r,i=n.deflate(s),i!=S)throw"deflating: "+n.msg;n.next_out_index&&u.push(n.next_out_index==r?new Uint8Array(o):new Uint8Array(o.subarray(0,n.next_out_index))),f+=n.next_out_index,e&&n.next_in_index>0&&n.next_in_index!=c&&(e(n.next_in_index),c=n.next_in_index)}while(n.avail_in>0||0===n.avail_out);return a=new Uint8Array(f),u.forEach(function(t){a.set(t,l),l+=t.length}),a}},e.flush=function(){var t,e,s=[],i=0,a=0;do{if(n.next_out_index=0,n.avail_out=r,t=n.deflate(C),t!=E&&t!=S)throw"deflating: "+n.msg;r-n.avail_out>0&&s.push(new Uint8Array(o.subarray(0,n.next_out_index))),a+=n.next_out_index}while(n.avail_in>0||0===n.avail_out);return n.deflateEnd(),e=new Uint8Array(a),s.forEach(function(t){e.set(t,i),i+=t.length}),e}}}(this);!function(t){var e;e=function(){function e(t){var e,n,r,s,i,o,a,u,c,l,f,d,h,p,m;for(this.data=t,this.pos=8,this.palette=[],this.imgData=[],this.transparency={},this.animation=null,this.text={},o=null;;){switch(e=this.readUInt32(),l=function(){var t,e;for(e=[],a=t=0;4>t;a=++t)e.push(String.fromCharCode(this.data[this.pos++]));return e}.call(this).join("")){case"IHDR":this.width=this.readUInt32(),this.height=this.readUInt32(),this.bits=this.data[this.pos++],this.colorType=this.data[this.pos++],this.compressionMethod=this.data[this.pos++],this.filterMethod=this.data[this.pos++],this.interlaceMethod=this.data[this.pos++];break;case"acTL":this.animation={numFrames:this.readUInt32(),numPlays:this.readUInt32()||1/0,frames:[]};break;case"PLTE":this.palette=this.read(e);break;case"fcTL":o&&this.animation.frames.push(o),this.pos+=4,o={width:this.readUInt32(),height:this.readUInt32(),xOffset:this.readUInt32(),yOffset:this.readUInt32()},i=this.readUInt16(),s=this.readUInt16()||100,o.delay=1e3*i/s,o.disposeOp=this.data[this.pos++],o.blendOp=this.data[this.pos++],o.data=[];break;case"IDAT":case"fdAT":for("fdAT"===l&&(this.pos+=4,e-=4),t=(null!=o?o.data:void 0)||this.imgData,a=h=0;e>=0?e>h:h>e;a=e>=0?++h:--h)t.push(this.data[this.pos++]);break;case"tRNS":switch(this.transparency={},this.colorType){case 3:if(r=this.palette.length/3,this.transparency.indexed=this.read(e),this.transparency.indexed.length>r)throw new Error("More transparent colors than palette size");if(f=r-this.transparency.indexed.length,f>0)for(a=p=0;f>=0?f>p:p>f;a=f>=0?++p:--p)this.transparency.indexed.push(255);break;case 0:this.transparency.grayscale=this.read(e)[0];break;case 2:this.transparency.rgb=this.read(e)}break;case"tEXt":d=this.read(e),u=d.indexOf(0),c=String.fromCharCode.apply(String,d.slice(0,u)),this.text[c]=String.fromCharCode.apply(String,d.slice(u+1));break;case"IEND":return o&&this.animation.frames.push(o),this.colors=function(){switch(this.colorType){case 0:case 3:case 4:return 1;case 2:case 6:return 3}}.call(this),this.hasAlphaChannel=4===(m=this.colorType)||6===m,n=this.colors+(this.hasAlphaChannel?1:0),this.pixelBitlength=this.bits*n,this.colorSpace=function(){switch(this.colors){case 1:return"DeviceGray";case 3:return"DeviceRGB"}}.call(this),void(this.imgData=new Uint8Array(this.imgData));default:this.pos+=e}if(this.pos+=4,this.pos>this.data.length)throw new Error("Incomplete or corrupt PNG file")}}var n,r,s,i,a,u,c,l;e.load=function(t,n,r){var s;return"function"==typeof n&&(r=n),s=new XMLHttpRequest,s.open("GET",t,!0),s.responseType="arraybuffer",s.onload=function(){var t,i;return t=new Uint8Array(s.response||s.mozResponseArrayBuffer),i=new e(t),"function"==typeof(null!=n?n.getContext:void 0)&&i.render(n),"function"==typeof r?r(i):void 0},s.send(null)},i=0,s=1,a=2,r=0,n=1,e.prototype.read=function(t){var e,n,r;for(r=[],e=n=0;t>=0?t>n:n>t;e=t>=0?++n:--n)r.push(this.data[this.pos++]);return r},e.prototype.readUInt32=function(){var t,e,n,r;return t=this.data[this.pos++]<<24,e=this.data[this.pos++]<<16,n=this.data[this.pos++]<<8,r=this.data[this.pos++],t|e|n|r},e.prototype.readUInt16=function(){var t,e;return t=this.data[this.pos++]<<8,e=this.data[this.pos++],t|e},e.prototype.decodePixels=function(t){var e,n,r,s,i,a,u,c,l,f,d,h,p,m,w,g,y,v,b,q,x,k,_;if(null==t&&(t=this.imgData),0===t.length)return new Uint8Array(0);for(t=new o(t),t=t.getBytes(),h=this.pixelBitlength/8,g=h*this.width,p=new Uint8Array(g*this.height),a=t.length,w=0,m=0,n=0;a>m;){switch(t[m++]){case 0:for(s=b=0;g>b;s=b+=1)p[n++]=t[m++];break;case 1:for(s=q=0;g>q;s=q+=1)e=t[m++],i=h>s?0:p[n-h],p[n++]=(e+i)%256;break;case 2:for(s=x=0;g>x;s=x+=1)e=t[m++],r=(s-s%h)/h,y=w&&p[(w-1)*g+r*h+s%h],p[n++]=(y+e)%256;break;case 3:for(s=k=0;g>k;s=k+=1)e=t[m++],r=(s-s%h)/h,i=h>s?0:p[n-h],y=w&&p[(w-1)*g+r*h+s%h],p[n++]=(e+Math.floor((i+y)/2))%256;break;case 4:for(s=_=0;g>_;s=_+=1)e=t[m++],r=(s-s%h)/h,i=h>s?0:p[n-h],0===w?y=v=0:(y=p[(w-1)*g+r*h+s%h],v=r&&p[(w-1)*g+(r-1)*h+s%h]),u=i+y-v,c=Math.abs(u-i),f=Math.abs(u-y),d=Math.abs(u-v),l=f>=c&&d>=c?i:d>=f?y:v,p[n++]=(e+l)%256;break;default:throw new Error("Invalid filter algorithm: "+t[m-1])}w++}return p},e.prototype.decodePalette=function(){var t,e,n,r,s,i,o,a,u,c;for(r=this.palette,o=this.transparency.indexed||[],i=new Uint8Array((o.length||0)+r.length),s=0,n=r.length,t=0,e=a=0,u=r.length;u>a;e=a+=3)i[s++]=r[e],i[s++]=r[e+1],i[s++]=r[e+2],i[s++]=null!=(c=o[t++])?c:255;return i},e.prototype.copyToImageData=function(t,e){var n,r,s,i,o,a,u,c,l,f,d;if(r=this.colors,l=null,n=this.hasAlphaChannel,this.palette.length&&(l=null!=(d=this._decodedPalette)?d:this._decodedPalette=this.decodePalette(),r=4,n=!0),s=t.data||t,c=s.length,o=l||e,i=a=0,1===r)for(;c>i;)u=l?4*e[i/4]:a,f=o[u++],s[i++]=f,s[i++]=f,s[i++]=f,s[i++]=n?o[u++]:255,a=u;else for(;c>i;)u=l?4*e[i/4]:a,s[i++]=o[u++],s[i++]=o[u++],s[i++]=o[u++],s[i++]=n?o[u++]:255,a=u},e.prototype.decode=function(){var t;return t=new Uint8Array(this.width*this.height*4),this.copyToImageData(t,this.decodePixels()),t};try{c=t.document.createElement("canvas"),l=c.getContext("2d")}catch(f){return-1}return u=function(t){var e;return l.width=t.width,l.height=t.height,l.clearRect(0,0,t.width,t.height),l.putImageData(t,0,0),e=new Image,e.src=c.toDataURL(),e},e.prototype.decodeFrames=function(t){var e,n,r,s,i,o,a,c;if(this.animation){for(a=this.animation.frames,c=[],n=i=0,o=a.length;o>i;n=++i)e=a[n],r=t.createImageData(e.width,e.height),s=this.decodePixels(new Uint8Array(e.data)),this.copyToImageData(r,s),e.imageData=r,c.push(e.image=u(r));return c}},e.prototype.renderFrame=function(t,e){var n,i,o;return i=this.animation.frames,n=i[e],o=i[e-1],0===e&&t.clearRect(0,0,this.width,this.height),(null!=o?o.disposeOp:void 0)===s?t.clearRect(o.xOffset,o.yOffset,o.width,o.height):(null!=o?o.disposeOp:void 0)===a&&t.putImageData(o.imageData,o.xOffset,o.yOffset),n.blendOp===r&&t.clearRect(n.xOffset,n.yOffset,n.width,n.height),t.drawImage(n.image,n.xOffset,n.yOffset)},e.prototype.animate=function(t){var e,n,r,s,i,o,a=this;return n=0,o=this.animation,s=o.numFrames,r=o.frames,i=o.numPlays,(e=function(){var o,u;return o=n++%s,u=r[o],a.renderFrame(t,o),s>1&&i>n/s?a.animation._timeout=setTimeout(e,u.delay):void 0 +})()},e.prototype.stopAnimation=function(){var t;return clearTimeout(null!=(t=this.animation)?t._timeout:void 0)},e.prototype.render=function(t){var e,n;return t._png&&t._png.stopAnimation(),t._png=this,t.width=this.width,t.height=this.height,e=t.getContext("2d"),this.animation?(this.decodeFrames(e),this.animate(e)):(n=e.createImageData(this.width,this.height),this.copyToImageData(n,this.decodePixels()),e.putImageData(n,0,0))},e}(),t.PNG=e}("undefined"!=typeof window&&window||this);var i=function(){function t(){this.pos=0,this.bufferLength=0,this.eof=!1,this.buffer=null}return t.prototype={ensureBuffer:function(t){var e=this.buffer,n=e?e.byteLength:0;if(n>t)return e;for(var r=512;t>r;)r<<=1;for(var s=new Uint8Array(r),i=0;n>i;++i)s[i]=e[i];return this.buffer=s},getByte:function(){for(var t=this.pos;this.bufferLength<=t;){if(this.eof)return null;this.readBlock()}return this.buffer[this.pos++]},getBytes:function(t){var e=this.pos;if(t){this.ensureBuffer(e+t);for(var n=e+t;!this.eof&&this.bufferLength<n;)this.readBlock();var r=this.bufferLength;n>r&&(n=r)}else{for(;!this.eof;)this.readBlock();var n=this.bufferLength}return this.pos=n,this.buffer.subarray(e,n)},lookChar:function(){for(var t=this.pos;this.bufferLength<=t;){if(this.eof)return null;this.readBlock()}return String.fromCharCode(this.buffer[this.pos])},getChar:function(){for(var t=this.pos;this.bufferLength<=t;){if(this.eof)return null;this.readBlock()}return String.fromCharCode(this.buffer[this.pos++])},makeSubStream:function(t,e,n){for(var r=t+e;this.bufferLength<=r&&!this.eof;)this.readBlock();return new Stream(this.buffer,t,e,n)},skip:function(t){t||(t=1),this.pos+=t},reset:function(){this.pos=0}},t}(),o=function(){function t(t){throw new Error(t)}function e(e){var n=0,r=e[n++],s=e[n++];(-1==r||-1==s)&&t("Invalid header in flate stream"),8!=(15&r)&&t("Unknown compression method in flate stream"),((r<<8)+s)%31!=0&&t("Bad FCHECK in flate stream"),32&s&&t("FDICT bit set in flate stream"),this.bytes=e,this.bytesPos=n,this.codeSize=0,this.codeBuf=0,i.call(this)}if("undefined"==typeof Uint32Array)return void 0;var n=new Uint32Array([16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15]),r=new Uint32Array([3,4,5,6,7,8,9,10,65547,65549,65551,65553,131091,131095,131099,131103,196643,196651,196659,196667,262211,262227,262243,262259,327811,327843,327875,327907,258,258,258]),s=new Uint32Array([1,2,3,4,65541,65543,131081,131085,196625,196633,262177,262193,327745,327777,393345,393409,459009,459137,524801,525057,590849,591361,657409,658433,724993,727041,794625,798721,868353,876545]),o=[new Uint32Array([459008,524368,524304,524568,459024,524400,524336,590016,459016,524384,524320,589984,524288,524416,524352,590048,459012,524376,524312,589968,459028,524408,524344,590032,459020,524392,524328,59e4,524296,524424,524360,590064,459010,524372,524308,524572,459026,524404,524340,590024,459018,524388,524324,589992,524292,524420,524356,590056,459014,524380,524316,589976,459030,524412,524348,590040,459022,524396,524332,590008,524300,524428,524364,590072,459009,524370,524306,524570,459025,524402,524338,590020,459017,524386,524322,589988,524290,524418,524354,590052,459013,524378,524314,589972,459029,524410,524346,590036,459021,524394,524330,590004,524298,524426,524362,590068,459011,524374,524310,524574,459027,524406,524342,590028,459019,524390,524326,589996,524294,524422,524358,590060,459015,524382,524318,589980,459031,524414,524350,590044,459023,524398,524334,590012,524302,524430,524366,590076,459008,524369,524305,524569,459024,524401,524337,590018,459016,524385,524321,589986,524289,524417,524353,590050,459012,524377,524313,589970,459028,524409,524345,590034,459020,524393,524329,590002,524297,524425,524361,590066,459010,524373,524309,524573,459026,524405,524341,590026,459018,524389,524325,589994,524293,524421,524357,590058,459014,524381,524317,589978,459030,524413,524349,590042,459022,524397,524333,590010,524301,524429,524365,590074,459009,524371,524307,524571,459025,524403,524339,590022,459017,524387,524323,589990,524291,524419,524355,590054,459013,524379,524315,589974,459029,524411,524347,590038,459021,524395,524331,590006,524299,524427,524363,590070,459011,524375,524311,524575,459027,524407,524343,590030,459019,524391,524327,589998,524295,524423,524359,590062,459015,524383,524319,589982,459031,524415,524351,590046,459023,524399,524335,590014,524303,524431,524367,590078,459008,524368,524304,524568,459024,524400,524336,590017,459016,524384,524320,589985,524288,524416,524352,590049,459012,524376,524312,589969,459028,524408,524344,590033,459020,524392,524328,590001,524296,524424,524360,590065,459010,524372,524308,524572,459026,524404,524340,590025,459018,524388,524324,589993,524292,524420,524356,590057,459014,524380,524316,589977,459030,524412,524348,590041,459022,524396,524332,590009,524300,524428,524364,590073,459009,524370,524306,524570,459025,524402,524338,590021,459017,524386,524322,589989,524290,524418,524354,590053,459013,524378,524314,589973,459029,524410,524346,590037,459021,524394,524330,590005,524298,524426,524362,590069,459011,524374,524310,524574,459027,524406,524342,590029,459019,524390,524326,589997,524294,524422,524358,590061,459015,524382,524318,589981,459031,524414,524350,590045,459023,524398,524334,590013,524302,524430,524366,590077,459008,524369,524305,524569,459024,524401,524337,590019,459016,524385,524321,589987,524289,524417,524353,590051,459012,524377,524313,589971,459028,524409,524345,590035,459020,524393,524329,590003,524297,524425,524361,590067,459010,524373,524309,524573,459026,524405,524341,590027,459018,524389,524325,589995,524293,524421,524357,590059,459014,524381,524317,589979,459030,524413,524349,590043,459022,524397,524333,590011,524301,524429,524365,590075,459009,524371,524307,524571,459025,524403,524339,590023,459017,524387,524323,589991,524291,524419,524355,590055,459013,524379,524315,589975,459029,524411,524347,590039,459021,524395,524331,590007,524299,524427,524363,590071,459011,524375,524311,524575,459027,524407,524343,590031,459019,524391,524327,589999,524295,524423,524359,590063,459015,524383,524319,589983,459031,524415,524351,590047,459023,524399,524335,590015,524303,524431,524367,590079]),9],a=[new Uint32Array([327680,327696,327688,327704,327684,327700,327692,327708,327682,327698,327690,327706,327686,327702,327694,0,327681,327697,327689,327705,327685,327701,327693,327709,327683,327699,327691,327707,327687,327703,327695,0]),5];return e.prototype=Object.create(i.prototype),e.prototype.getBits=function(e){for(var n,r=this.codeSize,s=this.codeBuf,i=this.bytes,o=this.bytesPos;e>r;)"undefined"==typeof(n=i[o++])&&t("Bad encoding in flate stream"),s|=n<<r,r+=8;return n=s&(1<<e)-1,this.codeBuf=s>>e,this.codeSize=r-=e,this.bytesPos=o,n},e.prototype.getCode=function(e){for(var n=e[0],r=e[1],s=this.codeSize,i=this.codeBuf,o=this.bytes,a=this.bytesPos;r>s;){var u;"undefined"==typeof(u=o[a++])&&t("Bad encoding in flate stream"),i|=u<<s,s+=8}var c=n[i&(1<<r)-1],l=c>>16,f=65535&c;return(0==s||l>s||0==l)&&t("Bad encoding in flate stream"),this.codeBuf=i>>l,this.codeSize=s-l,this.bytesPos=a,f},e.prototype.generateHuffmanTable=function(t){for(var e=t.length,n=0,r=0;e>r;++r)t[r]>n&&(n=t[r]);for(var s=1<<n,i=new Uint32Array(s),o=1,a=0,u=2;n>=o;++o,a<<=1,u<<=1)for(var c=0;e>c;++c)if(t[c]==o){for(var l=0,f=a,r=0;o>r;++r)l=l<<1|1&f,f>>=1;for(var r=l;s>r;r+=u)i[r]=o<<16|c;++a}return[i,n]},e.prototype.readBlock=function(){function e(t,e,n,r,s){for(var i=t.getBits(n)+r;i-->0;)e[k++]=s}var i=this.getBits(3);if(1&i&&(this.eof=!0),i>>=1,0==i){var u,c=this.bytes,l=this.bytesPos;"undefined"==typeof(u=c[l++])&&t("Bad block header in flate stream");var f=u;"undefined"==typeof(u=c[l++])&&t("Bad block header in flate stream"),f|=u<<8,"undefined"==typeof(u=c[l++])&&t("Bad block header in flate stream");var d=u;"undefined"==typeof(u=c[l++])&&t("Bad block header in flate stream"),d|=u<<8,d!=(65535&~f)&&t("Bad uncompressed block length in flate stream"),this.codeBuf=0,this.codeSize=0;var h=this.bufferLength,p=this.ensureBuffer(h+f),m=h+f;this.bufferLength=m;for(var w=h;m>w;++w){if("undefined"==typeof(u=c[l++])){this.eof=!0;break}p[w]=u}return void(this.bytesPos=l)}var g,y;if(1==i)g=o,y=a;else if(2==i){for(var v=this.getBits(5)+257,b=this.getBits(5)+1,q=this.getBits(4)+4,x=Array(n.length),k=0;q>k;)x[n[k++]]=this.getBits(3);for(var _=this.generateHuffmanTable(x),A=0,k=0,C=v+b,S=new Array(C);C>k;){var E=this.getCode(_);16==E?e(this,S,2,3,A):17==E?e(this,S,3,3,A=0):18==E?e(this,S,7,11,A=0):S[k++]=A=E}g=this.generateHuffmanTable(S.slice(0,v)),y=this.generateHuffmanTable(S.slice(v,C))}else t("Unknown block type in flate stream");for(var p=this.buffer,z=p?p.length:0,T=this.bufferLength;;){var I=this.getCode(g);if(256>I)T+1>=z&&(p=this.ensureBuffer(T+1),z=p.length),p[T++]=I;else{if(256==I)return void(this.bufferLength=T);I-=257,I=r[I];var B=I>>16;B>0&&(B=this.getBits(B));var A=(65535&I)+B;I=this.getCode(y),I=s[I],B=I>>16,B>0&&(B=this.getBits(B));var O=(65535&I)+B;T+A>=z&&(p=this.ensureBuffer(T+A),z=p.length);for(var P=0;A>P;++P,++T)p[T]=p[T-O]}}},e}();!function(t){var e="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";"undefined"==typeof t.btoa&&(t.btoa=function(t){var n,r,s,i,o,a,u,c,l=0,f=0,d="",h=[];if(!t)return t;do n=t.charCodeAt(l++),r=t.charCodeAt(l++),s=t.charCodeAt(l++),c=n<<16|r<<8|s,i=c>>18&63,o=c>>12&63,a=c>>6&63,u=63&c,h[f++]=e.charAt(i)+e.charAt(o)+e.charAt(a)+e.charAt(u);while(l<t.length);d=h.join("");var p=t.length%3;return(p?d.slice(0,p-3):d)+"===".slice(p||3)}),"undefined"==typeof t.atob&&(t.atob=function(t){var n,r,s,i,o,a,u,c,l=0,f=0,d="",h=[];if(!t)return t;t+="";do i=e.indexOf(t.charAt(l++)),o=e.indexOf(t.charAt(l++)),a=e.indexOf(t.charAt(l++)),u=e.indexOf(t.charAt(l++)),c=i<<18|o<<12|a<<6|u,n=c>>16&255,r=c>>8&255,s=255&c,h[f++]=64==a?String.fromCharCode(n):64==u?String.fromCharCode(n,r):String.fromCharCode(n,r,s);while(l<t.length);return d=h.join("")}),Array.prototype.map||(Array.prototype.map=function(t){if(void 0===this||null===this||"function"!=typeof t)throw new TypeError;for(var e=Object(this),n=e.length>>>0,r=new Array(n),s=arguments.length>1?arguments[1]:void 0,i=0;n>i;i++)i in e&&(r[i]=t.call(s,e[i],i,e));return r}),Array.isArray||(Array.isArray=function(t){return"[object Array]"===Object.prototype.toString.call(t)}),Array.prototype.forEach||(Array.prototype.forEach=function(t,e){"use strict";if(void 0===this||null===this||"function"!=typeof t)throw new TypeError;for(var n=Object(this),r=n.length>>>0,s=0;r>s;s++)s in n&&t.call(e,n[s],s,n)}),Object.keys||(Object.keys=function(){"use strict";var t=Object.prototype.hasOwnProperty,e=!{toString:null}.propertyIsEnumerable("toString"),n=["toString","toLocaleString","valueOf","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","constructor"],r=n.length;return function(s){if("object"!=typeof s&&("function"!=typeof s||null===s))throw new TypeError;var i,o,a=[];for(i in s)t.call(s,i)&&a.push(i);if(e)for(o=0;r>o;o++)t.call(s,n[o])&&a.push(n[o]);return a}}()),String.prototype.trim||(String.prototype.trim=function(){return this.replace(/^\s+|\s+$/g,"")}),String.prototype.trimLeft||(String.prototype.trimLeft=function(){return this.replace(/^\s+/g,"")}),String.prototype.trimRight||(String.prototype.trimRight=function(){return this.replace(/\s+$/g,"")})}("undefined"!=typeof self&&self||"undefined"!=typeof window&&window||this)}({},function(){return this}()); \ No newline at end of file From 22be076504d62962c81ce4f275cff8babed5f4b8 Mon Sep 17 00:00:00 2001 From: snipe <snipe@snipe.net> Date: Mon, 27 Jul 2015 22:39:47 -0700 Subject: [PATCH 009/120] More experiments --- app/controllers/admin/AssetsController.php | 13 ++++++++--- app/models/Asset.php | 27 ++++++++++++++++++++-- app/views/backend/hardware/index.blade.php | 4 ++-- 3 files changed, 37 insertions(+), 7 deletions(-) diff --git a/app/controllers/admin/AssetsController.php b/app/controllers/admin/AssetsController.php index 5a1b7b0c12..f7385f42c2 100755 --- a/app/controllers/admin/AssetsController.php +++ b/app/controllers/admin/AssetsController.php @@ -27,6 +27,7 @@ use Mail; use Datatable; use TCPDF; use Slack; +use Paginator; class AssetsController extends AdminController { @@ -1068,7 +1069,13 @@ class AssetsController extends AdminController $assets->where('order_number','=',e(Input::get('order_number'))); } - $assets = $assets->orderBy('asset_tag', 'ASC')->get(); + $assets = $assets->orderBy('asset_tag', 'ASC'); + + if (Input::has('search')) { + $assets = $assets->TextSearch(Input::has('search')); + } + $assets = $assets->skip(Input::get('offset'))->take(Input::get('limit'))->get(); + $rows = array(); $i=0; @@ -1108,8 +1115,8 @@ class AssetsController extends AdminController $i++; } - $data = array('total'=>$i, 'rows'=>$rows); + $data = array('total'=>Asset::assetcount(), 'rows'=>$rows); - return $rows; + return $data; } } diff --git a/app/models/Asset.php b/app/models/Asset.php index 5091f3d1d8..dda08ac1ff 100755 --- a/app/models/Asset.php +++ b/app/models/Asset.php @@ -240,8 +240,8 @@ class Asset extends Depreciable return false; } } - - public function checkin_email() { + + public function checkin_email() { return $this->model->category->checkin_email; } @@ -393,4 +393,27 @@ class Asset extends Depreciable } + /** + * Query builder scope to search on text + * + * @param Illuminate\Database\Query\Builder $query Query builder instance + * @param text $search Search term + * + * @return Illuminate\Database\Query\Builder Modified query builder + */ + public function scopeTextSearch($query, $search) + { + + + return $query->where(function($query) use ($search) + { + + $query->where('name','LIKE','%'.$search.'%') + ->orWhere('asset_tag','LIKE','%'.$search.'%') + ->orWhere('serial','LIKE','%'.$search.'%'); + }); + + } + + } diff --git a/app/views/backend/hardware/index.blade.php b/app/views/backend/hardware/index.blade.php index 876cfd8b77..6a154d0865 100755 --- a/app/views/backend/hardware/index.blade.php +++ b/app/views/backend/hardware/index.blade.php @@ -95,7 +95,7 @@ search: true, pageSize: {{{ Setting::getSettings()->per_page }}}, pagination: true, - sidePagination: 'client', + sidePagination: 'server', sortable: true, mobileResponsive: true, columnsHidden: ['name'], @@ -112,7 +112,7 @@ columns: 'fa-columns', refresh: 'fa-refresh' }, - + }); </script> From 4a51ff9ba5ac433d2aba19b3ba4708da4471d42d Mon Sep 17 00:00:00 2001 From: snipe <snipe@snipe.net> Date: Mon, 27 Jul 2015 22:46:13 -0700 Subject: [PATCH 010/120] Duh --- app/controllers/admin/AssetsController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/admin/AssetsController.php b/app/controllers/admin/AssetsController.php index f7385f42c2..10ca3e219e 100755 --- a/app/controllers/admin/AssetsController.php +++ b/app/controllers/admin/AssetsController.php @@ -1072,7 +1072,7 @@ class AssetsController extends AdminController $assets = $assets->orderBy('asset_tag', 'ASC'); if (Input::has('search')) { - $assets = $assets->TextSearch(Input::has('search')); + $assets = $assets->TextSearch(Input::get('search')); } $assets = $assets->skip(Input::get('offset'))->take(Input::get('limit'))->get(); From a6d4b30df8a7c4cc2cc5da11b8d6ade8da56c345 Mon Sep 17 00:00:00 2001 From: snipe <snipe@snipe.net> Date: Mon, 27 Jul 2015 22:50:01 -0700 Subject: [PATCH 011/120] Make checkall work --- app/views/backend/hardware/index.blade.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/backend/hardware/index.blade.php b/app/views/backend/hardware/index.blade.php index 6a154d0865..d3e77d9bc3 100755 --- a/app/views/backend/hardware/index.blade.php +++ b/app/views/backend/hardware/index.blade.php @@ -55,7 +55,7 @@ <table name="assets" id="table" data-url="{{route('api.hardware.list', array(''=>Input::get('status'),'order_number'=>Input::get('order_number')))}}"> <thead> <tr> - <th data-class="hidden-xs" data-switchable="false" data-searchable="false" data-sortable="false" data-field="checkbox"><div class="text-center"><input type="checkbox" id="checkAll" style="padding-left: 0px;"></div></th> + <th data-class="hidden-xs" data-switchable="false" data-searchable="false" data-sortable="false" data-field="checkbox" clickToSelect="true"><div class="text-center"><input type="checkbox" id="checkAll" style="padding-left: 0px;"></div></th> <th data-sortable="true" data-field="name">{{Lang::get('admin/hardware/form.name')}}</th> <th data-sortable="true" data-field="asset_tag">{{Lang::get('admin/hardware/table.asset_tag')}}</th> <th data-sortable="true" data-field="serial">{{Lang::get('admin/hardware/table.serial')}}</th> From 4af635df28c4252f8510983a46acd0109f4e5e1a Mon Sep 17 00:00:00 2001 From: snipe <snipe@snipe.net> Date: Mon, 27 Jul 2015 22:59:36 -0700 Subject: [PATCH 012/120] NEVERMIND. --- app/views/backend/hardware/index.blade.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/backend/hardware/index.blade.php b/app/views/backend/hardware/index.blade.php index d3e77d9bc3..6a154d0865 100755 --- a/app/views/backend/hardware/index.blade.php +++ b/app/views/backend/hardware/index.blade.php @@ -55,7 +55,7 @@ <table name="assets" id="table" data-url="{{route('api.hardware.list', array(''=>Input::get('status'),'order_number'=>Input::get('order_number')))}}"> <thead> <tr> - <th data-class="hidden-xs" data-switchable="false" data-searchable="false" data-sortable="false" data-field="checkbox" clickToSelect="true"><div class="text-center"><input type="checkbox" id="checkAll" style="padding-left: 0px;"></div></th> + <th data-class="hidden-xs" data-switchable="false" data-searchable="false" data-sortable="false" data-field="checkbox"><div class="text-center"><input type="checkbox" id="checkAll" style="padding-left: 0px;"></div></th> <th data-sortable="true" data-field="name">{{Lang::get('admin/hardware/form.name')}}</th> <th data-sortable="true" data-field="asset_tag">{{Lang::get('admin/hardware/table.asset_tag')}}</th> <th data-sortable="true" data-field="serial">{{Lang::get('admin/hardware/table.serial')}}</th> From ed02d7daae3a566c317d81c08c12a1bdc1e8edb5 Mon Sep 17 00:00:00 2001 From: madd15 <joshdeakin@adam.com.au> Date: Tue, 28 Jul 2015 15:57:21 +0930 Subject: [PATCH 013/120] Remove remnants of dataTables --- public/assets/js/snipeit.js | 61 +------------------------------------ 1 file changed, 1 insertion(+), 60 deletions(-) diff --git a/public/assets/js/snipeit.js b/public/assets/js/snipeit.js index 0bddfa55c5..7bf1cf8c51 100755 --- a/public/assets/js/snipeit.js +++ b/public/assets/js/snipeit.js @@ -8,63 +8,6 @@ var Components = {}; Components.modals = {}; - Components.example = function() { - var paginationType = 'full_numbers'; - var $el = $('#example'); - - var render = function() { - $el.dataTable({ - "sPaginationType": paginationType, - "iDisplayLength": settings.per_page, - "aLengthMenu": [ - [settings.per_page, -1], - [settings.per_page, "All"] - ], - "aoColumnDefs": [{ - 'bSortable': false, - 'aTargets': ['actions'] - }] - }); - - $el.popover(); - }; - - return { - render: render - }; - }; - - - Components.nosorting = function() { - var paginationType = 'full_numbers'; - var $el = $('#nosorting'); - - var render = function() { - $el.dataTable({ - "sPaginationType": paginationType, - "fnSort": [1, 'asc'], - "aoColumns": [{ - "bSortable": false - }, { - "bSortable": false - }, { - "bSortable": false - }, { - "bSortable": false - }], - "iDisplayLength": settings.per_page, - "aLengthMenu": [ - [settings.per_page, -1], - [settings.per_page, "All"] - ] - }); - }; - - return { - render: render - }; - }; - // add uniform plugin styles to html elements Components.pluginStyles = function() { var $el = $("input:checkbox, input:radio"); @@ -164,12 +107,10 @@ * Component definition stays out of load event, execution only happens. */ $(function() { - new Components.example().render(); - new Components.nosorting().render(); new Components.pluginStyles().render(); new Components.datepicker().render(); new Components.select2().render(); new Components.knob().render(); new Components.modals.confirmDelete().render(); }); -}(jQuery, window.snipeit.settings)); \ No newline at end of file +}(jQuery, window.snipeit.settings)); From 679b9f6def461ae5e2c0fa1223368d5838ac2945 Mon Sep 17 00:00:00 2001 From: madd15 <joshdeakin@adam.com.au> Date: Tue, 28 Jul 2015 17:03:39 +0930 Subject: [PATCH 014/120] Small EOL fix --- app/controllers/admin/AssetsController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/admin/AssetsController.php b/app/controllers/admin/AssetsController.php index d3e0dd3281..864da9b797 100755 --- a/app/controllers/admin/AssetsController.php +++ b/app/controllers/admin/AssetsController.php @@ -1113,7 +1113,7 @@ class AssetsController extends AdminController 'status' => ($asset->assigned_to!='') ? link_to('../admin/users/'.$asset->assigned_to.'/view', $asset->assigneduser->fullName()) : (($asset->assetstatus) ? $asset->assetstatus->name : ''), 'location' => (($asset->assigned_to)&&($asset->assigneduser->userloc!='')) ? link_to('admin/settings/locations/'.$asset->assigneduser->userloc->id.'/edit', $asset->assigneduser->userloc->name) : (($asset->defaultLoc!='') ? link_to('admin/settings/locations/'.$asset->defaultLoc->id.'/edit', $asset->defaultLoc->name) : ''), 'category' => ($asset->model->category) ? $asset->model->category->name : 'No category', - 'eol' => $asset->eol_date(), + 'eol' => ($asset->eol_date()) ? $asset->eol_date() : '', 'notes' => $asset->notes, 'order' => ($asset->order_number) ? '<a href="../hardware/?order_number='.$asset->order_number.'">'.$asset->order_number.'</a>' : '', 'checkout_date' => (($asset->assigned_to!='')&&($asset->assetlog->first())) ? $asset->assetlog->first()->created_at->format('Y-m-d') : '', From 2507c1aa7008d4298547d2f5b72f9e6e7bb10d96 Mon Sep 17 00:00:00 2001 From: madd15 <joshdeakin@adam.com.au> Date: Wed, 29 Jul 2015 09:26:44 +0930 Subject: [PATCH 015/120] Correct Asset Count --- app/controllers/admin/AssetsController.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/controllers/admin/AssetsController.php b/app/controllers/admin/AssetsController.php index d3e0dd3281..b472fd146e 100755 --- a/app/controllers/admin/AssetsController.php +++ b/app/controllers/admin/AssetsController.php @@ -1082,6 +1082,7 @@ class AssetsController extends AdminController if (Input::has('search')) { $assets = $assets->TextSearch(Input::get('search')); } + $assetCount = $assets->count(); $assets = $assets->skip(Input::get('offset'))->take(Input::get('limit'))->get(); @@ -1123,7 +1124,7 @@ class AssetsController extends AdminController $i++; } - $data = array('total'=>Asset::assetcount(), 'rows'=>$rows); + $data = array('total'=>$assetCount, 'rows'=>$rows); return $data; } From 35f97cceb72f20ff104252066e92324cd5691827 Mon Sep 17 00:00:00 2001 From: madd15 <joshdeakin@adam.com.au> Date: Wed, 29 Jul 2015 10:34:21 +0930 Subject: [PATCH 016/120] Fix missing lists causing modal errors --- app/controllers/admin/AssetsController.php | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/app/controllers/admin/AssetsController.php b/app/controllers/admin/AssetsController.php index b472fd146e..eea5613f44 100755 --- a/app/controllers/admin/AssetsController.php +++ b/app/controllers/admin/AssetsController.php @@ -227,18 +227,30 @@ class AssetsController extends AdminController // Grab the dropdown list of models - $model_list = array('' => Lang::get('general.select_model')) + DB::table('models') + $model_list = array('' => Lang::get('general.select_model')) + DB::table('models') ->select(DB::raw('concat(name," / ",modelno) as name, id'))->orderBy('name', 'asc') ->orderBy('modelno', 'asc') ->lists('name', 'id'); $supplier_list = array('' => Lang::get('general.select_supplier')) + Supplier::orderBy('name', 'asc')->lists('name', 'id'); $location_list = array('' => Lang::get('general.select_location')) + Location::orderBy('name', 'asc')->lists('name', 'id'); $assigned_to = array('' => Lang::get('general.select_user')) + DB::table('users')->select(DB::raw('concat(first_name," ",last_name) as full_name, id'))->whereNull('deleted_at')->lists('full_name', 'id'); + // grap dropdown lists for embedded create drop-downs + $manufacturer_list = array('' => 'Select One') + Manufacturer::lists('name', 'id'); + $category_list = array('' => '') + DB::table('categories')->whereNull('deleted_at')->lists('name', 'id'); // Grab the dropdown list of status $statuslabel_list = Statuslabel::orderBy('name', 'asc')->lists('name', 'id'); - return View::make('backend/hardware/edit', compact('asset'))->with('model_list',$model_list)->with('supplier_list',$supplier_list)->with('location_list',$location_list)->with('statuslabel_list',$statuslabel_list)->with('assigned_to',$assigned_to); + $view = View::make('backend/hardware/edit', compact('asset')); + $view = $view->with('model_list',$model_list); + $view = $view->with('supplier_list',$supplier_list); + $view = $view->with('location_list',$location_list); + $view = $view->with('statuslabel_list',$statuslabel_list); + $view = $view->with('manufacturer',$manufacturer_list); + $view = $view->with('category',$category_list); + $view = $view->with('assigned_to',$assigned_to); + + return $view; } From c513007b36b2bb8d6d09c9a25fbbf5e3ac71760c Mon Sep 17 00:00:00 2001 From: madd15 <joshdeakin@adam.com.au> Date: Thu, 30 Jul 2015 13:44:32 +0930 Subject: [PATCH 017/120] Add sort to table, missing most columns still --- app/controllers/admin/AssetsController.php | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/app/controllers/admin/AssetsController.php b/app/controllers/admin/AssetsController.php index cbb88ff4e2..c71911e7d2 100755 --- a/app/controllers/admin/AssetsController.php +++ b/app/controllers/admin/AssetsController.php @@ -1089,17 +1089,32 @@ class AssetsController extends AdminController $assets->where('order_number','=',e(Input::get('order_number'))); } - $assets = $assets->orderBy('asset_tag', 'ASC'); - if (Input::has('search')) { $assets = $assets->TextSearch(Input::get('search')); } + + if (Input::has('sort') && Input::has('order')){ + $order = Input::get('order'); + $sort = Input::get('sort'); + + switch ($sort) + { + case 'model': + $assets = $assets->OrderModels($order); + break; + default: + $assets = $assets->orderBy($sort, $order); + break; + } + } else { + $assets = $assets->orderBy('asset_tag', 'ASC'); + } + $assetCount = $assets->count(); $assets = $assets->skip(Input::get('offset'))->take(Input::get('limit'))->get(); $rows = array(); - $i=0; foreach ($assets as $asset) { if ($asset->deleted_at=='') { $actions = '<div style=" white-space: nowrap;"><a href="'.route('clone/hardware', $asset->id).'" class="btn btn-info btn-sm" title="Clone asset"><i class="fa fa-files-o"></i></a> <a href="'.route('update/hardware', $asset->id).'" class="btn btn-warning btn-sm"><i class="fa fa-pencil icon-white"></i></a> <a data-html="false" class="btn delete-asset btn-danger btn-sm" data-toggle="modal" href="'.route('delete/hardware', $asset->id).'" data-content="'.Lang::get('admin/hardware/message.delete.confirm').'" data-title="'.Lang::get('general.delete').' '.htmlspecialchars($asset->asset_tag).'?" onClick="return false;"><i class="fa fa-trash icon-white"></i></a></div>'; @@ -1133,7 +1148,6 @@ class AssetsController extends AdminController 'change' => $inout, 'actions' => $actions ); - $i++; } $data = array('total'=>$assetCount, 'rows'=>$rows); From e66ea4dcd1d00419f33d08aacb58f9aa6a63834d Mon Sep 17 00:00:00 2001 From: madd15 <joshdeakin@adam.com.au> Date: Thu, 30 Jul 2015 13:45:46 +0930 Subject: [PATCH 018/120] Build out search and add Model order scope --- app/models/Asset.php | 57 ++++++++++++++++++++++++++++++++++---------- 1 file changed, 44 insertions(+), 13 deletions(-) diff --git a/app/models/Asset.php b/app/models/Asset.php index dda08ac1ff..9fcad6f461 100755 --- a/app/models/Asset.php +++ b/app/models/Asset.php @@ -391,8 +391,7 @@ class Asset extends Depreciable { return $query->whereNotNull('deleted_at'); } - - + /** * Query builder scope to search on text * @@ -402,18 +401,50 @@ class Asset extends Depreciable * @return Illuminate\Database\Query\Builder Modified query builder */ public function scopeTextSearch($query, $search) + { + $search = explode('+', $search); + + return $query->where(function($query) use ($search) { - - - return $query->where(function($query) use ($search) - { - - $query->where('name','LIKE','%'.$search.'%') + foreach ($search as $search) { + $query->whereHas('model', function($query) use ($search) { + $query->join('categories','models.category_id','=','categories.id') + ->where('categories.name','LIKE','%'.$search.'%') + ->orWhere('models.name','LIKE','%'.$search.'%'); + })->orWhere(function($query) use ($search) { + $query->whereHas('assetstatus', function($query) use ($search) { + $query->where('name','LIKE','%'.$search.'%'); + }); + })->orWhere(function($query) use ($search) { + $query->whereHas('defaultLoc', function($query) use ($search) { + $query->where('name','LIKE','%'.$search.'%'); + }); + })->orWhere(function($query) use ($search) { + $query->whereHas('assigneduser', function($query) use ($search) { + $query->where('first_name','LIKE','%'.$search.'%') + ->orWhere('last_name','LIKE','%'.$search.'%'); + }); + })->orWhere('name','LIKE','%'.$search.'%') ->orWhere('asset_tag','LIKE','%'.$search.'%') - ->orWhere('serial','LIKE','%'.$search.'%'); - }); - - } - + ->orWhere('serial','LIKE','%'.$search.'%') + ->orWhere('order_number','LIKE','%'.$search.'%'); + } + }); + } + /** + * Query builder scope to order on model + * + * @param Illuminate\Database\Query\Builder $query Query builder instance + * @param text $order Order + * + * @return Illuminate\Database\Query\Builder Modified query builder + */ + public function scopeOrderModels($query, $order) + { + return $query->where(function($query) use ($order) + { + $query->join('models', 'assets.model_id', '=', 'models.id')->orderBy('models.name', $order); + }); + } } From f152841e817ab6e9571eaad56d30fd5fc7e2715a Mon Sep 17 00:00:00 2001 From: madd15 <joshdeakin@adam.com.au> Date: Thu, 30 Jul 2015 13:46:59 +0930 Subject: [PATCH 019/120] quick fix $inout/$action issue --- app/controllers/admin/AssetsController.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/controllers/admin/AssetsController.php b/app/controllers/admin/AssetsController.php index c71911e7d2..8fb42f7d2b 100755 --- a/app/controllers/admin/AssetsController.php +++ b/app/controllers/admin/AssetsController.php @@ -1116,6 +1116,8 @@ class AssetsController extends AdminController $rows = array(); foreach ($assets as $asset) { + $inout = ''; + $actions = ''; if ($asset->deleted_at=='') { $actions = '<div style=" white-space: nowrap;"><a href="'.route('clone/hardware', $asset->id).'" class="btn btn-info btn-sm" title="Clone asset"><i class="fa fa-files-o"></i></a> <a href="'.route('update/hardware', $asset->id).'" class="btn btn-warning btn-sm"><i class="fa fa-pencil icon-white"></i></a> <a data-html="false" class="btn delete-asset btn-danger btn-sm" data-toggle="modal" href="'.route('delete/hardware', $asset->id).'" data-content="'.Lang::get('admin/hardware/message.delete.confirm').'" data-title="'.Lang::get('general.delete').' '.htmlspecialchars($asset->asset_tag).'?" onClick="return false;"><i class="fa fa-trash icon-white"></i></a></div>'; } elseif ($asset->model->deleted_at=='') { From 032d79593aac47c1516061e30882784fd64fd342 Mon Sep 17 00:00:00 2001 From: madd15 <joshdeakin@adam.com.au> Date: Thu, 30 Jul 2015 13:47:43 +0930 Subject: [PATCH 020/120] quick fix $inout/$action issue --- app/controllers/admin/AssetsController.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/controllers/admin/AssetsController.php b/app/controllers/admin/AssetsController.php index 8fb42f7d2b..24bd76ea82 100755 --- a/app/controllers/admin/AssetsController.php +++ b/app/controllers/admin/AssetsController.php @@ -1147,8 +1147,8 @@ class AssetsController extends AdminController 'notes' => $asset->notes, 'order' => ($asset->order_number) ? '<a href="../hardware/?order_number='.$asset->order_number.'">'.$asset->order_number.'</a>' : '', 'checkout_date' => (($asset->assigned_to!='')&&($asset->assetlog->first())) ? $asset->assetlog->first()->created_at->format('Y-m-d') : '', - 'change' => $inout, - 'actions' => $actions + 'change' => ($inout) ? $inout : '', + 'actions' => ($actions) ? $actions : '' ); } From 78e0af383d729718aa525cdd8fb382600c5fe2ad Mon Sep 17 00:00:00 2001 From: madd15 <joshdeakin@adam.com.au> Date: Thu, 30 Jul 2015 14:08:03 +0930 Subject: [PATCH 021/120] Fix user firstname/lastname search --- app/models/Asset.php | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/app/models/Asset.php b/app/models/Asset.php index 9fcad6f461..f955c9a901 100755 --- a/app/models/Asset.php +++ b/app/models/Asset.php @@ -420,10 +420,12 @@ class Asset extends Depreciable $query->where('name','LIKE','%'.$search.'%'); }); })->orWhere(function($query) use ($search) { - $query->whereHas('assigneduser', function($query) use ($search) { - $query->where('first_name','LIKE','%'.$search.'%') - ->orWhere('last_name','LIKE','%'.$search.'%'); - }); + $query->whereHas('assigneduser', function($query) use ($search) { + $query->where(function($query) use ($search) { + $query->where('first_name','LIKE','%'.$search.'%') + ->orWhere('last_name','LIKE','%'.$search.'%'); + }); + }); })->orWhere('name','LIKE','%'.$search.'%') ->orWhere('asset_tag','LIKE','%'.$search.'%') ->orWhere('serial','LIKE','%'.$search.'%') From 0fcf33ed8cb5c0977587185c34982d96d254d9eb Mon Sep 17 00:00:00 2001 From: madd15 <joshdeakin@adam.com.au> Date: Thu, 30 Jul 2015 15:22:58 +0930 Subject: [PATCH 022/120] MOAR SEARCH --- app/models/Asset.php | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/app/models/Asset.php b/app/models/Asset.php index f955c9a901..a725a5bfcb 100755 --- a/app/models/Asset.php +++ b/app/models/Asset.php @@ -408,9 +408,12 @@ class Asset extends Depreciable { foreach ($search as $search) { $query->whereHas('model', function($query) use ($search) { - $query->join('categories','models.category_id','=','categories.id') - ->where('categories.name','LIKE','%'.$search.'%') - ->orWhere('models.name','LIKE','%'.$search.'%'); + $query->whereHas('category', function($query) use ($search) { + $query->where(function($query) use ($search) { + $query->where('categories.name','LIKE','%'.$search.'%') + ->orWhere('models.name','LIKE','%'.$search.'%'); + }); + }); })->orWhere(function($query) use ($search) { $query->whereHas('assetstatus', function($query) use ($search) { $query->where('name','LIKE','%'.$search.'%'); @@ -420,16 +423,22 @@ class Asset extends Depreciable $query->where('name','LIKE','%'.$search.'%'); }); })->orWhere(function($query) use ($search) { - $query->whereHas('assigneduser', function($query) use ($search) { - $query->where(function($query) use ($search) { - $query->where('first_name','LIKE','%'.$search.'%') - ->orWhere('last_name','LIKE','%'.$search.'%'); - }); - }); + $query->whereHas('assigneduser', function($query) use ($search) { + $query->where(function($query) use ($search) { + $query->where('users.first_name','LIKE','%'.$search.'%') + ->orWhere('users.last_name','LIKE','%'.$search.'%') + ->orWhere(function($query) use ($search) { + $query->whereHas('userloc', function($query) use ($search) { + $query->where('locations.name','LIKE','%'.$search.'%'); + }); + }); + }); + }); })->orWhere('name','LIKE','%'.$search.'%') ->orWhere('asset_tag','LIKE','%'.$search.'%') ->orWhere('serial','LIKE','%'.$search.'%') - ->orWhere('order_number','LIKE','%'.$search.'%'); + ->orWhere('order_number','LIKE','%'.$search.'%') + ->orWhere('notes','LIKE','%'.$search.'%'); } }); } From b9e3dd10b44475e9a8f92cb82583f6da31931f0f Mon Sep 17 00:00:00 2001 From: madd15 <joshdeakin@adam.com.au> Date: Fri, 7 Aug 2015 09:42:49 +0930 Subject: [PATCH 023/120] Additional Search and Order --- app/models/Asset.php | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/app/models/Asset.php b/app/models/Asset.php index a725a5bfcb..f8f9be5d69 100755 --- a/app/models/Asset.php +++ b/app/models/Asset.php @@ -392,7 +392,7 @@ class Asset extends Depreciable return $query->whereNotNull('deleted_at'); } - /** +/** * Query builder scope to search on text * * @param Illuminate\Database\Query\Builder $query Query builder instance @@ -434,11 +434,16 @@ class Asset extends Depreciable }); }); }); + })->orWhere(function($query) use ($search) { + $query->whereHas('assetlog', function($query) use ($search) { + $query->where('action_type','=','checkout') + ->where('created_at','LIKE','%'.$search.'%'); + }); })->orWhere('name','LIKE','%'.$search.'%') ->orWhere('asset_tag','LIKE','%'.$search.'%') ->orWhere('serial','LIKE','%'.$search.'%') ->orWhere('order_number','LIKE','%'.$search.'%') - ->orWhere('notes','LIKE','%'.$search.'%'); + ->orWhere('notes','LIKE','%'.$search.''); } }); } @@ -453,9 +458,21 @@ class Asset extends Depreciable */ public function scopeOrderModels($query, $order) { - return $query->where(function($query) use ($order) - { - $query->join('models', 'assets.model_id', '=', 'models.id')->orderBy('models.name', $order); - }); + return $query->join('models', 'assets.model_id', '=', 'models.id')->orderBy('models.name', $order); + } + + public function scopeOrderCheckout($query, $order) + { + return $query->join('asset_logs', function($join){ + $join->on('assets.id', '=', 'asset_logs.asset_id'); + })->where('asset_logs.action_type', '=', 'checkout') + ->orderBy('asset_logs.created_at', $order); + } + + public function scopeOrderCategory($query, $order) + { + return $query->join('models', 'assets.model_id', '=', 'models.id') + ->join('categories', 'models.category_id', '=', 'categories.id') + ->orderBy('categories.name', $order); } } From fd9cf29459a70e0eb21bac3963f4c1d94527a227 Mon Sep 17 00:00:00 2001 From: madd15 <joshdeakin@adam.com.au> Date: Fri, 7 Aug 2015 09:44:23 +0930 Subject: [PATCH 024/120] Additional changes for search and order functions --- app/controllers/admin/AssetsController.php | 41 ++++++++++++---------- 1 file changed, 22 insertions(+), 19 deletions(-) diff --git a/app/controllers/admin/AssetsController.php b/app/controllers/admin/AssetsController.php index 24bd76ea82..01ca6fa8a2 100755 --- a/app/controllers/admin/AssetsController.php +++ b/app/controllers/admin/AssetsController.php @@ -1057,7 +1057,7 @@ class AssetsController extends AdminController public function getDatatable($status = null) { - $assets = Asset::with('model','assigneduser','assigneduser.userloc','assetstatus','defaultLoc','assetlog','model','model.category')->Hardware()->select(array('id', 'name','model_id','assigned_to','asset_tag','serial','status_id','purchase_date','deleted_at','rtd_location_id','notes','order_number')); + $assets = Asset::with('model','assigneduser','assigneduser.userloc','assetstatus','defaultLoc','assetlog','model','model.category')->Hardware()->select(array('assets.id', 'assets.name','assets.model_id','assets.assigned_to','assets.asset_tag','assets.serial','assets.status_id','assets.purchase_date','assets.deleted_at','assets.rtd_location_id','assets.notes','assets.order_number')); switch ($status) { @@ -1093,30 +1093,33 @@ class AssetsController extends AdminController $assets = $assets->TextSearch(Input::get('search')); } - if (Input::has('sort') && Input::has('order')){ - $order = Input::get('order'); - $sort = Input::get('sort'); + $allowed_columns = ['name','asset_tag','serial','model','checkout_date','category','notes']; + $order = Input::get('order') === 'asc' ? 'asc' : 'desc'; + $sort = in_array(Input::get('sort'), $allowed_columns) ? Input::get('sort') : 'asset_tag'; + + switch ($sort) + { + case 'model': + $assets = $assets->OrderModels($order); + break; + case 'checkout_date': + $assets = $assets->OrderCheckout($order)->first(); + break; + case 'category': + $assets = $assets->OrderCategory($order); + break; + default: + $assets = $assets->orderBy($sort, $order); + break; + } - switch ($sort) - { - case 'model': - $assets = $assets->OrderModels($order); - break; - default: - $assets = $assets->orderBy($sort, $order); - break; - } - } else { - $assets = $assets->orderBy('asset_tag', 'ASC'); - } - $assetCount = $assets->count(); $assets = $assets->skip(Input::get('offset'))->take(Input::get('limit'))->get(); $rows = array(); foreach ($assets as $asset) { - $inout = ''; + $inout = ''; $actions = ''; if ($asset->deleted_at=='') { $actions = '<div style=" white-space: nowrap;"><a href="'.route('clone/hardware', $asset->id).'" class="btn btn-info btn-sm" title="Clone asset"><i class="fa fa-files-o"></i></a> <a href="'.route('update/hardware', $asset->id).'" class="btn btn-warning btn-sm"><i class="fa fa-pencil icon-white"></i></a> <a data-html="false" class="btn delete-asset btn-danger btn-sm" data-toggle="modal" href="'.route('delete/hardware', $asset->id).'" data-content="'.Lang::get('admin/hardware/message.delete.confirm').'" data-title="'.Lang::get('general.delete').' '.htmlspecialchars($asset->asset_tag).'?" onClick="return false;"><i class="fa fa-trash icon-white"></i></a></div>'; @@ -1145,7 +1148,7 @@ class AssetsController extends AdminController 'category' => ($asset->model->category) ? $asset->model->category->name : 'No category', 'eol' => ($asset->eol_date()) ? $asset->eol_date() : '', 'notes' => $asset->notes, - 'order' => ($asset->order_number) ? '<a href="../hardware/?order_number='.$asset->order_number.'">'.$asset->order_number.'</a>' : '', + 'order_number' => ($asset->order_number) ? '<a href="../hardware/?order_number='.$asset->order_number.'">'.$asset->order_number.'</a>' : '', 'checkout_date' => (($asset->assigned_to!='')&&($asset->assetlog->first())) ? $asset->assetlog->first()->created_at->format('Y-m-d') : '', 'change' => ($inout) ? $inout : '', 'actions' => ($actions) ? $actions : '' From 567ad6c3bb2340d13706d1a670fc4526e2cb8a11 Mon Sep 17 00:00:00 2001 From: madd15 <joshdeakin@adam.com.au> Date: Tue, 18 Aug 2015 14:11:03 +0930 Subject: [PATCH 025/120] Switch to new method --- .../admin/AccessoriesController.php | 76 ++++++++++--------- 1 file changed, 42 insertions(+), 34 deletions(-) diff --git a/app/controllers/admin/AccessoriesController.php b/app/controllers/admin/AccessoriesController.php index 7fee731d39..8e163cb7f0 100755 --- a/app/controllers/admin/AccessoriesController.php +++ b/app/controllers/admin/AccessoriesController.php @@ -466,51 +466,59 @@ class AccessoriesController extends AdminController public function getDatatable() { $accessories = Accessory::select(array('id','name','qty')) - ->whereNull('deleted_at') - ->orderBy('created_at', 'DESC'); + ->whereNull('deleted_at'); - $accessories = $accessories->get(); + if (Input::has('search')) { + $accessories = $accessories->TextSearch(Input::get('search')); + } - $actions = new \Chumper\Datatable\Columns\FunctionColumn('actions',function($accessories) - { - return '<a href="'.route('checkout/accessory', $accessories->id).'" style="margin-right:5px;" class="btn btn-info btn-sm" '.(($accessories->numRemaining() > 0 ) ? '' : ' disabled').'>'.Lang::get('general.checkout').'</a><a href="'.route('update/accessory', $accessories->id).'" class="btn btn-warning btn-sm" style="margin-right:5px;"><i class="fa fa-pencil icon-white"></i></a><a data-html="false" class="btn delete-asset btn-danger btn-sm" data-toggle="modal" href="'.route('delete/accessory', $accessories->id).'" data-content="'.Lang::get('admin/accessories/message.delete.confirm').'" data-title="'.Lang::get('general.delete').' '.htmlspecialchars($accessories->name).'?" onClick="return false;"><i class="fa fa-trash icon-white"></i></a>'; - }); + $allowed_columns = ['name']; + $order = Input::get('order') === 'asc' ? 'asc' : 'desc'; + $sort = in_array(Input::get('sort'), $allowed_columns) ? Input::get('sort') : 'created_at'; - return Datatable::collection($accessories) - ->addColumn('name',function($accessories) - { - return link_to('admin/accessories/'.$accessories->id.'/view', $accessories->name); - }) - ->addColumn('qty',function($accessories) - { - return $accessories->qty; - }) - ->addColumn('numRemaining',function($accessories) - { - return $accessories->numRemaining(); - }) - ->addColumn($actions) - ->searchColumns('name','qty','numRemaining','actions') - ->orderColumns('name','qty','numRemaining','actions') - ->make(); + $accessories = $accessories->orderBy($sort, $order); + + $accessCount = $accessories->count(); + $accessories = $accessories->skip(Input::get('offset'))->take(Input::get('limit'))->get(); + + $rows = array(); + + foreach ($accessories as $accessory) { + $actions = '<a href="'.route('checkout/accessory', $accessory->id).'" style="margin-right:5px;" class="btn btn-info btn-sm" '.(($accessory->numRemaining() > 0 ) ? '' : ' disabled').'>'.Lang::get('general.checkout').'</a><a href="'.route('update/accessory', $accessory->id).'" class="btn btn-warning btn-sm" style="margin-right:5px;"><i class="fa fa-pencil icon-white"></i></a><a data-html="false" class="btn delete-asset btn-danger btn-sm" data-toggle="modal" href="'.route('delete/accessory', $accessory->id).'" data-content="'.Lang::get('admin/accessories/message.delete.confirm').'" data-title="'.Lang::get('general.delete').' '.htmlspecialchars($accessory->name).'?" onClick="return false;"><i class="fa fa-trash icon-white"></i></a>'; + + $rows[] = array( + 'name' => link_to('admin/accessories/'.$accessory->id.'/view', $accessory->name), + 'qty' => $accessory->qty, + 'numRemaining' => $accessory->numRemaining(), + 'actions' => $actions + ); + } + + $data = array('total'=>$accessCount, 'rows'=>$rows); + + return $data; } public function getDataView($accessoryID) { $accessory = Accessory::find($accessoryID); $accessory_users = $accessory->users; + $count = $accessory_users->count(); - $actions = new \Chumper\Datatable\Columns\FunctionColumn('actions',function($accessory_users){ - return '<a href="'.route('checkin/accessory', $accessory_users->pivot->id).'" class="btn-flat info">Checkin</a>'; - }); + $rows = array(); - return Datatable::collection($accessory_users) - ->addColumn('name',function($accessory_users) - { - return link_to('/admin/users/'.$accessory_users->id.'/view', $accessory_users->fullName()); - }) - ->addColumn($actions) - ->make(); + foreach ($accessory_users as $user) { + $actions = '<a href="'.route('checkin/accessory', $user->pivot->id).'" class="btn-flat info">Checkin</a>'; + + $rows[] = array( + 'name' => link_to('/admin/users/'.$user->id.'/view', $user->fullName()), + 'actions' => $actions + ); + } + + $data = array('total'=>$count, 'rows'=>$rows); + + return $data; } } From 6a2016685e386a57fba4253e3393e2b789a5a033 Mon Sep 17 00:00:00 2001 From: madd15 <joshdeakin@adam.com.au> Date: Tue, 18 Aug 2015 14:13:28 +0930 Subject: [PATCH 026/120] Change to Bootstrap Table --- app/views/backend/accessories/index.blade.php | 112 +++++++----------- 1 file changed, 40 insertions(+), 72 deletions(-) diff --git a/app/views/backend/accessories/index.blade.php b/app/views/backend/accessories/index.blade.php index f5af5ba661..947163ce7d 100755 --- a/app/views/backend/accessories/index.blade.php +++ b/app/views/backend/accessories/index.blade.php @@ -19,78 +19,16 @@ <div class="user-profile"> <div class="row profile"> <div class="col-md-9 bio"> - {{ Datatable::table() - ->addColumn(Lang::get('admin/accessories/table.title'), - Lang::get('admin/accessories/general.total'), - Lang::get('admin/accessories/general.remaining'), - Lang::get('table.actions')) - ->setOptions( - array( - 'language' => array( - 'search' => Lang::get('general.search'), - 'lengthMenu' => Lang::get('general.page_menu'), - 'loadingRecords' => Lang::get('general.loading'), - 'zeroRecords' => Lang::get('general.no_results'), - 'info' => Lang::get('general.pagination_info'), - 'processing' => '<i class="fa fa-spinner fa-spin"></i> '.Lang::get('general.processing'), - 'paginate'=> array( - 'first'=>Lang::get('general.first'), - 'previous'=>Lang::get('general.previous'), - 'next'=>Lang::get('general.next'), - 'last'=>Lang::get('general.last'), - ), - ), - 'sAjaxSource'=>route('api.accessories.list'), - 'dom' =>'T<"clear">lfrtip', - 'tableTools' => array( - 'sSwfPath'=> Config::get('app.url').'/assets/swf/copy_csv_xls_pdf.swf', - 'aButtons'=>array( - array( - 'sExtends'=>'copy', - 'sButtonText'=>'Copy', - 'mColumns'=>array(0,1,2), - 'bFooter'=>false, - ), - array( - 'sExtends'=>'print', - 'sButtonText'=>'Print', - 'mColumns'=>array(0,1,2), - 'bShowAll'=>true, - 'bFooter'=>true, - ), - array( - 'sExtends'=>'collection', - 'sButtonText'=>'Export', - 'aButtons'=>array( - array( - 'sExtends'=>'csv', - 'sButtonText'=>'csv', - 'mColumns'=>array(0,1,2), - 'bFooter'=>false, - ), - array( - 'sExtends'=>'xls', - 'sButtonText'=>'XLS', - 'mColumns'=>array(0,1,2), - 'bFooter'=>false, - ), - array( - 'sExtends'=>'pdf', - 'sButtonText'=>'PDF', - 'mColumns'=>array(0,1,2), - 'bFooter'=>false, - ) - ) - ), - ) - ), - 'columnDefs'=> array( - array('bSortable'=>false,'targets'=>array(3)), - ), - 'order'=>array(array(0,'asc')), - ) - ) - ->render() }} + <table name="accessories" id="table" data-url="{{route('api.accessories.list')}}"> + <thead> + <tr> + <th data-sortable="true" data-field="name">{{Lang::get('admin/accessories/table.title')}}</th> + <th data-switchable="false" data-searchable="false" data-sortable="false" data-field="qty">{{Lang::get('admin/accessories/general.total')}}</th> + <th data-switchable="false" data-searchable="false" data-sortable="false" data-field="numRemaining">{{Lang::get('admin/accessories/general.remaining')}}</th> + <th data-switchable="false" data-searchable="false" data-sortable="false" data-field="actions">{{Lang::get('table.actions')}}</th> + </tr> + </thead> + </table> </div> @@ -103,4 +41,34 @@ </div> </div> </div> + +<script type="text/javascript"> + $('#table').bootstrapTable({ + classes: 'table table-hover table-no-bordered', + undefinedText: 'undefined', + iconsPrefix: 'fa', + showRefresh: true, + search: true, + pageSize: {{{ Setting::getSettings()->per_page }}}, + pagination: true, + sidePagination: 'server', + sortable: true, + mobileResponsive: true, + showExport: true, + showColumns: false, + maintainSelected: true, + paginationFirstText: "@lang('general.first')", + paginationLastText: "@lang('general.last')", + paginationPreText: "@lang('general.previous')", + paginationNextText: "@lang('general.next')", + pageList: ['10','25','50','100','150','200'], + icons: { + paginationSwitchDown: 'fa-caret-square-o-down', + paginationSwitchUp: 'fa-caret-square-o-up', + columns: 'fa-columns', + refresh: 'fa-refresh' + }, + }); +</script> + @stop From d35f8e624496ab820ab03cb65a63f9760f3190e9 Mon Sep 17 00:00:00 2001 From: madd15 <joshdeakin@adam.com.au> Date: Tue, 18 Aug 2015 14:13:59 +0930 Subject: [PATCH 027/120] Change to Bootstrap Table --- app/views/backend/accessories/view.blade.php | 105 +++++++++---------- 1 file changed, 49 insertions(+), 56 deletions(-) diff --git a/app/views/backend/accessories/view.blade.php b/app/views/backend/accessories/view.blade.php index a2f9876c77..2a0feae145 100644 --- a/app/views/backend/accessories/view.blade.php +++ b/app/views/backend/accessories/view.blade.php @@ -25,62 +25,26 @@ </div> <div class="user-profile"> -<div class="row profile"> -<div class="col-md-9 bio"> - - - <!-- checked out accessories table --> - @if ($accessory->users->count() > 0) - {{ Datatable::table() - ->addColumn(Lang::get('general.user'), - Lang::get('table.actions')) - ->setOptions( - array( - 'sAjaxSource'=>route('api.accessories.view', $accessory->id), - 'dom' =>'T<"clear">lfrtip', - 'tableTools' => array( - 'sSwfPath'=> Config::get('app.url').'/assets/swf/copy_csv_xls_pdf.swf', - 'aButtons'=>array( - array( - 'sExtends'=>'copy', - ), - 'print', - array( - 'sExtends'=>'collection', - 'sButtonText'=>'Export', - 'aButtons'=>array( - array( - 'sExtends'=>'csv', - ), - array( - 'sExtends'=>'xls', - ), - array( - 'sExtends'=>'pdf', - ), - ), - ), - ) - ), - 'columnDefs'=> array( - array('bSortable'=>false,'targets'=>array(1)), - array('width'=>'auto','targets'=>array(1)), - ), - 'order'=>array(array(0,'asc')), - ) - ) - ->render() }} - - @else - <div class="col-md-9"> - <div class="alert alert-info alert-block"> - <i class="fa fa-info-circle"></i> - @lang('general.no_results') - </div> - </div> - @endif - - </div> + <div class="row profile"> + <div class="col-md-9 bio"> + @if ($accessory->users->count() > 0) + <table name="accessory_users" id="table" data-url="{{route('api.accessories.view', $accessory->id)}}"> + <thead> + <tr> + <th data-switchable="false" data-searchable="false" data-sortable="false" data-field="name">{{Lang::get('general.user')}}</th> + <th data-switchable="false" data-searchable="false" data-sortable="false" data-field="actions">{{Lang::get('table.actions')}}</th> + </tr> + </thead> + </table> + @else + <div class="col-md-9"> + <div class="alert alert-info alert-block"> + <i class="fa fa-info-circle"></i> + @lang('general.no_results') + </div> + </div> + @endif + </div> <!-- side address column --> <div class="col-md-3 col-xs-12 address pull-right"> @@ -90,4 +54,33 @@ </div> +<script type="text/javascript"> + $('#table').bootstrapTable({ + classes: 'table table-hover table-no-bordered', + undefinedText: 'undefined', + iconsPrefix: 'fa', + showRefresh: true, + search: false, + pageSize: {{{ Setting::getSettings()->per_page }}}, + pagination: true, + sidePagination: 'server', + sortable: true, + mobileResponsive: true, + showExport: true, + showColumns: false, + maintainSelected: true, + paginationFirstText: "@lang('general.first')", + paginationLastText: "@lang('general.last')", + paginationPreText: "@lang('general.previous')", + paginationNextText: "@lang('general.next')", + pageList: ['10','25','50','100','150','200'], + icons: { + paginationSwitchDown: 'fa-caret-square-o-down', + paginationSwitchUp: 'fa-caret-square-o-up', + columns: 'fa-columns', + refresh: 'fa-refresh' + }, + }); +</script> + @stop From 5568f7fc5ff474fbbcceae718652fc7f5b915ad5 Mon Sep 17 00:00:00 2001 From: madd15 <joshdeakin@adam.com.au> Date: Tue, 18 Aug 2015 14:15:03 +0930 Subject: [PATCH 028/120] Add name text search --- app/models/Accessory.php | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/app/models/Accessory.php b/app/models/Accessory.php index 6d36f7ac0b..d8e9cb7ba7 100755 --- a/app/models/Accessory.php +++ b/app/models/Accessory.php @@ -67,6 +67,25 @@ class Accessory extends Elegant $remaining = $total - $checkedout; return $remaining; } + + /** + * Query builder scope to search on text + * + * @param Illuminate\Database\Query\Builder $query Query builder instance + * @param text $search Search term + * + * @return Illuminate\Database\Query\Builder Modified query builder + */ + public function scopeTextSearch($query, $search) + { + $search = explode('+', $search); + return $query->where(function($query) use ($search) + { + foreach ($search as $s) { + $query->where('name', 'LIKE', '%'.$s.'%'); + } + }); + } } From 899e5431737b42f704c80c96ef362b7b5fc55ce4 Mon Sep 17 00:00:00 2001 From: madd15 <joshdeakin@adam.com.au> Date: Tue, 18 Aug 2015 16:12:23 +0930 Subject: [PATCH 029/120] Switch to new method --- .../admin/ConsumablesController.php | 70 +++++++++++-------- 1 file changed, 40 insertions(+), 30 deletions(-) diff --git a/app/controllers/admin/ConsumablesController.php b/app/controllers/admin/ConsumablesController.php index 05376143b6..19f0786c97 100644 --- a/app/controllers/admin/ConsumablesController.php +++ b/app/controllers/admin/ConsumablesController.php @@ -348,47 +348,57 @@ class ConsumablesController extends AdminController public function getDatatable() { $consumables = Consumable::select(array('id','name','qty')) - ->whereNull('deleted_at') - ->orderBy('created_at', 'DESC'); + ->whereNull('deleted_at'); - $consumables = $consumables->get(); + if (Input::has('search')) { + $consumables = $consumables->TextSearch(Input::get('search')); + } - $actions = new \Chumper\Datatable\Columns\FunctionColumn('actions',function($consumables) - { - return '<a href="'.route('checkout/consumable', $consumables->id).'" style="margin-right:5px;" class="btn btn-info btn-sm" '.(($consumables->numRemaining() > 0 ) ? '' : ' disabled').'>'.Lang::get('general.checkout').'</a><a href="'.route('update/consumable', $consumables->id).'" class="btn btn-warning btn-sm" style="margin-right:5px;"><i class="fa fa-pencil icon-white"></i></a><a data-html="false" class="btn delete-asset btn-danger btn-sm" data-toggle="modal" href="'.route('delete/consumable', $consumables->id).'" data-content="'.Lang::get('admin/consumables/message.delete.confirm').'" data-title="'.Lang::get('general.delete').' '.htmlspecialchars($consumables->name).'?" onClick="return false;"><i class="fa fa-trash icon-white"></i></a>'; - }); + $allowed_columns = ['name']; + $order = Input::get('order') === 'asc' ? 'asc' : 'desc'; + $sort = in_array(Input::get('sort'), $allowed_columns) ? Input::get('sort') : 'created_at'; + + $consumables->orderBy($sort, $order); + + $consumCount = $consumables->count(); + $consumables = $consumables->skip(Input::get('offset'))->take(Input::get('limit'))->get(); + + $rows = array(); + + foreach($consumables as $consumable) { + $actions = '<a href="'.route('checkout/consumable', $consumable->id).'" style="margin-right:5px;" class="btn btn-info btn-sm" '.(($consumable->numRemaining() > 0 ) ? '' : ' disabled').'>'.Lang::get('general.checkout').'</a><a href="'.route('update/consumable', $consumable->id).'" class="btn btn-warning btn-sm" style="margin-right:5px;"><i class="fa fa-pencil icon-white"></i></a><a data-html="false" class="btn delete-asset btn-danger btn-sm" data-toggle="modal" href="'.route('delete/consumable', $consumable->id).'" data-content="'.Lang::get('admin/consumables/message.delete.confirm').'" data-title="'.Lang::get('general.delete').' '.htmlspecialchars($consumable->name).'?" onClick="return false;"><i class="fa fa-trash icon-white"></i></a>'; + + $rows[] = array( + 'name' => link_to('admin/consumables/'.$consumable->id.'/view', $consumable->name), + 'qty' => $consumable->qty, + 'numRemaining' => $consumable->numRemaining(), + 'actions' => $actions + ); + } + + $data = array('total' => $consumCount, 'rows' => $rows); + + return $data; - return Datatable::collection($consumables) - ->addColumn('name',function($consumables) - { - return link_to('admin/consumables/'.$consumables->id.'/view', $consumables->name); - }) - ->addColumn('qty',function($consumables) - { - return $consumables->qty; - }) - ->addColumn('numRemaining',function($consumables) - { - return $consumables->numRemaining(); - }) - ->addColumn($actions) - ->searchColumns('name','qty','numRemaining','actions') - ->orderColumns('name','qty','numRemaining','actions') - ->make(); } public function getDataView($consumableID) { $consumable = Consumable::find($consumableID); $consumable_users = $consumable->users; + $count = $consumable_users->count(); + $rows = array(); - return Datatable::collection($consumable_users) - ->addColumn('name',function($consumable_users) - { - return link_to('/admin/users/'.$consumable_users->id.'/view', $consumable_users->fullName()); - }) - ->make(); + foreach ($consumable_users as $user) { + $rows[] = array( + 'name' => link_to('/admin/users/'.$user->id.'/view', $user->fullName()) + ); + } + + $data = array('total' => $count, 'rows' => $rows); + + return $data; } } From 611f59b507f184162a9dcef5aee6eab54de27236 Mon Sep 17 00:00:00 2001 From: madd15 <joshdeakin@adam.com.au> Date: Tue, 18 Aug 2015 16:13:05 +0930 Subject: [PATCH 030/120] Add name text search --- app/models/Consumable.php | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/app/models/Consumable.php b/app/models/Consumable.php index 2f6170d2f6..109a58bee0 100644 --- a/app/models/Consumable.php +++ b/app/models/Consumable.php @@ -64,6 +64,22 @@ class Consumable extends Elegant $remaining = $total - $checkedout; return $remaining; } + + /** + * Query builder scope to search on text + * + * @param Illuminate\Database\Query\Builder $query Query builder instance + * @param text $search Search term + * + * @return Illuminate\Database\Query\Builder Modified query builder + */ + public function scopeTextSearch($query, $search) + { + return $query->where(function($query) use ($search) + { + $query->where('name', 'LIKE', '%'.$search.'%'); + }); + } } From 93fe9a279977810851c5fe932e39600a1665ed50 Mon Sep 17 00:00:00 2001 From: madd15 <joshdeakin@adam.com.au> Date: Tue, 18 Aug 2015 16:13:49 +0930 Subject: [PATCH 031/120] Change to Bootstrap Table --- app/views/backend/consumables/index.blade.php | 111 ++++++------------ 1 file changed, 39 insertions(+), 72 deletions(-) diff --git a/app/views/backend/consumables/index.blade.php b/app/views/backend/consumables/index.blade.php index 70f23c4295..3672d73ae6 100644 --- a/app/views/backend/consumables/index.blade.php +++ b/app/views/backend/consumables/index.blade.php @@ -19,78 +19,15 @@ <div class="user-profile"> <div class="row profile"> <div class="col-md-9 bio"> - {{ Datatable::table() - ->addColumn(Lang::get('admin/consumables/table.title'), - Lang::get('admin/consumables/general.total'), - Lang::get('admin/consumables/general.remaining'), - Lang::get('table.actions')) - ->setOptions( - array( - 'language' => array( - 'search' => Lang::get('general.search'), - 'lengthMenu' => Lang::get('general.page_menu'), - 'loadingRecords' => Lang::get('general.loading'), - 'zeroRecords' => Lang::get('general.no_results'), - 'info' => Lang::get('general.pagination_info'), - 'processing' => '<i class="fa fa-spinner fa-spin"></i> '.Lang::get('general.processing'), - 'paginate'=> array( - 'first'=>Lang::get('general.first'), - 'previous'=>Lang::get('general.previous'), - 'next'=>Lang::get('general.next'), - 'last'=>Lang::get('general.last'), - ), - ), - 'sAjaxSource'=>route('api.consumables.list'), - 'dom' =>'T<"clear">lfrtip', - 'tableTools' => array( - 'sSwfPath'=> Config::get('app.url').'/assets/swf/copy_csv_xls_pdf.swf', - 'aButtons'=>array( - array( - 'sExtends'=>'copy', - 'sButtonText'=>'Copy', - 'mColumns'=>array(0,1,2), - 'bFooter'=>false, - ), - array( - 'sExtends'=>'print', - 'sButtonText'=>'Print', - 'mColumns'=>array(0,1,2), - 'bShowAll'=>true, - 'bFooter'=>true, - ), - array( - 'sExtends'=>'collection', - 'sButtonText'=>'Export', - 'aButtons'=>array( - array( - 'sExtends'=>'csv', - 'sButtonText'=>'csv', - 'mColumns'=>array(0,1,2), - 'bFooter'=>false, - ), - array( - 'sExtends'=>'xls', - 'sButtonText'=>'XLS', - 'mColumns'=>array(0,1,2), - 'bFooter'=>false, - ), - array( - 'sExtends'=>'pdf', - 'sButtonText'=>'PDF', - 'mColumns'=>array(0,1,2), - 'bFooter'=>false, - ) - ) - ), - ) - ), - 'columnDefs'=> array( - array('bSortable'=>false,'targets'=>array(3)), - ), - 'order'=>array(array(0,'asc')), - ) - ) - ->render() }} + <table name="consumables" id="table" data-url="{{route('api.consumables.list')}}"> + <thead> + <tr> + <th data-sortable="true" data-field="name">{{Lang::get('admin/consumables/table.title')}}</th> + <th data-switchable="false" data-searchable="false" data-sortable="false" data-field="qty">{{Lang::get('admin/consumables/general.total')}}</th> + <th data-switchable="false" data-searchable="false" data-sortable="false" data-field="numRemaining">{{Lang::get('admin/consumables/general.remaining')}}</th> + </tr> + </thead> + </table> </div> @@ -103,4 +40,34 @@ </div> </div> </div> + +<script type="text/javascript"> + $('#table').bootstrapTable({ + classes: 'table table-hover table-no-bordered', + undefinedText: 'undefined', + iconsPrefix: 'fa', + showRefresh: true, + search: true, + pageSize: {{{ Setting::getSettings()->per_page }}}, + pagination: true, + sidePagination: 'server', + sortable: true, + mobileResponsive: true, + showExport: true, + showColumns: false, + maintainSelected: true, + paginationFirstText: "@lang('general.first')", + paginationLastText: "@lang('general.last')", + paginationPreText: "@lang('general.previous')", + paginationNextText: "@lang('general.next')", + pageList: ['10','25','50','100','150','200'], + icons: { + paginationSwitchDown: 'fa-caret-square-o-down', + paginationSwitchUp: 'fa-caret-square-o-up', + columns: 'fa-columns', + refresh: 'fa-refresh' + }, + }); +</script> + @stop From e0bf6ee3905769fd344cc0f3e7288cd51717d931 Mon Sep 17 00:00:00 2001 From: madd15 <joshdeakin@adam.com.au> Date: Tue, 18 Aug 2015 16:14:10 +0930 Subject: [PATCH 032/120] Change to Bootstrap Table --- app/views/backend/consumables/view.blade.php | 85 ++++++++++---------- 1 file changed, 41 insertions(+), 44 deletions(-) diff --git a/app/views/backend/consumables/view.blade.php b/app/views/backend/consumables/view.blade.php index 68243c2699..f994cef8ec 100644 --- a/app/views/backend/consumables/view.blade.php +++ b/app/views/backend/consumables/view.blade.php @@ -31,52 +31,20 @@ <!-- checked out consumables table --> @if ($consumable->users->count() > 0) - {{ Datatable::table() - ->addColumn(Lang::get('general.user')) - ->setOptions( - array( - 'sAjaxSource'=>route('api.consumables.view', $consumable->id), - 'dom' =>'T<"clear">lfrtip', - 'tableTools' => array( - 'sSwfPath'=> Config::get('app.url').'/assets/swf/copy_csv_xls_pdf.swf', - 'aButtons'=>array( - array( - 'sExtends'=>'copy', - ), - 'print', - array( - 'sExtends'=>'collection', - 'sButtonText'=>'Export', - 'aButtons'=>array( - array( - 'sExtends'=>'csv', - ), - array( - 'sExtends'=>'xls', - ), - array( - 'sExtends'=>'pdf', - ), - ), - ), - ) - ), - 'columnDefs'=> array( - - array('width'=>'auto','targets'=>array(0)), - ), - 'order'=>array(array(0,'asc')), - ) - ) - ->render() }} - + <table name="consumable_users" id="table" data-url="{{route('api.consumables.view', $consumable->id)}}"> + <thead> + <tr> + <th data-switchable="false" data-searchable="false" data-sortable="false" data-field="name">{{Lang::get('general.user')}}</th> + </tr> + </thead> + </table> @else - <div class="col-md-9"> - <div class="alert alert-info alert-block"> - <i class="fa fa-info-circle"></i> - @lang('general.no_results') + <div class="col-md-9"> + <div class="alert alert-info alert-block"> + <i class="fa fa-info-circle"></i> + @lang('general.no_results') + </div> </div> - </div> @endif </div> @@ -89,4 +57,33 @@ </div> +<script type="text/javascript"> + $('#table').bootstrapTable({ + classes: 'table table-hover table-no-bordered', + undefinedText: 'undefined', + iconsPrefix: 'fa', + showRefresh: true, + search: false, + pageSize: {{{ Setting::getSettings()->per_page }}}, + pagination: true, + sidePagination: 'server', + sortable: true, + mobileResponsive: true, + showExport: true, + showColumns: false, + maintainSelected: true, + paginationFirstText: "@lang('general.first')", + paginationLastText: "@lang('general.last')", + paginationPreText: "@lang('general.previous')", + paginationNextText: "@lang('general.next')", + pageList: ['10','25','50','100','150','200'], + icons: { + paginationSwitchDown: 'fa-caret-square-o-down', + paginationSwitchUp: 'fa-caret-square-o-up', + columns: 'fa-columns', + refresh: 'fa-refresh' + }, + }); +</script> + @stop From a1c6ea798ad48643f8c88a85ff32cb94dd9bed0d Mon Sep 17 00:00:00 2001 From: madd15 <joshdeakin@adam.com.au> Date: Tue, 18 Aug 2015 16:15:41 +0930 Subject: [PATCH 033/120] matching wording.....so damn picky :P --- app/routes.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/routes.php b/app/routes.php index f5c15445aa..11129bb071 100755 --- a/app/routes.php +++ b/app/routes.php @@ -32,7 +32,7 @@ Route::group(array('prefix' => 'api', 'namespace' => 'Controllers\Admin', 'befor /*---Consumables API---*/ Route::group(array('prefix'=>'consumables'), function () { Route::get('list', array('as'=>'api.consumables.list', 'uses'=>'ConsumablesController@getDatatable')); - Route::get('{accessoryID}/view', array('as'=>'api.consumables.view', 'uses'=>'ConsumablesController@getDataView')); + Route::get('{consumableID}/view', array('as'=>'api.consumables.view', 'uses'=>'ConsumablesController@getDataView')); }); /*---Users API---*/ From 5aff3d9380c3e9153c87bdf109a48b4e0723199f Mon Sep 17 00:00:00 2001 From: madd15 <joshdeakin@adam.com.au> Date: Tue, 18 Aug 2015 16:17:46 +0930 Subject: [PATCH 034/120] remove search explode --- app/models/Accessory.php | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/app/models/Accessory.php b/app/models/Accessory.php index d8e9cb7ba7..6d77764e30 100755 --- a/app/models/Accessory.php +++ b/app/models/Accessory.php @@ -68,7 +68,7 @@ class Accessory extends Elegant return $remaining; } - /** + /** * Query builder scope to search on text * * @param Illuminate\Database\Query\Builder $query Query builder instance @@ -78,13 +78,10 @@ class Accessory extends Elegant */ public function scopeTextSearch($query, $search) { - $search = explode('+', $search); return $query->where(function($query) use ($search) { - foreach ($search as $s) { $query->where('name', 'LIKE', '%'.$s.'%'); - } }); } From a365cdc2ccc347f433ddae3d6f73edfbed11cd93 Mon Sep 17 00:00:00 2001 From: madd15 <joshdeakin@adam.com.au> Date: Tue, 25 Aug 2015 16:34:51 +0930 Subject: [PATCH 035/120] Switch to new method --- app/controllers/admin/LicensesController.php | 55 +++++++++++--------- 1 file changed, 31 insertions(+), 24 deletions(-) diff --git a/app/controllers/admin/LicensesController.php b/app/controllers/admin/LicensesController.php index 1ad87cde1e..a93c0185cd 100755 --- a/app/controllers/admin/LicensesController.php +++ b/app/controllers/admin/LicensesController.php @@ -887,32 +887,39 @@ class LicensesController extends AdminController } public function getDatatable() { - $licenses = License::orderBy('created_at', 'DESC')->get(); + $licenses = License::select('id','name','serial','purchase_date','seats'); - $actions = new \Chumper\Datatable\Columns\FunctionColumn('actions', function($licenses) { - return '<span style="white-space: nowrap;"><a href="'.route('freecheckout/license', $licenses->id).'" class="btn btn-primary btn-sm" style="margin-right:5px;" '.(($licenses->remaincount() > 0) ? '' : 'disabled').'>'.Lang::get('general.checkout').'</a> <a href="'.route('clone/license', $licenses->id).'" class="btn btn-info btn-sm" style="margin-right:5px;" title="Clone asset"><i class="fa fa-files-o"></i></a><a href="'.route('update/license', $licenses->id).'" class="btn btn-warning btn-sm" style="margin-right:5px;"><i class="fa fa-pencil icon-white"></i></a><a data-html="false" class="btn delete-asset btn-danger btn-sm" data-toggle="modal" href="'.route('delete/license', $licenses->id).'" data-content="'.Lang::get('admin/licenses/message.delete.confirm').'" data-title="'.Lang::get('general.delete').' '.htmlspecialchars($licenses->name).'?" onClick="return false;"><i class="fa fa-trash icon-white"></i></a></span>'; - }); + if (Input::has('search')) { + $licenses = $licenses->TextSearch(Input::get('search')); + } - return Datatable::collection($licenses) - ->addColumn('name', function($licenses) { - return link_to('/admin/licenses/'.$licenses->id.'/view', $licenses->name); - }) - ->addColumn('serial', function($licenses) { - return link_to('/admin/licenses/'.$licenses->id.'/view', mb_strimwidth($licenses->serial, 0, 50, "...")); - }) - ->addColumn('totalSeats', function($licenses) { - return $licenses->totalSeatsByLicenseID(); - }) - ->addColumn('remaining', function($licenses) { - return $licenses->remaincount(); - }) - ->addColumn('purchase_date', function($licenses) { - return $licenses->purchase_date; - }) - ->addColumn($actions) - ->searchColumns('name','serial','totalSeats','remaining','purchase_date','actions') - ->orderColumns('name','serial','totalSeats','remaining','purchase_date','actions') - ->make(); + $allowed_columns = ['name']; + $order = Input::get('order') === 'asc' ? 'asc' : 'desc'; + $sort = in_array(Input::get('sort'), $allowed_columns) ? Input::get('sort') : 'created_at'; + + $licenses = $licenses->orderBy($sort, $order); + + $licenseCount = $licenses->count(); + $licenses = $licenses->skip(Input::get('offset'))->take(Input::get('limit'))->get(); + + $rows = array(); + + foreach ($licenses as $license) { + $actions = '<span style="white-space: nowrap;"><a href="'.route('freecheckout/license', $license->id).'" class="btn btn-primary btn-sm" style="margin-right:5px;" '.(($license->remaincount() > 0) ? '' : 'disabled').'>'.Lang::get('general.checkout').'</a> <a href="'.route('clone/license', $license->id).'" class="btn btn-info btn-sm" style="margin-right:5px;" title="Clone asset"><i class="fa fa-files-o"></i></a><a href="'.route('update/license', $license->id).'" class="btn btn-warning btn-sm" style="margin-right:5px;"><i class="fa fa-pencil icon-white"></i></a><a data-html="false" class="btn delete-asset btn-danger btn-sm" data-toggle="modal" href="'.route('delete/license', $license->id).'" data-content="'.Lang::get('admin/licenses/message.delete.confirm').'" data-title="'.Lang::get('general.delete').' '.htmlspecialchars($license->name).'?" onClick="return false;"><i class="fa fa-trash icon-white"></i></a></span>'; + + $rows[] = array( + 'name' => link_to('/admin/licenses/'.$license->id.'/view', $license->name), + 'serial' => link_to('/admin/licenses/'.$license->id.'/view', mb_strimwidth($license->serial, 0, 50, "...")), + 'totalSeats' => $license->totalSeatsByLicenseID(), + 'remaining' => $license->remaincount(), + 'purchase_date' => ($license->purchase_date) ? $license->purchase_date : '', + 'actions' => $actions + ); + } + + $data = array('total' => $licenseCount, 'rows' => $rows); + + return $data; } public function getFreeLicense($licenseId) { From 3f5dad77895bc923c9ab66a1ad1d094757ccabd4 Mon Sep 17 00:00:00 2001 From: madd15 <joshdeakin@adam.com.au> Date: Tue, 25 Aug 2015 16:36:32 +0930 Subject: [PATCH 036/120] Change to Bootstrap Table --- app/views/backend/licenses/index.blade.php | 75 ++++++++++++---------- 1 file changed, 41 insertions(+), 34 deletions(-) diff --git a/app/views/backend/licenses/index.blade.php b/app/views/backend/licenses/index.blade.php index f49bfe3969..c2c899b702 100755 --- a/app/views/backend/licenses/index.blade.php +++ b/app/views/backend/licenses/index.blade.php @@ -17,39 +17,46 @@ </div> <div class="row form-wrapper"> - {{ Datatable::table() - ->addColumn(Lang::get('admin/licenses/table.title'), - Lang::get('admin/licenses/table.serial'), - Lang::get('admin/licenses/form.seats'), - Lang::get('admin/licenses/form.remaining_seats'), - Lang::get('admin/licenses/table.purchase_date'), - Lang::get('table.actions')) - ->setOptions( - array( - 'language' => array( - 'search' => Lang::get('general.search'), - 'lengthMenu' => Lang::get('general.page_menu'), - 'loadingRecords' => Lang::get('general.loading'), - 'zeroRecords' => Lang::get('general.no_results'), - 'info' => Lang::get('general.pagination_info'), - 'processing' => Lang::get('general.processing'), - 'paginate'=> array( - 'first'=>Lang::get('general.first'), - 'previous'=>Lang::get('general.previous'), - 'next'=>Lang::get('general.next'), - 'last'=>Lang::get('general.last'), - ), - ), - 'sAjaxSource'=>route('api.licenses.list'), - 'dom' =>'CT<"clear">lfrtip', - 'colVis'=> array('showAll'=>'Show All','restore'=>'Restore','exclude'=>array(5),'activate'=>'mouseover'), - 'columnDefs'=> array( - array('bSortable'=>false,'targets'=>array(5)), - array('width'=>'20%','targets'=>array(5)), - ), - 'order'=>array(array(0,'asc')), - ) - ) - ->render() }} + <table name="licenses" id="table" data-url="{{route('api.licenses.list')}}"> + <thead> + <tr> + <th data-field="name">{{Lang::get('admin/licenses/table.title')}}</th> + <th data-field="serial">{{Lang::get('admin/licenses/table.serial')}}</th> + <th data-field="totalSeats">{{Lang::get('admin/licenses/form.seats')}}</th> + <th data-field="remaining">{{Lang::get('admin/licenses/form.remaining_seats')}}</th> + <th data-field="purchase_date">{{Lang::get('admin/licenses/table.purchase_date')}}</th> + <th data-field="actions">{{Lang::get('table.actions')}}</th> + </tr> + </thead> + </table> </div> + +<script type="text/javascript"> + $('#table').bootstrapTable({ + classes: 'table table-hover table-no-bordered', + undefinedText: 'undefined', + iconsPrefix: 'fa', + showRefresh: true, + search: true, + pageSize: {{{ Setting::getSettings()->per_page }}}, + pagination: true, + sidePagination: 'server', + sortable: true, + mobileResponsive: true, + showExport: true, + showColumns: false, + maintainSelected: true, + paginationFirstText: "@lang('general.first')", + paginationLastText: "@lang('general.last')", + paginationPreText: "@lang('general.previous')", + paginationNextText: "@lang('general.next')", + pageList: ['10','25','50','100','150','200'], + icons: { + paginationSwitchDown: 'fa-caret-square-o-down', + paginationSwitchUp: 'fa-caret-square-o-up', + columns: 'fa-columns', + refresh: 'fa-refresh' + }, + }); +</script> @stop From 0074e1abccae3b7f7df57a596815631263665c5d Mon Sep 17 00:00:00 2001 From: madd15 <joshdeakin@adam.com.au> Date: Tue, 25 Aug 2015 16:37:10 +0930 Subject: [PATCH 037/120] Add name text search --- app/models/License.php | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/app/models/License.php b/app/models/License.php index 3a55253d66..d2be54b610 100755 --- a/app/models/License.php +++ b/app/models/License.php @@ -176,4 +176,21 @@ public function freeSeat() ->get(); } + + /** + * Query builder scope to search on text + * + * @param Illuminate\Database\Query\Builder $query Query builder instance + * @param text $search Search term + * + * @return Illuminate\Database\Query\Builder Modified query builder + */ + public function scopeTextSearch($query, $search) + { + + return $query->where(function($query) use ($search) + { + $query->where('name', 'LIKE', '%'.$search.'%'); + }); + } } From 6bfa5837c5bf45a18a4de398e99b4927ff345073 Mon Sep 17 00:00:00 2001 From: snipe <snipe@snipe.net> Date: Mon, 21 Sep 2015 00:17:22 -0700 Subject: [PATCH 038/120] Updated gitignore to ignore sql dumps --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 2fde66d88e..519a40f4cf 100755 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,7 @@ composer.phar /app/storage/meta/services.json /app/config/*/mail.php /app/config/*/session.php +/app/config/*/ldap.php /app/config/*/database.php /app/config/*/app.php public/packages/* @@ -15,6 +16,7 @@ public/uploads/models/* public/uploads/avatars/* /app/storage/views/* /app/storage/logs/* +/app/storage/dumps/* /app/storage/debugbar/ /bin/ .idea @@ -25,3 +27,4 @@ public/uploads/logo.png public/assets/.siteflow app/config/local/session.php .couscous +2015091584319-backup.zip From 3ecfff94ef9713e623e2b56629dec6f45a9e8a4e Mon Sep 17 00:00:00 2001 From: Daniel Dreier <ddreier@gmail.com> Date: Wed, 30 Sep 2015 22:44:55 -0500 Subject: [PATCH 039/120] Created the migration, copied view stuff from asset edit to acc. and consumable. --- ...51_add_accessory_consumable_price_info.php | 48 +++++++++++++++++++ app/views/backend/accessories/edit.blade.php | 21 ++++++++ app/views/backend/consumables/edit.blade.php | 39 +++++++++++++++ 3 files changed, 108 insertions(+) create mode 100644 app/database/migrations/2015_10_01_024551_add_accessory_consumable_price_info.php diff --git a/app/database/migrations/2015_10_01_024551_add_accessory_consumable_price_info.php b/app/database/migrations/2015_10_01_024551_add_accessory_consumable_price_info.php new file mode 100644 index 0000000000..21bbefc6ac --- /dev/null +++ b/app/database/migrations/2015_10_01_024551_add_accessory_consumable_price_info.php @@ -0,0 +1,48 @@ +<?php + +use Illuminate\Database\Schema\Blueprint; +use Illuminate\Database\Migrations\Migration; + +class AddAccessoryConsumablePriceInfo extends Migration { + + /** + * Run the migrations. + * + * @return void + */ + public function up() + { + Schema::table('accessories', function ($table) { + $table->date('purchase_date')->nullable(); + $table->decimal('purchase_cost', 13, 4)->nullable(); + $table->string('order_number'); + }); + + Schema::table('consumables', function ($table) { + $table->date('purchase_date')->nullable(); + $table->decimal('purchase_cost', 13, 4)->nullable(); + $table->string('order_number'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('accessories', function ($table) { + $table->dropColumn('purchase_date'); + $table->dropColumn('purchase_cost'); + $table->dropColumn('order_number'); + }); + + Schema::table('consumables', function ($table) { + $table->dropColumn('purchase_date'); + $table->dropColumn('purchase_cost'); + $table->dropColumn('order_number'); + }); + } + +} diff --git a/app/views/backend/accessories/edit.blade.php b/app/views/backend/accessories/edit.blade.php index c2880ae31e..bcbc20133a 100755 --- a/app/views/backend/accessories/edit.blade.php +++ b/app/views/backend/accessories/edit.blade.php @@ -58,6 +58,27 @@ {{ $errors->first('category_id', '<span class="alert-msg"><i class="fa fa-times"></i> :message</span>') }} </div> </div> + + <!-- Order Number --> + <div class="form-group {{ $errors->has('order_number') ? ' has-error' : '' }}"> + <label for="order_number" class="col-md-2 control-label">@lang('admin/hardware/form.order')</label> + <div class="col-md-7 col-sm-12"> + <input class="form-control" type="text" name="order_number" id="order_number" value="{{{ Input::old('order_number', $accessory->order_number) }}}" /> + {{ $errors->first('order_number', '<br><span class="alert-msg"><i class="fa fa-times"></i> :message</span>') }} + </div> + </div> + + <!-- Purchase Date --> + <div class="form-group {{ $errors->has('purchase_date') ? ' has-error' : '' }}"> + <label for="purchase_date" class="col-md-2 control-label">@lang('admin/hardware/form.date')</label> + <div class="input-group col-md-3"> + <input type="date" class="datepicker form-control" data-date-format="yyyy-mm-dd" placeholder="@lang('general.select_date')" name="purchase_date" id="purchase_date" value="{{{ Input::old('purchase_date', $accessory->purchase_date) }}}"> + <span class="input-group-addon"><i class="fa fa-calendar"></i></span> + {{ $errors->first('purchase_date', '<br><span class="alert-msg"><i class="fa fa-times"></i> :message</span>') }} + </div> + </div> + + <!-- QTY --> <div class="form-group {{ $errors->has('qty') ? ' has-error' : '' }}"> diff --git a/app/views/backend/consumables/edit.blade.php b/app/views/backend/consumables/edit.blade.php index 9008e55ec3..20294a6147 100644 --- a/app/views/backend/consumables/edit.blade.php +++ b/app/views/backend/consumables/edit.blade.php @@ -58,6 +58,45 @@ {{ $errors->first('category_id', '<span class="alert-msg"><i class="fa fa-times"></i> :message</span>') }} </div> </div> + + <!-- Order Number --> + <div class="form-group {{ $errors->has('order_number') ? ' has-error' : '' }}"> + <label for="order_number" class="col-md-2 control-label">@lang('admin/hardware/form.order')</label> + <div class="col-md-7 col-sm-12"> + <input class="form-control" type="text" name="order_number" id="order_number" value="{{{ Input::old('order_number', $asset->order_number) }}}" /> + {{ $errors->first('order_number', '<br><span class="alert-msg"><i class="fa fa-times"></i> :message</span>') }} + </div> + </div> + + <!-- Purchase Date --> + <div class="form-group {{ $errors->has('purchase_date') ? ' has-error' : '' }}"> + <label for="purchase_date" class="col-md-2 control-label">@lang('admin/hardware/form.date')</label> + <div class="input-group col-md-3"> + <input type="date" class="datepicker form-control" data-date-format="yyyy-mm-dd" placeholder="@lang('general.select_date')" name="purchase_date" id="purchase_date" value="{{{ Input::old('purchase_date', $asset->purchase_date) }}}"> + <span class="input-group-addon"><i class="fa fa-calendar"></i></span> + {{ $errors->first('purchase_date', '<br><span class="alert-msg"><i class="fa fa-times"></i> :message</span>') }} + </div> + </div> + + <!-- Purchase Cost --> + <div class="form-group {{ $errors->has('purchase_cost') ? ' has-error' : '' }}"> + <label for="purchase_cost" class="col-md-2 control-label">@lang('admin/hardware/form.cost') </label> + <div class="col-md-2"> + <div class="input-group"> + <span class="input-group-addon"> + @if (($asset->id) && ($asset->assetloc)) + {{{ $asset->assetloc->currency }}} + @else + {{{ Setting::first()->default_currency }}} + @endif + + + </span> + <input class="col-md-2 form-control" type="text" name="purchase_cost" id="purchase_cost" value="{{ Input::old('purchase_cost', number_format($asset->purchase_cost,2)) }}" /> + {{ $errors->first('purchase_cost', '<br><span class="alert-msg"><i class="fa fa-times"></i> :message</span>') }} + </div> + </div> + </div> <!-- QTY --> <div class="form-group {{ $errors->has('qty') ? ' has-error' : '' }}"> From 73d4c65daf22ac75d10d4179fd3b90e4bdd10569 Mon Sep 17 00:00:00 2001 From: Daniel Dreier <ddreier@gmail.com> Date: Tue, 6 Oct 2015 19:29:44 -0500 Subject: [PATCH 040/120] Finished work on #1088. Added info to view, translation strings and logic to controllers. --- .../admin/AccessoriesController.php | 28 +++++++++++ .../admin/ConsumablesController.php | 42 +++++++++++++--- app/lang/en/admin/accessories/general.php | 3 ++ app/lang/en/admin/consumables/general.php | 3 ++ app/views/backend/accessories/edit.blade.php | 32 ++++++++++--- app/views/backend/accessories/view.blade.php | 18 +++++++ app/views/backend/consumables/edit.blade.php | 48 +++++++++---------- app/views/backend/consumables/view.blade.php | 17 +++++++ 8 files changed, 153 insertions(+), 38 deletions(-) diff --git a/app/controllers/admin/AccessoriesController.php b/app/controllers/admin/AccessoriesController.php index 7fee731d39..f4de9fda09 100755 --- a/app/controllers/admin/AccessoriesController.php +++ b/app/controllers/admin/AccessoriesController.php @@ -68,6 +68,20 @@ class AccessoriesController extends AdminController // Update the accessory data $accessory->name = e(Input::get('name')); $accessory->category_id = e(Input::get('category_id')); + $accessory->order_number = e(Input::get('order_number')); + + if (e(Input::get('purchase_date')) == '') { + $accessory->purchase_date = NULL; + } else { + $accessory->purchase_date = e(Input::get('purchase_date')); + } + + if (e(Input::get('purchase_cost')) == '0.00') { + $accessory->purchase_cost = NULL; + } else { + $accessory->purchase_cost = ParseFloat(e(Input::get('purchase_cost'))); + } + $accessory->qty = e(Input::get('qty')); $accessory->user_id = Sentry::getId(); @@ -136,6 +150,20 @@ class AccessoriesController extends AdminController // Update the accessory data $accessory->name = e(Input::get('name')); $accessory->category_id = e(Input::get('category_id')); + $accessory->order_number = e(Input::get('order_number')); + + if (e(Input::get('purchase_date')) == '') { + $accessory->purchase_date = NULL; + } else { + $accessory->purchase_date = e(Input::get('purchase_date')); + } + + if (e(Input::get('purchase_cost')) == '0.00') { + $accessory->purchase_cost = NULL; + } else { + $accessory->purchase_cost = ParseFloat(e(Input::get('purchase_cost'))); + } + $accessory->qty = e(Input::get('qty')); // Was the accessory created? diff --git a/app/controllers/admin/ConsumablesController.php b/app/controllers/admin/ConsumablesController.php index 05376143b6..8f6bc2ba65 100644 --- a/app/controllers/admin/ConsumablesController.php +++ b/app/controllers/admin/ConsumablesController.php @@ -66,10 +66,24 @@ class ConsumablesController extends AdminController else{ // Update the consumable data - $consumable->name = e(Input::get('name')); - $consumable->category_id = e(Input::get('category_id')); - $consumable->qty = e(Input::get('qty')); - $consumable->user_id = Sentry::getId(); + $consumable->name = e(Input::get('name')); + $consumable->category_id = e(Input::get('category_id')); + $consumable->order_number = e(Input::get('order_number')); + + if (e(Input::get('purchase_date')) == '') { + $consumable->purchase_date = NULL; + } else { + $consumable->purchase_date = e(Input::get('purchase_date')); + } + + if (e(Input::get('purchase_cost')) == '0.00') { + $consumable->purchase_cost = NULL; + } else { + $consumable->purchase_cost = ParseFloat(e(Input::get('purchase_cost'))); + } + + $consumable->qty = e(Input::get('qty')); + $consumable->user_id = Sentry::getId(); // Was the consumable created? if($consumable->save()) { @@ -134,9 +148,23 @@ class ConsumablesController extends AdminController else { // Update the consumable data - $consumable->name = e(Input::get('name')); - $consumable->category_id = e(Input::get('category_id')); - $consumable->qty = e(Input::get('qty')); + $consumable->name = e(Input::get('name')); + $consumable->category_id = e(Input::get('category_id')); + $consumable->order_number = e(Input::get('order_number')); + + if (e(Input::get('purchase_date')) == '') { + $consumable->purchase_date = NULL; + } else { + $consumable->purchase_date = e(Input::get('purchase_date')); + } + + if (e(Input::get('purchase_cost')) == '0.00') { + $consumable->purchase_cost = NULL; + } else { + $consumable->purchase_cost = ParseFloat(e(Input::get('purchase_cost'))); + } + + $consumable->qty = e(Input::get('qty')); // Was the consumable created? if($consumable->save()) { diff --git a/app/lang/en/admin/accessories/general.php b/app/lang/en/admin/accessories/general.php index 7d68dcabc5..85a199dbfc 100755 --- a/app/lang/en/admin/accessories/general.php +++ b/app/lang/en/admin/accessories/general.php @@ -5,11 +5,14 @@ return array( 'about_accessories_text' => 'Accessories are anything you issue to users but that do not have a serial number (or you do not care about tracking them uniquely). For example, computer mice or keyboards.', 'accessory_category' => 'Accessory Category', 'accessory_name' => 'Accessory Name', + 'cost' => 'Purchase Cost', 'create' => 'Create Accessory', + 'date' => 'Purchase Date', 'eula_text' => 'Category EULA', 'eula_text_help' => 'This field allows you to customize your EULAs for specific types of assets. If you only have one EULA for all of your assets, you can check the box below to use the primary default.', 'require_acceptance' => 'Require users to confirm acceptance of assets in this category.', 'no_default_eula' => 'No primary default EULA found. Add one in Settings.', + 'order' => 'Order Number', 'qty' => 'QTY', 'total' => 'Total', 'remaining' => 'Avail', diff --git a/app/lang/en/admin/consumables/general.php b/app/lang/en/admin/consumables/general.php index 01ab4eb692..b29947f13a 100755 --- a/app/lang/en/admin/consumables/general.php +++ b/app/lang/en/admin/consumables/general.php @@ -4,7 +4,10 @@ return array( 'about_consumables_title' => 'About Consumables', 'about_consumables_text' => 'Consumables are anything purchased that will be used up over time. For example, printer ink or copier paper.', 'consumable_name' => 'Consumable Name', + 'cost' => 'Purchase Cost', 'create' => 'Create Consumable', + 'date' => 'Purchase Date', + 'order' => 'Order Number', 'remaining' => 'Remaining', 'total' => 'Total', 'update' => 'Update Consumable', diff --git a/app/views/backend/accessories/edit.blade.php b/app/views/backend/accessories/edit.blade.php index bcbc20133a..02ce60e0f0 100755 --- a/app/views/backend/accessories/edit.blade.php +++ b/app/views/backend/accessories/edit.blade.php @@ -61,8 +61,10 @@ <!-- Order Number --> <div class="form-group {{ $errors->has('order_number') ? ' has-error' : '' }}"> - <label for="order_number" class="col-md-2 control-label">@lang('admin/hardware/form.order')</label> - <div class="col-md-7 col-sm-12"> + <div class="col-md-3"> + {{ Form::label('order_number', Lang::get('admin/accessories/general.order')) }} + </div> + <div class="col-md-3"> <input class="form-control" type="text" name="order_number" id="order_number" value="{{{ Input::old('order_number', $accessory->order_number) }}}" /> {{ $errors->first('order_number', '<br><span class="alert-msg"><i class="fa fa-times"></i> :message</span>') }} </div> @@ -70,15 +72,31 @@ <!-- Purchase Date --> <div class="form-group {{ $errors->has('purchase_date') ? ' has-error' : '' }}"> - <label for="purchase_date" class="col-md-2 control-label">@lang('admin/hardware/form.date')</label> + <div class="col-md-3"> + {{ Form::label('purchase_date', Lang::get('admin/accessories/general.date')) }} + </div> <div class="input-group col-md-3"> <input type="date" class="datepicker form-control" data-date-format="yyyy-mm-dd" placeholder="@lang('general.select_date')" name="purchase_date" id="purchase_date" value="{{{ Input::old('purchase_date', $accessory->purchase_date) }}}"> <span class="input-group-addon"><i class="fa fa-calendar"></i></span> - {{ $errors->first('purchase_date', '<br><span class="alert-msg"><i class="fa fa-times"></i> :message</span>') }} + {{ $errors->first('purchase_date', '<br><span class="alert-msg"><i class="fa fa-times"></i> :message</span>') }} </div> </div> - + <!-- Purchase Cost --> + <div class="form-group {{ $errors->has('purchase_cost') ? ' has-error' : '' }}"> + <div class="col-md-3"> + {{ Form::label('purchase_cost', Lang::get('admin/accessories/general.cost')) }} + </div> + <div class="col-md-2"> + <div class="input-group"> + <span class="input-group-addon"> + {{{ Setting::first()->default_currency }}} + </span> + <input class="col-md-2 form-control" type="text" name="purchase_cost" id="purchase_cost" value="{{ Input::old('purchase_cost', number_format($accessory->purchase_cost,2)) }}" /> + {{ $errors->first('purchase_cost', '<br><span class="alert-msg"><i class="fa fa-times"></i> :message</span>') }} + </div> + </div> + </div> <!-- QTY --> <div class="form-group {{ $errors->has('qty') ? ' has-error' : '' }}"> @@ -87,8 +105,8 @@ <i class='fa fa-asterisk'></i> </div> <div class="col-md-9"> - <div class="col-md-2"> - <input class="form-control" type="text" name="qty" id="qty" value="{{{ Input::old('qty', $accessory->qty) }}}" /> + <div class="col-md-2"> + <input class="form-control" type="text" name="qty" id="qty" value="{{{ Input::old('qty', $accessory->qty) }}}" /> </div> {{ $errors->first('qty', '<span class="alert-msg"><i class="fa fa-times"></i> :message</span>') }} </div> diff --git a/app/views/backend/accessories/view.blade.php b/app/views/backend/accessories/view.blade.php index a5cee39394..93d9c31518 100644 --- a/app/views/backend/accessories/view.blade.php +++ b/app/views/backend/accessories/view.blade.php @@ -27,6 +27,24 @@ <div class="user-profile"> <div class="row profile"> <div class="col-md-9 bio"> + + @if ($accessory->purchase_date) + <div class="col-md-12" style="padding-bottom: 5px;"><strong>@lang('admin/accessories/general.date'): </strong> + {{{ $accessory->purchase_date }}} </div> + @endif + + @if ($accessory->purchase_cost) + <div class="col-md-12" style="padding-bottom: 5px;"><strong>@lang('admin/accessories/general.cost'):</strong> + {{{ Setting::first()->default_currency }}} + + {{{ number_format($accessory->purchase_cost,2) }}} </div> + @endif + + @if ($accessory->order_number) + <div class="col-md-12" style="padding-bottom: 5px;"><strong>@lang('admin/accessories/general.order'):</strong> + {{{ $accessory->order_number }}} </div> + @endif + <br /> <!-- checked out accessories table --> diff --git a/app/views/backend/consumables/edit.blade.php b/app/views/backend/consumables/edit.blade.php index 20294a6147..a33058b7c4 100644 --- a/app/views/backend/consumables/edit.blade.php +++ b/app/views/backend/consumables/edit.blade.php @@ -61,41 +61,41 @@ <!-- Order Number --> <div class="form-group {{ $errors->has('order_number') ? ' has-error' : '' }}"> - <label for="order_number" class="col-md-2 control-label">@lang('admin/hardware/form.order')</label> - <div class="col-md-7 col-sm-12"> - <input class="form-control" type="text" name="order_number" id="order_number" value="{{{ Input::old('order_number', $asset->order_number) }}}" /> + <div class="col-md-3"> + {{ Form::label('order_number', Lang::get('admin/consumables/general.order')) }} + </div> + <div class="col-md-3"> + <input class="form-control" type="text" name="order_number" id="order_number" value="{{{ Input::old('order_number', $consumable->order_number) }}}" /> {{ $errors->first('order_number', '<br><span class="alert-msg"><i class="fa fa-times"></i> :message</span>') }} </div> </div> <!-- Purchase Date --> <div class="form-group {{ $errors->has('purchase_date') ? ' has-error' : '' }}"> - <label for="purchase_date" class="col-md-2 control-label">@lang('admin/hardware/form.date')</label> + <div class="col-md-3"> + {{ Form::label('purchase_date', Lang::get('admin/consumables/general.date')) }} + </div> <div class="input-group col-md-3"> - <input type="date" class="datepicker form-control" data-date-format="yyyy-mm-dd" placeholder="@lang('general.select_date')" name="purchase_date" id="purchase_date" value="{{{ Input::old('purchase_date', $asset->purchase_date) }}}"> + <input type="date" class="datepicker form-control" data-date-format="yyyy-mm-dd" placeholder="@lang('general.select_date')" name="purchase_date" id="purchase_date" value="{{{ Input::old('purchase_date', $consumable->purchase_date) }}}"> <span class="input-group-addon"><i class="fa fa-calendar"></i></span> - {{ $errors->first('purchase_date', '<br><span class="alert-msg"><i class="fa fa-times"></i> :message</span>') }} + {{ $errors->first('purchase_date', '<br><span class="alert-msg"><i class="fa fa-times"></i> :message</span>') }} </div> </div> <!-- Purchase Cost --> <div class="form-group {{ $errors->has('purchase_cost') ? ' has-error' : '' }}"> - <label for="purchase_cost" class="col-md-2 control-label">@lang('admin/hardware/form.cost') </label> - <div class="col-md-2"> - <div class="input-group"> - <span class="input-group-addon"> - @if (($asset->id) && ($asset->assetloc)) - {{{ $asset->assetloc->currency }}} - @else - {{{ Setting::first()->default_currency }}} - @endif - - - </span> - <input class="col-md-2 form-control" type="text" name="purchase_cost" id="purchase_cost" value="{{ Input::old('purchase_cost', number_format($asset->purchase_cost,2)) }}" /> - {{ $errors->first('purchase_cost', '<br><span class="alert-msg"><i class="fa fa-times"></i> :message</span>') }} - </div> - </div> + <div class="col-md-3"> + {{ Form::label('purchase_cost', Lang::get('admin/consumables/general.cost')) }} + </div> + <div class="col-md-2"> + <div class="input-group"> + <span class="input-group-addon"> + {{{ Setting::first()->default_currency }}} + </span> + <input class="col-md-2 form-control" type="text" name="purchase_cost" id="purchase_cost" value="{{ Input::old('purchase_cost', number_format($consumable->purchase_cost,2)) }}" /> + {{ $errors->first('purchase_cost', '<br><span class="alert-msg"><i class="fa fa-times"></i> :message</span>') }} + </div> + </div> </div> <!-- QTY --> @@ -105,8 +105,8 @@ <i class='fa fa-asterisk'></i> </div> <div class="col-md-9"> - <div class="col-md-2"> - <input class="form-control" type="text" name="qty" id="qty" value="{{{ Input::old('qty', $consumable->qty) }}}" /> + <div class="col-md-2"> + <input class="form-control" type="text" name="qty" id="qty" value="{{{ Input::old('qty', $consumable->qty) }}}" /> </div> {{ $errors->first('qty', '<span class="alert-msg"><i class="fa fa-times"></i> :message</span>') }} </div> diff --git a/app/views/backend/consumables/view.blade.php b/app/views/backend/consumables/view.blade.php index 68243c2699..3092c45990 100644 --- a/app/views/backend/consumables/view.blade.php +++ b/app/views/backend/consumables/view.blade.php @@ -27,7 +27,24 @@ <div class="user-profile"> <div class="row profile"> <div class="col-md-9 bio"> + + @if ($consumable->purchase_date) + <div class="col-md-12" style="padding-bottom: 5px;"><strong>@lang('admin/consumables/general.date'): </strong> + {{{ $consumable->purchase_date }}} </div> + @endif + @if ($consumable->purchase_cost) + <div class="col-md-12" style="padding-bottom: 5px;"><strong>@lang('admin/consumables/general.cost'):</strong> + {{{ Setting::first()->default_currency }}} + + {{{ number_format($consumable->purchase_cost,2) }}} </div> + @endif + + @if ($consumable->order_number) + <div class="col-md-12" style="padding-bottom: 5px;"><strong>@lang('admin/consumables/general.order'):</strong> + {{{ $consumable->order_number }}} </div> + @endif + <br /> <!-- checked out consumables table --> @if ($consumable->users->count() > 0) From e9e04e86da8d49d35c958cde2445499aae3f34ac Mon Sep 17 00:00:00 2001 From: Stefan Kittner <stefan.kittner@gmail.com> Date: Mon, 12 Oct 2015 10:26:27 +0200 Subject: [PATCH 041/120] added fixed width for navbar icons (fa-fw) --- app/views/backend/layouts/default.blade.php | 46 ++++++++++----------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/app/views/backend/layouts/default.blade.php b/app/views/backend/layouts/default.blade.php index 7f3186369f..b409510a44 100644 --- a/app/views/backend/layouts/default.blade.php +++ b/app/views/backend/layouts/default.blade.php @@ -131,33 +131,33 @@ @if(Sentry::getUser()->hasAccess('admin')) <li class="dropdown"> <a href="#" class="dropdown-toggle" data-toggle="dropdown"> - <i class="fa fa-plus"></i> @lang('general.create') + <i class="fa fa-plus fa-fw"></i> @lang('general.create') <b class="caret"></b> </a> <ul class="dropdown-menu"> <li {{{ (Request::is('hardware/create') ? 'class="active"' : '') }}}> <a href="{{ route('create/hardware') }}"> - <i class="fa fa-barcode"></i> + <i class="fa fa-barcode fa-fw"></i> @lang('general.asset')</a> </li> <li {{{ (Request::is('admin/licenses/create') ? 'class="active"' : '') }}}> <a href="{{ route('create/licenses') }}"> - <i class="fa fa-certificate"></i> + <i class="fa fa-certificate fa-fw"></i> @lang('general.license')</a> </li> <li {{{ (Request::is('admin/accessories/create') ? 'class="active"' : '') }}}> <a href="{{ route('create/accessory') }}"> - <i class="fa fa-keyboard-o"></i> + <i class="fa fa-keyboard-o fa-fw"></i> @lang('general.accessory')</a> </li> <li {{{ (Request::is('admin/consumables/create') ? 'class="active"' : '') }}}> <a href="{{ route('create/consumable') }}"> - <i class="fa fa-tint"></i> + <i class="fa fa-tint fa-fw"></i> @lang('general.consumable')</a> </li> <li {{{ (Request::is('admin/users/create') ? 'class="active"' : '') }}}> <a href="{{ route('create/user') }}"> - <i class="fa fa-user"></i> + <i class="fa fa-user fa-fw"></i> @lang('general.user')</a> </li> </ul> @@ -165,28 +165,28 @@ @endif <li class="dropdown"> <a href="#" class="dropdown-toggle" data-toggle="dropdown"> - {{{ Lang::get('general.welcome', array('name' => Sentry::getUser()->first_name)) }}} + <i class="fa fa-user fa-fw"></i> {{{ Lang::get('general.welcome', array('name' => Sentry::getUser()->first_name)) }}} <b class="caret"></b> </a> <ul class="dropdown-menu"> <li{{{ (Request::is('account/profile') ? ' class="active"' : '') }}}> <a href="{{ route('view-assets') }}"> - <i class="fa fa-check"></i> @lang('general.viewassets') + <i class="fa fa-check fa-fw"></i> @lang('general.viewassets') </a> <a href="{{ route('profile') }}"> - <i class="fa fa-user"></i> @lang('general.editprofile') + <i class="fa fa-user fa-fw"></i> @lang('general.editprofile') </a> <a href="{{ route('change-password') }}"> - <i class="fa fa-lock"></i> @lang('general.changepassword') + <i class="fa fa-lock fa-fw"></i> @lang('general.changepassword') </a> <a href="{{ route('change-email') }}"> - <i class="fa fa-envelope"></i> @lang('general.changeemail') + <i class="fa fa-envelope fa-fw"></i> @lang('general.changeemail') </a> </li> <li class="divider"></li> <li> <a href="{{ route('logout') }}"> - <i class="fa fa-sign-out"></i> + <i class="fa fa-sign-out fa-fw"></i> @lang('general.logout') </a> </li> @@ -195,59 +195,59 @@ @if(Sentry::getUser()->hasAccess('admin')) <li class="dropdown"> <a href="#" class="dropdown-toggle" data-toggle="dropdown"> - <i class="fa fa-wrench icon-white"></i> @lang('general.admin') + <i class="fa fa-wrench fa-fw"></i> @lang('general.admin') <b class="caret"></b> </a> <ul class="dropdown-menu"> <li{{ (Request::is('hardware/models*') ? ' class="active"' : '') }}> <a href="{{ URL::to('hardware/models') }}"> - <i class="fa fa-th"></i> @lang('general.asset_models') + <i class="fa fa-th fa-fw"></i> @lang('general.asset_models') </a> </li> <li{{ (Request::is('admin/settings/categories*') ? ' class="active"' : '') }}> <a href="{{ URL::to('admin/settings/categories') }}"> - <i class="fa fa-check"></i> @lang('general.categories') + <i class="fa fa-check fa-fw"></i> @lang('general.categories') </a> </li> <li{{ (Request::is('admin/settings/manufacturers*') ? ' class="active"' : '') }}> <a href="{{ URL::to('admin/settings/manufacturers') }}"> - <i class="fa fa-briefcase"></i> @lang('general.manufacturers') + <i class="fa fa-briefcase fa-fw"></i> @lang('general.manufacturers') </a> </li> <li{{ (Request::is('admin/settings/suppliers*') ? ' class="active"' : '') }}> <a href="{{ URL::to('admin/settings/suppliers') }}"> - <i class="fa fa-credit-card"></i> @lang('general.suppliers') + <i class="fa fa-credit-card fa-fw"></i> @lang('general.suppliers') </a> </li> <li{{ (Request::is('admin/settings/statuslabels*') ? ' class="active"' : '') }}> <a href="{{ URL::to('admin/settings/statuslabels') }}"> - <i class="fa fa-list"></i> @lang('general.status_labels') + <i class="fa fa-list fa-fw"></i> @lang('general.status_labels') </a> </li> <li{{ (Request::is('admin/settings/depreciations*') ? ' class="active"' : '') }}> <a href="{{ URL::to('admin/settings/depreciations') }}"> - <i class="fa fa-arrow-down"></i> @lang('general.depreciation') + <i class="fa fa-arrow-down fa-fw"></i> @lang('general.depreciation') </a> </li> <li{{ (Request::is('admin/settings/locations*') ? ' class="active"' : '') }}> <a href="{{ URL::to('admin/settings/locations') }}"> - <i class="fa fa-globe"></i> @lang('general.locations') + <i class="fa fa-globe fa-fw"></i> @lang('general.locations') </a> </li> <li{{ (Request::is('admin/groups*') ? ' class="active"' : '') }}> <a href="{{ URL::to('admin/groups') }}"> - <i class="fa fa-group"></i> @lang('general.groups') + <i class="fa fa-group fa-fw"></i> @lang('general.groups') </a> </li> <li{{ (Request::is('admin/settings/backups*') ? ' class="active"' : '') }}> <a href="{{ URL::to('admin/settings/backups') }}"> - <i class="fa fa-download"></i> @lang('admin/settings/general.backups') + <i class="fa fa-download fa-fw"></i> @lang('admin/settings/general.backups') </a> </li> <li class="divider"></li> <li> <a href="{{ route('app') }}"> - <i class="fa fa-cog"></i> @lang('general.settings') + <i class="fa fa-cog fa-fw"></i> @lang('general.settings') </a> </li> From 485b34b66e9570d40376f33c28a802e276476074 Mon Sep 17 00:00:00 2001 From: Stefan <stefan.kittner@gfk.com> Date: Mon, 12 Oct 2015 19:14:05 +0200 Subject: [PATCH 042/120] fixed layout and added branding option --- app/lang/en/admin/settings/general.php | 6 +- app/views/backend/settings/edit.blade.php | 607 ++++++++++------------ 2 files changed, 291 insertions(+), 322 deletions(-) diff --git a/app/lang/en/admin/settings/general.php b/app/lang/en/admin/settings/general.php index ff19aca7e7..d4f404c00c 100755 --- a/app/lang/en/admin/settings/general.php +++ b/app/lang/en/admin/settings/general.php @@ -26,7 +26,8 @@ return array( 'header_color' => 'Header Color', 'info' => 'These settings let you customize certain aspects of your installation.', 'laravel' => 'Laravel Version', - 'load_remote' => 'This Snipe-IT install can load scripts from the outside world.', + 'load_remote_text' => 'Remote Scripts', + 'load_remote_help_text' => 'This Snipe-IT install can load scripts from the outside world.', 'logo' => 'Logo', 'optional' => 'optional', 'per_page' => 'Results Per Page', @@ -47,4 +48,7 @@ return array( 'system' => 'System Information', 'update' => 'Update Settings', 'value' => 'Value', + 'brand' => 'Branding', + 'about_settings_title' => 'About Settings', + 'about_settings_text' => 'These settings let you customize certain aspects of your installation.', ); diff --git a/app/views/backend/settings/edit.blade.php b/app/views/backend/settings/edit.blade.php index fa522defba..41a7e89138 100755 --- a/app/views/backend/settings/edit.blade.php +++ b/app/views/backend/settings/edit.blade.php @@ -2,335 +2,300 @@ {{-- Page title --}} @section('title') - @lang('admin/settings/general.update') :: +@lang('admin/settings/general.update') :: @parent @stop {{-- Page content --}} @section('content') - -<style> -.checkbox { -padding-left: 0px; -} -#pad-wrapper { -padding: 0px 20px; -} -</style> - -<div id="pad-wrapper" class="user-profile"> - - <!-- header --> - - <div class="pull-right"> - <a href="{{ URL::previous() }}" class="btn-flat gray"> - <i class="fa fa-arrow-left icon-white"></i> @lang('general.back')</a> - </div> - - <h3 class="name">@lang('admin/settings/general.update')</h3> - - - <div class="profile"> - - <!-- bio, new note & orders column --> - - <div class="col-md-9 bio"> - <div class="profile-box"> - <br> - - {{ Form::open(['method' => 'POST', 'files' => true, 'class' => 'form-horizontal', 'role' => 'form' ]) }} - <!-- CSRF Token --> - {{ Form::hidden('_token', csrf_token()) }} - - - @foreach ($settings as $setting) - - <h4>@lang('admin/settings/general.general_settings')</h4> - - <div class="form-group {{ $errors->has('site_name') ? 'error' : '' }}"> - <div class="col-md-3"> - {{ Form::label('site_name', Lang::get('admin/settings/general.site_name')) }} - </div> - <div class="col-md-9"> - @if (Config::get('app.lock_passwords')===true) - {{ Form::text('site_name', Input::old('site_name', $setting->site_name), array('class' => 'form-control', 'disabled'=>'disabled','placeholder' => 'Snipe-IT Asset Management')) }} - @else - {{ Form::text('site_name', Input::old('site_name', $setting->site_name), array('class' => 'form-control','placeholder' => 'Snipe-IT Asset Management')) }} - - @endif - - {{ $errors->first('site_name', '<br><span class="alert-msg">:message</span>') }} - </div> - </div> - - <div class="form-group {{ $errors->has('logo') ? 'has-error' : '' }}"> - - <div class="col-md-3"> - {{ Form::label('logo', Lang::get('admin/settings/general.logo')) }} - </div> - <div class="col-md-9"> - - @if (Config::get('app.lock_passwords')) - <p class="help-block">@lang('general.lock_passwords')</p> - @else - - {{ Form::file('logo') }} - {{ $errors->first('logo', '<br><span class="alert-msg">:message</span>') }} - {{ Form::checkbox('clear_logo', '1', Input::old('clear_logo')) }} Remove - @endif - </div> - - </div> - - - <div class="form-group {{ $errors->has('default_currency') ? 'error' : '' }}"> - <div class="col-md-3"> - {{ Form::label('default_currency', Lang::get('admin/settings/general.default_currency')) }} - </div> - <div class="col-md-9"> - {{ Form::currencies('default_currency', Input::old('default_currency', $setting->default_currency)) }} - - - {{ $errors->first('default_currency', '<br><span class="alert-msg">:message</span>') }} - </div> - </div> - - <div class="form-group {{ $errors->has('alert_email') ? 'error' : '' }}"> - <div class="col-md-3"> - {{ Form::label('alert_email', Lang::get('admin/settings/general.alert_email')) }} - </div> - <div class="col-md-9"> - {{ Form::text('alert_email', Input::old('alert_email', $setting->alert_email), array('class' => 'form-control','placeholder' => 'admin@yourcompany.com')) }} - - - {{ Form::checkbox('alerts_enabled', '1', Input::old('alerts_enabled', $setting->alerts_enabled)) }} - @Lang('admin/settings/general.alerts_enabled') - - - {{ $errors->first('alert_email', '<br><span class="alert-msg">:message</span>') }} - </div> - </div> - - - <div class="form-group {{ $errors->has('header_color') ? 'error' : '' }}"> - <div class="col-md-3"> - {{ Form::label('header_color', Lang::get('admin/settings/general.header_color')) }} - </div> - <div class="col-md-9"> - - {{ Form::text('header_color', Input::old('header_color', $setting->header_color), array('class' => 'form-control', 'style' => 'width: 100px;')) }} - {{ $errors->first('header_color', '<br><span class="alert-msg">:message</span>') }} - </div> - </div> - - <div class="form-group {{ $errors->has('custom_css') ? 'error' : '' }}"> - <div class="col-md-3"> - {{ Form::label('custom_css', Lang::get('admin/settings/general.custom_css')) }} - </div> - <div class="col-md-9"> - - @if (Config::get('app.lock_passwords')===true) - {{ Form::textarea('custom_css', Input::old('custom_css', $setting->custom_css), array('class' => 'form-control','placeholder' => 'Add your custom CSS','disabled'=>'disabled')) }} - {{ $errors->first('custom_css', '<br><span class="alert-msg">:message</span>') }} - <p class="help-block">@lang('general.lock_passwords')</p> - @else - {{ Form::textarea('custom_css', Input::old('custom_css', $setting->custom_css), array('class' => 'form-control','placeholder' => 'Add your custom CSS')) }} - {{ $errors->first('custom_css', '<br><span class="alert-msg">:message</span>') }} - @endif - - - <p class="help-inline">@lang('admin/settings/general.custom_css_help')</p> - </div> - - - <div class="form-group {{ $errors->has('per_page') ? 'error' : '' }}"> - <div class="col-md-3"> - {{ Form::label('per_page', Lang::get('admin/settings/general.per_page')) }} - </div> - <div class="col-md-9"> - {{ Form::select('per_page', array('10'=>'10','25'=>'25','50'=>'50','75'=>'75','100'=>'100','125'=>'125','150'=>'150'), Input::old('per_page', $setting->per_page), array('class' => 'form-control', 'style'=>'width: 100px;')) }} - {{ $errors->first('per_page', '<br><span class="alert-msg">:message</span>') }} - </div> - </div> - - - - <div class="checkbox col-md-offset-3"> - <label> - {{ Form::checkbox('load_remote', '1', Input::old('load_remote', $setting->load_remote)) }} - @lang('admin/settings/general.load_remote') - </label> - </div> - <hr> - <h4>@lang('admin/settings/general.asset_ids') (@lang('admin/settings/general.optional'))</h4> - <div class="checkbox col-md-offset-3"> - <label> - {{ Form::checkbox('auto_increment_assets', '1', Input::old('auto_increment_assets', $setting->auto_increment_assets)) }} - @lang('admin/settings/general.auto_increment_assets') - </label> - </div> - - <div class="form-group {{ $errors->has('auto_increment_prefix') ? 'error' : '' }}"> - <div class="col-md-3"> - {{ Form::label('auto_increment_prefix', Lang::get('admin/settings/general.auto_increment_prefix')) }} - </div> - <div class="col-md-9"> - @if ($setting->auto_increment_assets == 1) - {{ Form::text('auto_increment_prefix', Input::old('auto_increment_prefix', $setting->auto_increment_prefix), array('class' => 'form-control', 'style'=>'width: 100px;')) }} - {{ $errors->first('auto_increment_prefix', '<br><span class="alert-msg">:message</span>') }} - @else - {{ Form::text('auto_increment_prefix', Input::old('auto_increment_prefix', $setting->auto_increment_prefix), array('class' => 'form-control', 'disabled'=>'disabled', 'style'=>'width: 100px;')) }} - @endif - - </div> - </div> - - - - <hr> - <h4>@lang('admin/settings/general.barcode_settings') (@lang('admin/settings/general.optional'))</h4> - @if ($is_gd_installed) - - <div class="checkbox col-md-offset-3 col-md-9" style="padding-bottom: 10px;"> - <label> - {{ Form::checkbox('qr_code', '1', Input::old('qr_code', $setting->qr_code)) }} - @lang('admin/settings/general.display_qr') - </label> - </div> - - <!-- Code type --> - <div class="form-group{{ $errors->has('barcode_type') ? ' has-error' : '' }}"> - <div class="col-md-3"> - {{ Form::label('barcode_type', Lang::get('admin/settings/general.barcode_type')) }} - </div> - - <div class="col-md-9"> - {{ Form::barcode_types('barcode_type', Input::old('barcode_type', $setting->barcode_type), 'select2') }} - - - {{ $errors->first('barcode_type', '<br><span class="alert-msg"><i class="fa fa-times"></i> :message</span>') }} - </div> - </div> - - - - <div class="form-group {{ $errors->has('qr_text') ? 'error' : '' }}"> - <div class="col-md-3"> - {{ Form::label('qr_text', Lang::get('admin/settings/general.qr_text')) }} - </div> - <div class="col-md-9"> - @if ($setting->qr_code == 1) - {{ Form::text('qr_text', Input::old('qr_text', $setting->qr_text), array('class' => 'form-control','placeholder' => 'Property of Your Company')) }} - {{ $errors->first('qr_text', '<br><span class="alert-msg">:message</span>') }} - @else - {{ Form::text('qr_text', Input::old('qr_text', $setting->qr_text), array('class' => 'form-control', 'disabled'=>'disabled','placeholder' => 'Property of Your Company')) }} - <p class="help-inline"> - @lang('admin/settings/general.qr_help') - </p> - @endif - </div> - - </div> - - @else - <span class="help-inline col-md-offset-3 col-md-12"> - @lang('admin/settings/general.php_gd_warning') - <br> - @lang('admin/settings/general.php_gd_info') - </span> - @endif - - - - <hr> - <h4>@lang('admin/settings/general.eula_settings') (@lang('admin/settings/general.optional'))</h4> - <div class="form-group {{ $errors->has('default_eula_text') ? 'error' : '' }}"> - <div class="col-md-3"> - {{ Form::label('default_eula_text', Lang::get('admin/settings/general.default_eula_text')) }} - </div> - <div class="col-md-9"> - {{ Form::textarea('default_eula_text', Input::old('default_eula_text', $setting->default_eula_text), array('class' => 'form-control','placeholder' => 'Add your default EULA text')) }} - {{ $errors->first('default_eula_text', '<br><span class="alert-msg">:message</span>') }} - - <p class="help-inline">@lang('admin/settings/general.default_eula_help_text')</p> - <p class="help-inline">@lang('admin/settings/general.eula_markdown')</p> - - </div> - - - </div> - - <hr> - <h4>@lang('admin/settings/general.slack_integration') (@lang('admin/settings/general.optional'))</h4> - <p class="help-inline">@lang('admin/settings/general.slack_integration_help',array('slack_link' => 'https://my.slack.com/services/new/incoming-webhook'))</p> - <div class="form-group {{ $errors->has('slack_channel') ? 'error' : '' }}"> - <div class="col-md-3"> - {{ Form::label('slack_endpoint', Lang::get('admin/settings/general.slack_endpoint')) }} - </div> - <div class="col-md-9"> - - @if (Config::get('app.lock_passwords')===true) - {{ Form::text('slack_endpoint', Input::old('slack_endpoint', $setting->slack_endpoint), array('class' => 'form-control','disabled'=>'disabled','placeholder' => 'https://hooks.slack.com/services/XXXXXXXXXXXXXXXXXXXXX')) }} - @else - {{ Form::text('slack_endpoint', Input::old('slack_endpoint', $setting->slack_endpoint), array('class' => 'form-control','placeholder' => 'https://hooks.slack.com/services/XXXXXXXXXXXXXXXXXXXXX')) }} - @endif - - {{ $errors->first('slack_endpoint', '<br><span class="alert-msg">:message</span>') }} - </div> - </div> - - <div class="form-group {{ $errors->has('slack_channel') ? 'error' : '' }}"> - <div class="col-md-3"> - {{ Form::label('slack_channel', Lang::get('admin/settings/general.slack_channel')) }} - </div> - <div class="col-md-9"> - @if (Config::get('app.lock_passwords')===true) - {{ Form::text('slack_channel', Input::old('slack_channel', $setting->slack_channel), array('class' => 'form-control','disabled'=>'disabled','placeholder' => '#IT-Ops')) }} - @else - {{ Form::text('slack_channel', Input::old('slack_channel', $setting->slack_channel), array('class' => 'form-control','placeholder' => '#IT-Ops')) }} - @endif - {{ $errors->first('slack_channel', '<br><span class="alert-msg">:message</span>') }} - </div> - </div> - - <div class="form-group {{ $errors->has('slack_botname') ? 'error' : '' }}"> - <div class="col-md-3"> - {{ Form::label('slack_botname', Lang::get('admin/settings/general.slack_botname')) }} - </div> - <div class="col-md-9"> - @if (Config::get('app.lock_passwords')===true) - {{ Form::text('slack_botname', Input::old('slack_botname', $setting->slack_botname), array('class' => 'form-control','disabled'=>'disabled','placeholder' => 'Snipe-IT Bot')) }} - @else - {{ Form::text('slack_botname', Input::old('slack_botname', $setting->slack_botname), array('class' => 'form-control','placeholder' => 'Snipe-IT Bot')) }} - @endif - {{ $errors->first('slack_botname', '<br><span class="alert-msg">:message</span>') }} - </div> - </div> - - - - - @endforeach - - <!-- Form actions --> - <div class="form-group"> - <div class="controls col-md-offset-3"> - <a class="btn btn-link" href="{{ URL::previous() }}">@lang('button.cancel')</a> - <button type="submit" class="btn-flat success"><i class="fa fa-check icon-white"></i> @lang('general.save')</button> - </div> - </div> - - </form> - </div> - +<div class="row header"> + <div class="col-md-12"> + <a href="{{ URL::previous() }}" class="btn btn-flat gray pull-right"><i class="fa fa-arrow-left icon-white"></i> @lang('general.back')</a> + <h3>@lang('admin/settings/general.update')</h3> + </div> </div> - <!-- side address column --> - <div class="col-md-3 address pull-right"> - <br /><br /> - <p>@lang('admin/settings/general.info')</p> +<div class="user-profile"> + <div class="row profile"> + <div class="col-md-9 bio"> - </div> + {{ Form::open(['method' => 'POST', 'files' => true, 'class' => 'form-horizontal', 'role' => 'form' ]) }} + <!-- CSRF Token --> + {{ Form::hidden('_token', csrf_token()) }} + @foreach ($settings as $setting) + + + + <h4>@lang('admin/settings/general.general_settings')</h4> + + <!-- Site name --> + <div class="form-group {{ $errors->has('site_name') ? 'error' : '' }}"> + <div class="col-md-3"> + {{ Form::label('site_name', Lang::get('admin/settings/general.site_name')) }} + </div> + <div class="col-md-9"> + @if (Config::get('app.lock_passwords')===true) + {{ Form::text('site_name', Input::old('site_name', $setting->site_name), array('class' => 'form-control', 'disabled'=>'disabled','placeholder' => 'Snipe-IT Asset Management')) }} + @else + {{ Form::text('site_name', Input::old('site_name', $setting->site_name), array('class' => 'form-control','placeholder' => 'Snipe-IT Asset Management')) }} + @endif + + {{ $errors->first('site_name', '<br><span class="alert-msg">:message</span>') }} + </div> + </div> + + <!-- Logo --> + <div class="form-group {{ $errors->has('logo') ? 'has-error' : '' }}"> + <div class="col-md-3"> + {{ Form::label('logo', Lang::get('admin/settings/general.logo')) }} + </div> + <div class="col-md-9"> + @if (Config::get('app.lock_passwords')) + <p class="help-block">@lang('general.lock_passwords')</p> + @else + {{ Form::file('logo') }} + {{ $errors->first('logo', '<br><span class="alert-msg">:message</span>') }} + {{ Form::checkbox('clear_logo', '1', Input::old('clear_logo')) }} Remove + @endif + </div> + </div> + + <!-- Branding --> + <div class="form-group {{ $errors->has('brand') ? 'error' : '' }}"> + <div class="col-md-3"> + {{ Form::label('brand', Lang::get('admin/settings/general.brand')) }} + </div> + <div class="col-md-9"> + {{ Form::select('brand', array('1'=>'Text','2'=>'Logo','3'=>'Logo + Text'), Input::old('brand', $setting->brand), array('class' => 'form-control', 'style'=>'width: 150px ;')) }} + {{ $errors->first('brand', '<br><span class="alert-msg">:message</span>') }} + </div> + </div> + + <!-- Currency --> + <div class="form-group {{ $errors->has('default_currency') ? 'error' : '' }}"> + <div class="col-md-3"> + {{ Form::label('default_currency', Lang::get('admin/settings/general.default_currency')) }} + </div> + <div class="col-md-9"> + {{ Form::currencies('default_currency', Input::old('default_currency', $setting->default_currency),'form-control') }} + {{ $errors->first('default_currency', '<br><span class="alert-msg">:message</span>') }} + </div> + </div> + + <!-- Alert Email --> + <div class="form-group {{ $errors->has('alert_email') ? 'error' : '' }}"> + <div class="col-md-3"> + {{ Form::label('alert_email', Lang::get('admin/settings/general.alert_email')) }} + </div> + <div class="col-md-9"> + {{ Form::text('alert_email', Input::old('alert_email', $setting->alert_email), array('class' => 'form-control','placeholder' => 'admin@yourcompany.com')) }} + {{ Form::checkbox('alerts_enabled', '1', Input::old('alerts_enabled', $setting->alerts_enabled)) }} + @Lang('admin/settings/general.alerts_enabled') + {{ $errors->first('alert_email', '<br><span class="alert-msg">:message</span>') }} + </div> + </div> + + <!-- Header color --> + <div class="form-group {{ $errors->has('header_color') ? 'error' : '' }}"> + <div class="col-md-3"> + {{ Form::label('header_color', Lang::get('admin/settings/general.header_color')) }} + </div> + <div class="col-md-9"> + {{ Form::text('header_color', Input::old('header_color', $setting->header_color), array('class' => 'form-control', 'style' => 'width: 100px;')) }} + {{ $errors->first('header_color', '<br><span class="alert-msg">:message</span>') }} + </div> + </div> + + <!-- Custom css --> + <div class="form-group {{ $errors->has('custom_css') ? 'error' : '' }}"> + <div class="col-md-3"> + {{ Form::label('custom_css', Lang::get('admin/settings/general.custom_css')) }} + </div> + <div class="col-md-9"> + @if (Config::get('app.lock_passwords')===true) + {{ Form::textarea('custom_css', Input::old('custom_css', $setting->custom_css), array('class' => 'form-control','placeholder' => 'Add your custom CSS','disabled'=>'disabled')) }} + {{ $errors->first('custom_css', '<br><span class="alert-msg">:message</span>') }} + <p class="help-block">@lang('general.lock_passwords')</p> + @else + {{ Form::textarea('custom_css', Input::old('custom_css', $setting->custom_css), array('class' => 'form-control','placeholder' => 'Add your custom CSS')) }} + {{ $errors->first('custom_css', '<br><span class="alert-msg">:message</span>') }} + @endif + <p class="help-inline">@lang('admin/settings/general.custom_css_help')</p> + </div> + </div> + + <!-- results per page --> + <div class="form-group {{ $errors->has('per_page') ? 'error' : '' }}"> + <div class="col-md-3"> + {{ Form::label('per_page', Lang::get('admin/settings/general.per_page')) }} + </div> + <div class="col-md-9"> + {{ Form::select('per_page', array('10'=>'10','25'=>'25','50'=>'50','75'=>'75','100'=>'100','125'=>'125','150'=>'150'), Input::old('per_page', $setting->per_page), array('class' => 'form-control', 'style'=>'width: 100px;')) }} + {{ $errors->first('per_page', '<br><span class="alert-msg">:message</span>') }} + </div> + </div> + + <!-- remote load --> + <div class="form-group"> + <div class="col-md-3"> + {{ Form::label('load_remote', Lang::get('admin/settings/general.load_remote_text')) }} + </div> + <div class="col-md-9"> + {{ Form::checkbox('load_remote', '1', Input::old('load_remote', $setting->load_remote)) }} + @lang('admin/settings/general.load_remote_help_text') + </div> + </div> + + <hr><h4>@lang('admin/settings/general.asset_ids') (@lang('admin/settings/general.optional'))</h4> + + <!-- auto ids --> + <div class="form-group"> + <div class="col-md-3"> + {{ Form::label('auto_increment_assets', Lang::get('admin/settings/general.asset_ids')) }} + </div> + <div class="col-md-9"> + {{ Form::checkbox('auto_increment_assets', '1', Input::old('auto_increment_assets', $setting->auto_increment_assets)) }} + @lang('admin/settings/general.auto_increment_assets') + </div> + </div> + + <!-- auto prefix --> + <div class="form-group {{ $errors->has('auto_increment_prefix') ? 'error' : '' }}"> + <div class="col-md-3"> + {{ Form::label('auto_increment_prefix', Lang::get('admin/settings/general.auto_increment_prefix')) }} + </div> + <div class="col-md-9"> + @if ($setting->auto_increment_assets == 1) + {{ Form::text('auto_increment_prefix', Input::old('auto_increment_prefix', $setting->auto_increment_prefix), array('class' => 'form-control', 'style'=>'width: 100px;')) }} + {{ $errors->first('auto_increment_prefix', '<br><span class="alert-msg">:message</span>') }} + @else + {{ Form::text('auto_increment_prefix', Input::old('auto_increment_prefix', $setting->auto_increment_prefix), array('class' => 'form-control', 'disabled'=>'disabled', 'style'=>'width: 100px;')) }} + @endif + </div> + </div> + + <hr><h4>@lang('admin/settings/general.barcode_settings') (@lang('admin/settings/general.optional'))</h4> + + @if ($is_gd_installed) + + <!-- qr code --> + <div class="form-group"> + <div class="col-md-3"> + {{ Form::label('qr_code', Lang::get('admin/settings/general.display_qr')) }} + </div> + <div class="col-md-9"> + {{ Form::checkbox('qr_code', '1', Input::old('qr_code', $setting->qr_code)) }} + @lang('admin/settings/general.display_qr') + </div> + </div> + + <!-- barcode type --> + <div class="form-group{{ $errors->has('barcode_type') ? ' has-error' : '' }}"> + <div class="col-md-3"> + {{ Form::label('barcode_type', Lang::get('admin/settings/general.barcode_type')) }} + </div> + <div class="col-md-9"> + {{ Form::barcode_types('barcode_type', Input::old('barcode_type', $setting->barcode_type), 'select2') }} + {{ $errors->first('barcode_type', '<br><span class="alert-msg"><i class="fa fa-times"></i> :message</span>') }} + </div> + </div> + + <!-- qr text --> + <div class="form-group {{ $errors->has('qr_text') ? 'error' : '' }}"> + <div class="col-md-3"> + {{ Form::label('qr_text', Lang::get('admin/settings/general.qr_text')) }} + </div> + <div class="col-md-9"> + @if ($setting->qr_code == 1) + {{ Form::text('qr_text', Input::old('qr_text', $setting->qr_text), array('class' => 'form-control','placeholder' => 'Property of Your Company')) }} + {{ $errors->first('qr_text', '<br><span class="alert-msg">:message</span>') }} + @else + {{ Form::text('qr_text', Input::old('qr_text', $setting->qr_text), array('class' => 'form-control', 'disabled'=>'disabled','placeholder' => 'Property of Your Company')) }} + <p class="help-inline">@lang('admin/settings/general.qr_help')</p> + @endif + </div> + </div> + + @else + <span class="help-inline col-md-offset-3 col-md-12"> + @lang('admin/settings/general.php_gd_warning') + <br> + @lang('admin/settings/general.php_gd_info') + </span> + @endif + + <hr><h4>@lang('admin/settings/general.eula_settings') (@lang('admin/settings/general.optional'))</h4> + <!-- EULA text --> + <div class="form-group {{ $errors->has('default_eula_text') ? 'error' : '' }}"> + <div class="col-md-3"> + {{ Form::label('default_eula_text', Lang::get('admin/settings/general.default_eula_text')) }} + </div> + <div class="col-md-9"> + {{ Form::textarea('default_eula_text', Input::old('default_eula_text', $setting->default_eula_text), array('class' => 'form-control','placeholder' => 'Add your default EULA text')) }} + {{ $errors->first('default_eula_text', '<br><span class="alert-msg">:message</span>') }} + <p class="help-inline">@lang('admin/settings/general.default_eula_help_text')</p> + <p class="help-inline">@lang('admin/settings/general.eula_markdown')</p> + </div> + </div> + + <hr><h4>@lang('admin/settings/general.slack_integration') (@lang('admin/settings/general.optional'))</h4> +<p class="help-inline">@lang('admin/settings/general.slack_integration_help',array('slack_link' => 'https://my.slack.com/services/new/incoming-webhook'))</p> + + <!-- slack endpoint --> + <div class="form-group {{ $errors->has('slack_endpoint') ? 'error' : '' }}"> + <div class="col-md-3"> + {{ Form::label('slack_endpoint', Lang::get('admin/settings/general.slack_endpoint')) }} + </div> + <div class="col-md-9"> + @if (Config::get('app.lock_passwords')===true) + {{ Form::text('slack_endpoint', Input::old('slack_endpoint', $setting->slack_endpoint), array('class' => 'form-control','disabled'=>'disabled','placeholder' => 'https://hooks.slack.com/services/XXXXXXXXXXXXXXXXXXXXX')) }} + @else + {{ Form::text('slack_endpoint', Input::old('slack_endpoint', $setting->slack_endpoint), array('class' => 'form-control','placeholder' => 'https://hooks.slack.com/services/XXXXXXXXXXXXXXXXXXXXX')) }} + @endif + {{ $errors->first('slack_endpoint', '<br><span class="alert-msg">:message</span>') }} + </div> + </div> + + <!-- slack channel --> + <div class="form-group {{ $errors->has('slack_channel') ? 'error' : '' }}"> + <div class="col-md-3"> + {{ Form::label('slack_channel', Lang::get('admin/settings/general.slack_channel')) }} + </div> + <div class="col-md-9"> + @if (Config::get('app.lock_passwords')===true) + {{ Form::text('slack_channel', Input::old('slack_channel', $setting->slack_channel), array('class' => 'form-control','disabled'=>'disabled','placeholder' => '#IT-Ops')) }} + @else + {{ Form::text('slack_channel', Input::old('slack_channel', $setting->slack_channel), array('class' => 'form-control','placeholder' => '#IT-Ops')) }} + @endif + {{ $errors->first('slack_channel', '<br><span class="alert-msg">:message</span>') }} + </div> + </div> + + @endforeach + + <!-- Form actions --> + <div class="form-group"> + <div class="controls col-md-offset-3"> + <a class="btn btn-link" href="{{ URL::previous() }}">@lang('button.cancel')</a> + <button type="submit" class="btn-flat success"><i class="fa fa-check icon-white"></i> @lang('general.save')</button> + </div> + </div> + + </form> + + + + </div> + + + <!-- side address column --> + <div class="col-md-3 col-xs-12 address pull-right"> + <br /><br /> + <h6>@lang('admin/settings/general.about_settings_title')</h6> + <p>@lang('admin/settings/general.about_settings_text')</p> + + </div> + </div> </div> @stop From a6586b5919253b7b2bb77cceaff6455d7b87f6f8 Mon Sep 17 00:00:00 2001 From: Stefan <stefan.kittner@gfk.com> Date: Mon, 12 Oct 2015 20:34:12 +0200 Subject: [PATCH 043/120] Added option to select brand type text or logo or text + logo --- app/controllers/admin/SettingsController.php | 4 ++- ...015_10_12_192706_add_brand_to_settings.php | 34 +++++++++++++++++++ app/views/backend/layouts/default.blade.php | 7 +++- app/views/backend/settings/edit.blade.php | 2 +- 4 files changed, 44 insertions(+), 3 deletions(-) create mode 100644 app/database/migrations/2015_10_12_192706_add_brand_to_settings.php diff --git a/app/controllers/admin/SettingsController.php b/app/controllers/admin/SettingsController.php index c714fefac1..e4a572298d 100755 --- a/app/controllers/admin/SettingsController.php +++ b/app/controllers/admin/SettingsController.php @@ -68,7 +68,8 @@ class SettingsController extends AdminController // Declare the rules for the form validation $rules = array( - "per_page" => 'required|min:1|numeric', + "brand" => 'required|min:1|numeric', + "per_page" => 'required|min:1|numeric', "qr_text" => 'min:1|max:31', "logo" => 'mimes:jpeg,bmp,png,gif', "custom_css" => 'alpha_space', @@ -115,6 +116,7 @@ class SettingsController extends AdminController if (Config::get('app.lock_passwords')==false) { $setting->site_name = e(Input::get('site_name')); + $setting->brand = e(Input::get('brand')); $setting->custom_css = e(Input::get('custom_css')); } diff --git a/app/database/migrations/2015_10_12_192706_add_brand_to_settings.php b/app/database/migrations/2015_10_12_192706_add_brand_to_settings.php new file mode 100644 index 0000000000..eae3acd849 --- /dev/null +++ b/app/database/migrations/2015_10_12_192706_add_brand_to_settings.php @@ -0,0 +1,34 @@ +<?php + +use Illuminate\Database\Schema\Blueprint; +use Illuminate\Database\Migrations\Migration; + +class AddBrandToSettings extends Migration { + + /** + * Run the migrations. + * + * @return void + */ + public function up() + { + Schema::table('settings', function(Blueprint $table) + { + $table->tinyInteger('brand')->default(1); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('settings', function(Blueprint $table) + { + $table->dropColumn('brand'); + }); + } + +} diff --git a/app/views/backend/layouts/default.blade.php b/app/views/backend/layouts/default.blade.php index b409510a44..1b3921fd76 100644 --- a/app/views/backend/layouts/default.blade.php +++ b/app/views/backend/layouts/default.blade.php @@ -113,7 +113,12 @@ </button> - @if (Setting::getSettings()->logo) + @if (Setting::getSettings()->brand === 3) + <a class="navbar-brand" href="{{ Config::get('app.url') }}" style="padding: 5px;"> + <img src="{{ Config::get('app.url') }}/uploads/{{{ Setting::getSettings()->logo }}}"> + {{{ Setting::getSettings()->site_name }}} + </a> + @elseif (Setting::getSettings()->brand === 2) <a class="navbar-brand" href="{{ Config::get('app.url') }}" style="padding: 5px;"> <img src="{{ Config::get('app.url') }}/uploads/{{{ Setting::getSettings()->logo }}}"> </a> diff --git a/app/views/backend/settings/edit.blade.php b/app/views/backend/settings/edit.blade.php index 41a7e89138..7c04f68dca 100755 --- a/app/views/backend/settings/edit.blade.php +++ b/app/views/backend/settings/edit.blade.php @@ -102,7 +102,7 @@ {{ Form::label('header_color', Lang::get('admin/settings/general.header_color')) }} </div> <div class="col-md-9"> - {{ Form::text('header_color', Input::old('header_color', $setting->header_color), array('class' => 'form-control', 'style' => 'width: 100px;')) }} + {{ Form::text('header_color', Input::old('header_color', $setting->header_color), array('class' => 'form-control', 'style' => 'width: 100px;','placeholder' => '#FF0000')) }} {{ $errors->first('header_color', '<br><span class="alert-msg">:message</span>') }} </div> </div> From 0db075cb13eb045ed863411a8f5801a980db481a Mon Sep 17 00:00:00 2001 From: Stefan <stefan.kittner@gfk.com> Date: Mon, 12 Oct 2015 21:00:27 +0200 Subject: [PATCH 044/120] fixes lang option for remote script --- app/views/backend/settings/index.blade.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/backend/settings/index.blade.php b/app/views/backend/settings/index.blade.php index 619fa1d10b..b856a23784 100755 --- a/app/views/backend/settings/index.blade.php +++ b/app/views/backend/settings/index.blade.php @@ -73,7 +73,7 @@ </tr> <tr> - <td>@lang('admin/settings/general.load_remote')</td> + <td>@lang('admin/settings/general.load_remote_text')</td> @if ($setting->load_remote == 1) <td>@lang('general.yes')</td> From 01f00cfe515971eb34095abda7eb059248b3a39d Mon Sep 17 00:00:00 2001 From: snipe <snipe@snipe.net> Date: Tue, 20 Oct 2015 17:52:14 -0700 Subject: [PATCH 045/120] Updated ignore for LDAP --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index cac14d0785..c1315449fe 100755 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,7 @@ composer.phar /app/config/*/session.php /app/config/*/database.php /app/config/*/app.php +/app/config/*/ldap.php public/packages/* public/uploads/models/* public/uploads/avatars/* From 78143cbd1caef32a90ad5d928e95ec47bf8e3fc8 Mon Sep 17 00:00:00 2001 From: snipe <snipe@snipe.net> Date: Tue, 20 Oct 2015 17:52:20 -0700 Subject: [PATCH 046/120] Bumped version --- app/config/version.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/config/version.php b/app/config/version.php index ccae3f3627..761cc57c43 100644 --- a/app/config/version.php +++ b/app/config/version.php @@ -1,5 +1,5 @@ <?php return array ( - 'app_version' => 'v2.0-175', - 'hash_version' => 'v2.0-175-gd0aab3e', + 'app_version' => 'v2.0-227', + 'hash_version' => 'v2.0-227-gb492ac4', ); \ No newline at end of file From 9264e7bdc4db61076180414c47fed866db02376f Mon Sep 17 00:00:00 2001 From: snipe <snipe@snipe.net> Date: Tue, 20 Oct 2015 18:08:53 -0700 Subject: [PATCH 047/120] Fixed missing limit --- app/controllers/admin/AssetsController.php | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/app/controllers/admin/AssetsController.php b/app/controllers/admin/AssetsController.php index 05efa470f7..32ef574fe7 100755 --- a/app/controllers/admin/AssetsController.php +++ b/app/controllers/admin/AssetsController.php @@ -1083,6 +1083,18 @@ class AssetsController extends AdminController public function getDatatable($status = null) { + if (Input::has('offset')) { + $offset = e(Input::get('offset')); + } else { + $offset = 0; + } + + if (Input::has('limit')) { + $limit = e(Input::get('limit')); + } else { + $limit = 50; + } + $assets = Asset::with('model','assigneduser','assigneduser.userloc','assetstatus','defaultLoc','assetlog','model','model.category')->Hardware()->select(array('assets.id', 'assets.name','assets.model_id','assets.assigned_to','assets.asset_tag','assets.serial','assets.status_id','assets.purchase_date','assets.deleted_at','assets.rtd_location_id','assets.notes','assets.order_number')); @@ -1118,7 +1130,7 @@ class AssetsController extends AdminController if (Input::has('search')) { $assets = $assets->TextSearch(Input::get('search')); } - + $allowed_columns = ['name','asset_tag','serial','model','checkout_date','category','notes']; $order = Input::get('order') === 'asc' ? 'asc' : 'desc'; $sort = in_array(Input::get('sort'), $allowed_columns) ? Input::get('sort') : 'asset_tag'; @@ -1140,7 +1152,7 @@ class AssetsController extends AdminController } $assetCount = $assets->count(); - $assets = $assets->skip(Input::get('offset'))->take(Input::get('limit'))->get(); + $assets = $assets->skip($offset)->take($limit)->get(); $rows = array(); @@ -1169,12 +1181,12 @@ class AssetsController extends AdminController 'asset_tag' => '<a title="'.$asset->asset_tag.'" href="hardware/'.$asset->id.'/view">'.$asset->asset_tag.'</a>', 'serial' => $asset->serial, 'model' => ($asset->model) ? $asset->model->name : 'No model', - 'status' => ($asset->assigned_to!='') ? link_to('../admin/users/'.$asset->assigned_to.'/view', $asset->assigneduser->fullName()) : (($asset->assetstatus) ? $asset->assetstatus->name : ''), - 'location' => (($asset->assigned_to)&&($asset->assigneduser->userloc!='')) ? link_to('admin/settings/locations/'.$asset->assigneduser->userloc->id.'/edit', $asset->assigneduser->userloc->name) : (($asset->defaultLoc!='') ? link_to('admin/settings/locations/'.$asset->defaultLoc->id.'/edit', $asset->defaultLoc->name) : ''), + 'status' => ($asset->assigneduser) ? link_to('../admin/users/'.$asset->assigned_to.'/view', $asset->assigneduser->fullName()) : (($asset->assetstatus) ? $asset->assetstatus->name : ''), + 'location' => (($asset->assigneduser) && ($asset->assigneduser->userloc!='')) ? link_to('admin/settings/locations/'.$asset->assigneduser->userloc->id.'/edit', $asset->assigneduser->userloc->name) : (($asset->defaultLoc!='') ? link_to('admin/settings/locations/'.$asset->defaultLoc->id.'/edit', $asset->defaultLoc->name) : ''), 'category' => ($asset->model->category) ? $asset->model->category->name : 'No category', 'eol' => ($asset->eol_date()) ? $asset->eol_date() : '', 'notes' => $asset->notes, - 'order_number' => ($asset->order_number) ? '<a href="../hardware/?order_number='.$asset->order_number.'">'.$asset->order_number.'</a>' : '', + 'order_number' => ($asset->order_number!='') ? '<a href="../hardware/?order_number='.$asset->order_number.'">'.$asset->order_number.'</a>' : ' ', 'checkout_date' => (($asset->assigned_to!='')&&($asset->assetlog->first())) ? $asset->assetlog->first()->created_at->format('Y-m-d') : '', 'change' => ($inout) ? $inout : '', 'actions' => ($actions) ? $actions : '' From 58911cd10e1c61310c281682eef2d6d281d5dd59 Mon Sep 17 00:00:00 2001 From: snipe <snipe@snipe.net> Date: Tue, 20 Oct 2015 18:51:21 -0700 Subject: [PATCH 048/120] Use moar_scripts to limit unnecessary loading --- app/config/version.php | 4 +-- app/controllers/admin/AssetsController.php | 26 +++++++++---------- app/views/backend/accessories/index.blade.php | 14 ++++++++++ app/views/backend/consumables/index.blade.php | 9 +++++++ app/views/backend/hardware/index.blade.php | 16 ++++++++++-- app/views/backend/layouts/default.blade.php | 20 ++++++-------- app/views/backend/licenses/index.blade.php | 10 +++++++ 7 files changed, 70 insertions(+), 29 deletions(-) diff --git a/app/config/version.php b/app/config/version.php index 761cc57c43..9495128716 100644 --- a/app/config/version.php +++ b/app/config/version.php @@ -1,5 +1,5 @@ <?php return array ( - 'app_version' => 'v2.0-227', - 'hash_version' => 'v2.0-227-gb492ac4', + 'app_version' => 'v2.0-229', + 'hash_version' => 'v2.0-229-g78143cb', ); \ No newline at end of file diff --git a/app/controllers/admin/AssetsController.php b/app/controllers/admin/AssetsController.php index 32ef574fe7..6e87d49619 100755 --- a/app/controllers/admin/AssetsController.php +++ b/app/controllers/admin/AssetsController.php @@ -1176,20 +1176,20 @@ class AssetsController extends AdminController } $rows[] = array( - 'checkbox' =>'<div class="text-center"><input type="checkbox" name="edit_asset['.$asset->id.']" class="one_required"></div>', - 'name' => '<a title="'.$asset->name.'" href="hardware/'.$asset->id.'/view">'.$asset->name.'</a>', - 'asset_tag' => '<a title="'.$asset->asset_tag.'" href="hardware/'.$asset->id.'/view">'.$asset->asset_tag.'</a>', - 'serial' => $asset->serial, - 'model' => ($asset->model) ? $asset->model->name : 'No model', - 'status' => ($asset->assigneduser) ? link_to('../admin/users/'.$asset->assigned_to.'/view', $asset->assigneduser->fullName()) : (($asset->assetstatus) ? $asset->assetstatus->name : ''), - 'location' => (($asset->assigneduser) && ($asset->assigneduser->userloc!='')) ? link_to('admin/settings/locations/'.$asset->assigneduser->userloc->id.'/edit', $asset->assigneduser->userloc->name) : (($asset->defaultLoc!='') ? link_to('admin/settings/locations/'.$asset->defaultLoc->id.'/edit', $asset->defaultLoc->name) : ''), - 'category' => ($asset->model->category) ? $asset->model->category->name : 'No category', - 'eol' => ($asset->eol_date()) ? $asset->eol_date() : '', - 'notes' => $asset->notes, - 'order_number' => ($asset->order_number!='') ? '<a href="../hardware/?order_number='.$asset->order_number.'">'.$asset->order_number.'</a>' : ' ', + 'checkbox' =>'<div class="text-center"><input type="checkbox" name="edit_asset['.$asset->id.']" class="one_required"></div>', + 'name' => '<a title="'.$asset->name.'" href="hardware/'.$asset->id.'/view">'.$asset->name.'</a>', + 'asset_tag' => '<a title="'.$asset->asset_tag.'" href="hardware/'.$asset->id.'/view">'.$asset->asset_tag.'</a>', + 'serial' => $asset->serial, + 'model' => ($asset->model) ? $asset->model->name : 'No model', + 'status' => ($asset->assigneduser) ? link_to('../admin/users/'.$asset->assigned_to.'/view', $asset->assigneduser->fullName()) : (($asset->assetstatus) ? $asset->assetstatus->name : ''), + 'location' => (($asset->assigneduser) && ($asset->assigneduser->userloc!='')) ? link_to('admin/settings/locations/'.$asset->assigneduser->userloc->id.'/edit', $asset->assigneduser->userloc->name) : (($asset->defaultLoc!='') ? link_to('admin/settings/locations/'.$asset->defaultLoc->id.'/edit', $asset->defaultLoc->name) : ''), + 'category' => ($asset->model->category) ? $asset->model->category->name : 'No category', + 'eol' => ($asset->eol_date()) ? $asset->eol_date() : '', + 'notes' => $asset->notes, + 'order_number' => ($asset->order_number!='') ? '<a href="../hardware/?order_number='.$asset->order_number.'">'.$asset->order_number.'</a>' : 'none', 'checkout_date' => (($asset->assigned_to!='')&&($asset->assetlog->first())) ? $asset->assetlog->first()->created_at->format('Y-m-d') : '', - 'change' => ($inout) ? $inout : '', - 'actions' => ($actions) ? $actions : '' + 'change' => ($inout) ? $inout : '', + 'actions' => ($actions) ? $actions : '' ); } diff --git a/app/views/backend/accessories/index.blade.php b/app/views/backend/accessories/index.blade.php index 947163ce7d..2ec51fa526 100755 --- a/app/views/backend/accessories/index.blade.php +++ b/app/views/backend/accessories/index.blade.php @@ -42,6 +42,18 @@ </div> </div> +@section('moar_scripts') +<script src="{{ asset('assets/js/bootstrap-table.js') }}"></script> +<script src="{{ asset('assets/js/extensions/cookie/bootstrap-table-cookie.js') }}"></script> +<script src="{{ asset('assets/js/extensions/mobile/bootstrap-table-mobile.js') }}"></script> +<script src="{{ asset('assets/js/libs/FileSaver/FileSaver.min.js') }}"></script> +<script src="{{ asset('assets/js/libs/html2canvas/html2canvas.min.js') }}"></script> +<script src="{{ asset('assets/js/libs/jsPDF/jspdf.min.js') }}"></script> +<script src="{{ asset('assets/js/libs/jsPDF-AutoTable/jspdf.plugin.autotable.js') }}"></script> +<script src="//rawgit.com/kayalshri/tableExport.jquery.plugin/master/tableExport.js?v=1"></script> +<script src="//rawgit.com/kayalshri/tableExport.jquery.plugin/master/jquery.base64.js?v=1"></script> + + <script type="text/javascript"> $('#table').bootstrapTable({ classes: 'table table-hover table-no-bordered', @@ -70,5 +82,7 @@ }, }); </script> +@stop + @stop diff --git a/app/views/backend/consumables/index.blade.php b/app/views/backend/consumables/index.blade.php index 3672d73ae6..3f2cd84ff2 100644 --- a/app/views/backend/consumables/index.blade.php +++ b/app/views/backend/consumables/index.blade.php @@ -41,6 +41,14 @@ </div> </div> +@section('moar_scripts') +<script src="{{ asset('assets/js/bootstrap-table.js') }}"></script> +<script src="{{ asset('assets/js/extensions/mobile/bootstrap-table-mobile.js') }}"></script> +<script src="{{ asset('assets/js/extensions/export/bootstrap-table-export.js?v=1') }}"></script> +<script src="{{ asset('assets/js/extensions/cookie/bootstrap-table-cookie.js?v=1') }}"></script> +<script src="//rawgit.com/kayalshri/tableExport.jquery.plugin/master/tableExport.js?v=1') }}"></script> +<script src="//rawgit.com/kayalshri/tableExport.jquery.plugin/master/jquery.base64.js?v=1') }}"></script> + <script type="text/javascript"> $('#table').bootstrapTable({ classes: 'table table-hover table-no-bordered', @@ -69,5 +77,6 @@ }, }); </script> +@stop @stop diff --git a/app/views/backend/hardware/index.blade.php b/app/views/backend/hardware/index.blade.php index 6a154d0865..8c1d288478 100755 --- a/app/views/backend/hardware/index.blade.php +++ b/app/views/backend/hardware/index.blade.php @@ -85,7 +85,16 @@ </table> {{ Form::close() }} +</div> + +@section('moar_scripts') +<script src="{{ asset('assets/js/bootstrap-table.js') }}"></script> +<script src="{{ asset('assets/js/extensions/mobile/bootstrap-table-mobile.js') }}"></script> +<script src="{{ asset('assets/js/extensions/export/bootstrap-table-export.js?v=1') }}"></script> +<script src="{{ asset('assets/js/extensions/cookie/bootstrap-table-cookie.js?v=1') }}"></script> +<script src="//rawgit.com/kayalshri/tableExport.jquery.plugin/master/tableExport.js?v=1') }}"></script> +<script src="//rawgit.com/kayalshri/tableExport.jquery.plugin/master/jquery.base64.js?v=1') }}"></script> <script type="text/javascript"> $('#table').bootstrapTable({ classes: 'table table-responsive table-no-bordered', @@ -97,8 +106,11 @@ pagination: true, sidePagination: 'server', sortable: true, + cookie: true, mobileResponsive: true, columnsHidden: ['name'], + showExport: true, + exportLabel: 'Export', showColumns: true, maintainSelected: true, paginationFirstText: "@lang('general.first')", @@ -134,6 +146,6 @@ }); }); </script> - -</div> +@stop + @stop diff --git a/app/views/backend/layouts/default.blade.php b/app/views/backend/layouts/default.blade.php index 78f382b0a7..cd9d84d036 100644 --- a/app/views/backend/layouts/default.blade.php +++ b/app/views/backend/layouts/default.blade.php @@ -5,7 +5,7 @@ <!-- Basic Page Needs ================================================== --> - <meta http-equiv="X-UA-Compatible" content="IE=edge" /> + <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta charset="utf-8" /> <title> @section('title') @@ -43,16 +43,6 @@ <!-- global header javascripts --> - <script src="{{ asset('assets/js/jquery-latest.js') }}"></script> - <script src="{{ asset('assets/js/bootstrap-table.js') }}"></script> - <script src="{{ asset('assets/js/extensions/export/bootstrap-table-export.js') }}"></script> - <script src="{{ asset('assets/js/extensions/cookie/bootstrap-table-cookie.js') }}"></script> - <script src="{{ asset('assets/js/extensions/mobile/bootstrap-table-mobile.js') }}"></script> - <script src="{{ asset('assets/js/libs/FileSaver/FileSaver.min.js') }}"></script> - <script src="{{ asset('assets/js/libs/html2canvas/html2canvas.min.js') }}"></script> - <script src="{{ asset('assets/js/libs/jsPDF/jspdf.min.js') }}"></script> - <script src="{{ asset('assets/js/libs/jsPDF-AutoTable/jspdf.plugin.autotable.js') }}"></script> - <script> window.snipeit = { settings: { @@ -464,12 +454,18 @@ </div> <!-- scripts --> - <script src="{{ asset('assets/js/bootstrap.min.js') }}"></script> + + <script src="{{ asset('assets/js/jquery-latest.js') }}"></script> + <script src="{{ asset('assets/js/bootstrap.min.js') }}"></script> <script src="{{ asset('assets/js/jquery.knob.js') }}"></script> <script src="{{ asset('assets/js/select2.min.js') }}"></script> <script src="{{ asset('assets/js/jquery.uniform.min.js') }}"></script> <script src="{{ asset('assets/js/bootstrap.datepicker.js') }}"></script> <script src="{{ asset('assets/js/theme.js') }}"></script> <script src="{{ asset('assets/js/snipeit.js') }}"></script> + + @section('moar_scripts') + @show + </body> </html> diff --git a/app/views/backend/licenses/index.blade.php b/app/views/backend/licenses/index.blade.php index c2c899b702..51447ea576 100755 --- a/app/views/backend/licenses/index.blade.php +++ b/app/views/backend/licenses/index.blade.php @@ -31,6 +31,14 @@ </table> </div> +@section('moar_scripts') +<script src="{{ asset('assets/js/bootstrap-table.js') }}"></script> +<script src="{{ asset('assets/js/extensions/mobile/bootstrap-table-mobile.js') }}"></script> +<script src="{{ asset('assets/js/extensions/export/bootstrap-table-export.js?v=1') }}"></script> +<script src="{{ asset('assets/js/extensions/cookie/bootstrap-table-cookie.js?v=1') }}"></script> +<script src="//rawgit.com/kayalshri/tableExport.jquery.plugin/master/tableExport.js?v=1') }}"></script> +<script src="//rawgit.com/kayalshri/tableExport.jquery.plugin/master/jquery.base64.js?v=1') }}"></script> + <script type="text/javascript"> $('#table').bootstrapTable({ classes: 'table table-hover table-no-bordered', @@ -60,3 +68,5 @@ }); </script> @stop + +@stop From 377e4c06a11d478579db990602f61148e97ba688 Mon Sep 17 00:00:00 2001 From: snipe <snipe@snipe.net> Date: Tue, 20 Oct 2015 18:58:21 -0700 Subject: [PATCH 049/120] Standardizing BS tables options for #1266 (should be made into a macro) --- app/config/version.php | 4 ++-- app/views/backend/accessories/index.blade.php | 23 +++++++++---------- app/views/backend/consumables/index.blade.php | 12 ++++++---- app/views/backend/hardware/index.blade.php | 2 +- app/views/backend/licenses/index.blade.php | 11 +++++---- 5 files changed, 29 insertions(+), 23 deletions(-) diff --git a/app/config/version.php b/app/config/version.php index 9495128716..246801623e 100644 --- a/app/config/version.php +++ b/app/config/version.php @@ -1,5 +1,5 @@ <?php return array ( - 'app_version' => 'v2.0-229', - 'hash_version' => 'v2.0-229-g78143cb', + 'app_version' => 'v2.0-230', + 'hash_version' => 'v2.0-230-g9264e7b', ); \ No newline at end of file diff --git a/app/views/backend/accessories/index.blade.php b/app/views/backend/accessories/index.blade.php index 2ec51fa526..98117c9e00 100755 --- a/app/views/backend/accessories/index.blade.php +++ b/app/views/backend/accessories/index.blade.php @@ -44,20 +44,15 @@ @section('moar_scripts') <script src="{{ asset('assets/js/bootstrap-table.js') }}"></script> -<script src="{{ asset('assets/js/extensions/cookie/bootstrap-table-cookie.js') }}"></script> <script src="{{ asset('assets/js/extensions/mobile/bootstrap-table-mobile.js') }}"></script> -<script src="{{ asset('assets/js/libs/FileSaver/FileSaver.min.js') }}"></script> -<script src="{{ asset('assets/js/libs/html2canvas/html2canvas.min.js') }}"></script> -<script src="{{ asset('assets/js/libs/jsPDF/jspdf.min.js') }}"></script> -<script src="{{ asset('assets/js/libs/jsPDF-AutoTable/jspdf.plugin.autotable.js') }}"></script> -<script src="//rawgit.com/kayalshri/tableExport.jquery.plugin/master/tableExport.js?v=1"></script> -<script src="//rawgit.com/kayalshri/tableExport.jquery.plugin/master/jquery.base64.js?v=1"></script> - - +<script src="{{ asset('assets/js/extensions/export/bootstrap-table-export.js?v=1') }}"></script> +<script src="{{ asset('assets/js/extensions/cookie/bootstrap-table-cookie.js?v=1') }}"></script> +<script src="//rawgit.com/kayalshri/tableExport.jquery.plugin/master/tableExport.js?v=1') }}"></script> +<script src="//rawgit.com/kayalshri/tableExport.jquery.plugin/master/jquery.base64.js?v=1') }}"></script> <script type="text/javascript"> $('#table').bootstrapTable({ - classes: 'table table-hover table-no-bordered', - undefinedText: 'undefined', + classes: 'table table-responsive table-no-bordered', + undefinedText: '', iconsPrefix: 'fa', showRefresh: true, search: true, @@ -65,9 +60,12 @@ pagination: true, sidePagination: 'server', sortable: true, + cookie: true, mobileResponsive: true, + columnsHidden: ['name'], showExport: true, - showColumns: false, + exportLabel: 'Export', + showColumns: true, maintainSelected: true, paginationFirstText: "@lang('general.first')", paginationLastText: "@lang('general.last')", @@ -80,6 +78,7 @@ columns: 'fa-columns', refresh: 'fa-refresh' }, + }); </script> @stop diff --git a/app/views/backend/consumables/index.blade.php b/app/views/backend/consumables/index.blade.php index 3f2cd84ff2..c20897243b 100644 --- a/app/views/backend/consumables/index.blade.php +++ b/app/views/backend/consumables/index.blade.php @@ -48,11 +48,10 @@ <script src="{{ asset('assets/js/extensions/cookie/bootstrap-table-cookie.js?v=1') }}"></script> <script src="//rawgit.com/kayalshri/tableExport.jquery.plugin/master/tableExport.js?v=1') }}"></script> <script src="//rawgit.com/kayalshri/tableExport.jquery.plugin/master/jquery.base64.js?v=1') }}"></script> - <script type="text/javascript"> $('#table').bootstrapTable({ - classes: 'table table-hover table-no-bordered', - undefinedText: 'undefined', + classes: 'table table-responsive table-no-bordered', + undefinedText: '', iconsPrefix: 'fa', showRefresh: true, search: true, @@ -60,9 +59,12 @@ pagination: true, sidePagination: 'server', sortable: true, + cookie: true, mobileResponsive: true, + columnsHidden: ['name'], showExport: true, - showColumns: false, + exportLabel: 'Export', + showColumns: true, maintainSelected: true, paginationFirstText: "@lang('general.first')", paginationLastText: "@lang('general.last')", @@ -75,8 +77,10 @@ columns: 'fa-columns', refresh: 'fa-refresh' }, + }); </script> + @stop @stop diff --git a/app/views/backend/hardware/index.blade.php b/app/views/backend/hardware/index.blade.php index 8c1d288478..906e1b5103 100755 --- a/app/views/backend/hardware/index.blade.php +++ b/app/views/backend/hardware/index.blade.php @@ -98,7 +98,7 @@ <script type="text/javascript"> $('#table').bootstrapTable({ classes: 'table table-responsive table-no-bordered', - undefinedText: 'undefined', + undefinedText: '', iconsPrefix: 'fa', showRefresh: true, search: true, diff --git a/app/views/backend/licenses/index.blade.php b/app/views/backend/licenses/index.blade.php index 51447ea576..67a794ac2b 100755 --- a/app/views/backend/licenses/index.blade.php +++ b/app/views/backend/licenses/index.blade.php @@ -38,11 +38,10 @@ <script src="{{ asset('assets/js/extensions/cookie/bootstrap-table-cookie.js?v=1') }}"></script> <script src="//rawgit.com/kayalshri/tableExport.jquery.plugin/master/tableExport.js?v=1') }}"></script> <script src="//rawgit.com/kayalshri/tableExport.jquery.plugin/master/jquery.base64.js?v=1') }}"></script> - <script type="text/javascript"> $('#table').bootstrapTable({ - classes: 'table table-hover table-no-bordered', - undefinedText: 'undefined', + classes: 'table table-responsive table-no-bordered', + undefinedText: '', iconsPrefix: 'fa', showRefresh: true, search: true, @@ -50,9 +49,12 @@ pagination: true, sidePagination: 'server', sortable: true, + cookie: true, mobileResponsive: true, + columnsHidden: ['name'], showExport: true, - showColumns: false, + exportLabel: 'Export', + showColumns: true, maintainSelected: true, paginationFirstText: "@lang('general.first')", paginationLastText: "@lang('general.last')", @@ -65,6 +67,7 @@ columns: 'fa-columns', refresh: 'fa-refresh' }, + }); </script> @stop From b56aba3cc2dc9517ffeb05b0548242de08d91829 Mon Sep 17 00:00:00 2001 From: snipe <snipe@snipe.net> Date: Tue, 20 Oct 2015 19:51:10 -0700 Subject: [PATCH 050/120] Added basic text search - this needs to be fleshed out more with more search options --- app/models/User.php | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/app/models/User.php b/app/models/User.php index 4f51934e10..1990c690a0 100755 --- a/app/models/User.php +++ b/app/models/User.php @@ -200,5 +200,28 @@ class User extends SentryUserModel } + /** + * Query builder scope to search on text + * + * @param Illuminate\Database\Query\Builder $query Query builder instance + * @param text $search Search term + * + * @return Illuminate\Database\Query\Builder Modified query builder + */ + public function scopeTextsearch($query, $q) + { + + return $query->where(function($query) use ($q) + { + + $query->orWhere('first_name', 'LIKE', "%$q%") + ->orWhere('first_name', 'LIKE', "%$q%") + ->orWhere('email', 'LIKE', "%$q%") + ->orWhere('username', 'LIKE', "%$q%") + ->orWhere('notes', 'LIKE', "%$q%"); + }); + + } + } From f4d882606af674edd4554165ffd64927307185bf Mon Sep 17 00:00:00 2001 From: snipe <snipe@snipe.net> Date: Tue, 20 Oct 2015 19:51:28 -0700 Subject: [PATCH 051/120] New getDataTable method for Bootstrap tables --- app/controllers/admin/UsersController.php | 138 +++++++++++----------- 1 file changed, 66 insertions(+), 72 deletions(-) diff --git a/app/controllers/admin/UsersController.php b/app/controllers/admin/UsersController.php index cc40728bbb..7b2226b794 100755 --- a/app/controllers/admin/UsersController.php +++ b/app/controllers/admin/UsersController.php @@ -824,94 +824,88 @@ class UsersController extends AdminController { return Redirect::route('users')->with('duplicates', $duplicates)->with('success', 'Success'); } - public function getDatatable($status = null) { + public function getDatatable($status = null) + { + + if (Input::has('offset')) { + $offset = e(Input::get('offset')); + } else { + $offset = 0; + } + + if (Input::has('limit')) { + $limit = e(Input::get('limit')); + } else { + $limit = 50; + } $users = User::with('assets', 'accessories', 'consumables', 'licenses', 'manager', 'sentryThrottle', 'groups', 'userloc'); - switch ($status) { - case 'deleted': - $users->GetDeleted(); - break; - case '': - $users->GetNotDeleted(); - break; - } - $users = $users->orderBy('created_at', 'DESC')->get(); + if (Input::has('search')) { + $users = $users->TextSearch(Input::get('search')); + } - $actions = new \Chumper\Datatable\Columns\FunctionColumn('actions', function ($users) { - $action_buttons = ''; + $allowed_columns = ['last_name','first_name','email','username','manager','location','assets','accessories', 'consumables','licenses','groups']; + $order = Input::get('order') === 'asc' ? 'asc' : 'desc'; + $sort = in_array(Input::get('sort'), $allowed_columns) ? Input::get('sort') : 'last_name'; - if (!is_null($users->deleted_at)) { - $action_buttons .= '<a href="' . route('restore/user', $users->id) . '" class="btn btn-warning btn-sm"><i class="fa fa-share icon-white"></i></a> '; + $userCount = $users->count(); + $users = $users->skip($offset)->take($limit)->get(); + + + $rows = array(); + + foreach ($users as $user) + { + + $group_names = ''; + $inout = ''; + $actions = ''; + + foreach ($user->groups as $group) { + $group_names .= '<a href="' . Config::get('app.url') . '/admin/groups/' . $group->id . '/edit" class="label label-default">' . $group->name . '</a> '; + } + + + if (!is_null($user->deleted_at)) { + + $actions .= '<a href="' . route('restore/user', $user->id) . '" class="btn btn-warning btn-sm"><i class="fa fa-share icon-white"></i></a> '; } else { - if ($users->accountStatus() == 'suspended') { - $action_buttons .= '<a href="' . route('unsuspend/user', $users->id) . '" class="btn btn-default btn-sm"><span class="fa fa-clock-o"></span></a> '; + + if ($user->accountStatus() == 'suspended') { + $actions .= '<a href="' . route('unsuspend/user', $user->id) . '" class="btn btn-default btn-sm"><span class="fa fa-clock-o"></span></a> '; } - $action_buttons .= '<a href="' . route('update/user', $users->id) . '" class="btn btn-warning btn-sm"><i class="fa fa-pencil icon-white"></i></a> '; + $actions .= '<a href="' . route('update/user', $user->id) . '" class="btn btn-warning btn-sm"><i class="fa fa-pencil icon-white"></i></a> '; - if ((Sentry::getId() !== $users->id) && (!Config::get('app.lock_passwords'))) { - $action_buttons .= '<a data-html="false" class="btn delete-asset btn-danger btn-sm" data-toggle="modal" href="' . route('delete/user', $users->id) . '" data-content="Are you sure you wish to delete this user?" data-title="Delete ' . htmlspecialchars($users->first_name) . '?" onClick="return false;"><i class="fa fa-trash icon-white"></i></a> '; + if ((Sentry::getId() !== $user->id) && (!Config::get('app.lock_passwords'))) { + $actions .= '<a data-html="false" class="btn delete-asset btn-danger btn-sm" data-toggle="modal" href="' . route('delete/user', $user->id) . '" data-content="Are you sure you wish to delete this user?" data-title="Delete ' . htmlspecialchars($user->first_name) . '?" onClick="return false;"><i class="fa fa-trash icon-white"></i></a> '; } else { - $action_buttons .= ' <span class="btn delete-asset btn-danger btn-sm disabled"><i class="fa fa-trash icon-white"></i></span>'; + $actions .= ' <span class="btn delete-asset btn-danger btn-sm disabled"><i class="fa fa-trash icon-white"></i></span>'; } } - return $action_buttons; - }); + $rows[] = array( + 'checkbox' =>'<div class="text-center"><input type="checkbox" name="edit_user['.$user->id.']" class="one_required"></div>', + 'name' => '<a title="'.$user->fullName().'" href="hardware/'.$user->id.'/view">'.$user->fullName().'</a>', + 'email' => ($user->email!='') ? '<a href="mailto:'.$user->email.'"><i class="fa fa-envelope"></i></a>' : '', + 'username' => $user->username, + 'location' => ($user->location_id!='') ? $user->userloc->name : '', + 'manager' => ($user->manager_id!='') ? '<a title="' . $user->manager->fullName() . '" href="users/' . $user->manager->id . '/view">' . $user->manager->fullName() . '</a>' : '', + 'assets' => $user->assets->count(), + 'licenses' => $user->licenses->count(), + 'accessories' => $user->accessories->count(), + 'consumables' => $user->consumables->count(), + 'groups' => $group_names, + 'notes' => $user->notes, + 'actions' => ($actions) ? $actions : '' + ); + } - return Datatable::collection($users) - ->addColumn('', function($users) { - return '<div class="text-center"><input type="checkbox" name="edit_user[]" value="' . $users->id . '" class="one_required"></div>'; - }) - ->addColumn('name', function($users) { - return '<a title="' . $users->fullName() . '" href="users/' . $users->id . '/view">' . $users->fullName() . '</a>'; - }) - ->addColumn('email', function($users) { - if ($users->email) { - return '<div class="text-center"><a title="' . $users->email . '" href="mailto:' . $users->email . '"><i class="fa fa-envelope fa-lg"></i></div>'; - } else { - return ''; - } - }) - ->addColumn('username', function($users) { - return $users->username; - }) - ->addColumn('manager', function($users) { - if ($users->manager) { - return '<a title="' . $users->manager->fullName() . '" href="users/' . $users->manager->id . '/view">' . $users->manager->fullName() . '</a>'; - } - }) - ->addColumn('location', function($users) { - if ($users->userloc) { - return $users->userloc->name; - } - }) - ->addColumn('assets', function($users) { - return $users->assets->count(); - }) - ->addColumn('licenses', function($users) { - return $users->licenses->count(); - }) - ->addColumn('accessories', function($users) { - return $users->accessories->count(); - }) - ->addColumn('consumables', function($users) { - return $users->consumables->count(); - }) - ->addColumn('groups', function($users) { - $group_names = ''; - foreach ($users->groups as $group) { - $group_names .= '<a href="' . Config::get('app.url') . '/admin/groups/' . $group->id . '/edit" class="label label-default">' . $group->name . '</a> '; - } - return $group_names; - }) - ->addColumn($actions) - ->searchColumns('name', 'email', 'username', 'manager', 'activated', 'groups', 'location') - ->orderColumns('name', 'email', 'username', 'manager', 'activated', 'licenses', 'assets', 'accessories', 'consumables', 'groups', 'location') - ->make(); + $data = array('total'=>$userCount, 'rows'=>$rows); + return $data; } /** From 103c61d93647cf33687a0f9ae79c344ea5d512df Mon Sep 17 00:00:00 2001 From: snipe <snipe@snipe.net> Date: Tue, 20 Oct 2015 19:51:46 -0700 Subject: [PATCH 052/120] Updated users view with bootstrap tables --- app/views/backend/users/index.blade.php | 134 +++++++++++++----------- 1 file changed, 75 insertions(+), 59 deletions(-) diff --git a/app/views/backend/users/index.blade.php b/app/views/backend/users/index.blade.php index 1ac7081bee..d6f7e7963e 100755 --- a/app/views/backend/users/index.blade.php +++ b/app/views/backend/users/index.blade.php @@ -34,69 +34,84 @@ </div> <div class="row"> -{{ Form::open([ - 'method' => 'POST', - 'route' => ['users/bulkedit'], - 'class' => 'form-horizontal' ]) }} + {{ Form::open([ + 'method' => 'POST', + 'route' => ['users/bulkedit'], + 'class' => 'form-horizontal' ]) }} + <table name="assets" id="table" data-url="{{route('api.users.list') }}"> + <thead> + <tr> + <th data-class="hidden-xs" data-switchable="false" data-searchable="false" data-sortable="false" data-field="checkbox"><div class="text-center"><input type="checkbox" id="checkAll" style="padding-left: 0px;"></div></th> + <th data-sortable="true" data-field="name">{{ Lang::get('admin/users/table.name') }}</th> + <th data-sortable="true" data-field="email"><i class="fa fa-envelope fa-lg"></i></th> + <th data-sortable="true" data-field="username">{{ Lang::get('admin/users/table.username') }}</th> + <th data-sortable="true" data-field="manager">{{ Lang::get('admin/users/table.manager') }}</th> + <th data-sortable="true" data-field="location">{{ Lang::get('admin/users/table.location') }}</th> + <th data-sortable="true" data-field="assets"><i class="fa fa-barcode fa-lg"></i></th> + <th data-sortable="true" data-field="licenses"><i class="fa fa-certificate fa-lg"></i></th> + <th data-sortable="true" data-field="accessories"><i class="fa fa-keyboard-o fa-lg"></i></th> + <th data-sortable="true" data-field="consumables"><i class="fa fa-tint fa-lg"></i></th> + <th data-sortable="true" data-field="groups">{{ Lang::get('general.groups') }}</th> + <th data-sortable="true" data-field="notes">{{ Lang::get('general.notes') }}</th> + <th data-switchable="false" data-searchable="false" data-sortable="false" data-field="actions" >{{ Lang::get('table.actions') }}</th> + </tr> + </thead> + <tfoot> + <tr> + <td colspan="12"> + <select name="bulk_actions"> + <option value="delete">Bulk Delete</option> + </select> + <button class="btn btn-default" id="bulkEdit" disabled>Go</button> + </td> + </tr> + </tfoot> + </table> - {{ Datatable::table() - ->addColumn('<div class="text-center"><input type="checkbox" id="checkAll" style="padding-left: 0px;"></div>', - Lang::get('admin/users/table.name'), - '<i class="fa fa-envelope fa-lg"></i>', - Lang::get('admin/users/table.username'), - Lang::get('admin/users/table.manager'), - Lang::get('admin/users/table.location'), - '<i class="fa fa-barcode fa-lg"></i>', - '<i class="fa fa-certificate fa-lg"></i>', - '<i class="fa fa-keyboard-o fa-lg"></i>', - '<i class="fa fa-tint fa-lg"></i>', - Lang::get('general.groups'), - Lang::get('table.actions')) - ->setOptions( - array( - 'language' => array( - 'search' => Lang::get('general.search'), - 'lengthMenu' => Lang::get('general.page_menu'), - 'loadingRecords' => Lang::get('general.loading'), - 'zeroRecords' => Lang::get('general.no_results'), - 'info' => Lang::get('general.pagination_info'), - 'processing' => '<i class="fa fa-spinner fa-spin"></i> '.Lang::get('general.processing'), - 'paginate'=> array( - 'first'=>Lang::get('general.first'), - 'previous'=>Lang::get('general.previous'), - 'next'=>Lang::get('general.next'), - 'last'=>Lang::get('general.last'), - ), - ), - 'sAjaxSource'=> route('api.users.list', Input::get('status')), - 'dom' =>'CT<"clear">lfrtip', - 'colVis'=> - array( - 'showAll'=>'Show All', - 'restore'=>'Restore', - 'exclude'=>array(0,10), - 'activate'=>'mouseover' - ), - 'columnDefs'=> - array( - array( - 'visible'=>false, - 'targets'=>array() - ), - array( - 'orderable'=>false, - 'targets'=>array(0,10) - ) - ), - 'order'=>array(array(1,'asc')), - ) - ) - ->render('backend/users/datatable') }} - - {{ Form::close() }} + {{ Form::close() }} </div> </div> +@section('moar_scripts') +<script src="{{ asset('assets/js/bootstrap-table.js') }}"></script> +<script src="{{ asset('assets/js/extensions/mobile/bootstrap-table-mobile.js') }}"></script> +<script src="{{ asset('assets/js/extensions/export/bootstrap-table-export.js?v=1') }}"></script> +<script src="{{ asset('assets/js/extensions/cookie/bootstrap-table-cookie.js?v=1') }}"></script> +<script src="//rawgit.com/kayalshri/tableExport.jquery.plugin/master/tableExport.js?v=1') }}"></script> +<script src="//rawgit.com/kayalshri/tableExport.jquery.plugin/master/jquery.base64.js?v=1') }}"></script> +<script type="text/javascript"> + $('#table').bootstrapTable({ + classes: 'table table-responsive table-no-bordered', + undefinedText: '', + iconsPrefix: 'fa', + showRefresh: true, + search: true, + pageSize: {{{ Setting::getSettings()->per_page }}}, + pagination: true, + sidePagination: 'server', + sortable: true, + cookie: true, + mobileResponsive: true, + columnsHidden: ['name'], + showExport: true, + exportLabel: 'Export', + showColumns: true, + maintainSelected: true, + paginationFirstText: "@lang('general.first')", + paginationLastText: "@lang('general.last')", + paginationPreText: "@lang('general.previous')", + paginationNextText: "@lang('general.next')", + pageList: ['10','25','50','100','150','200'], + icons: { + paginationSwitchDown: 'fa-caret-square-o-down', + paginationSwitchUp: 'fa-caret-square-o-up', + columns: 'fa-columns', + refresh: 'fa-refresh' + }, + + }); +</script> + <script> @@ -125,5 +140,6 @@ </script> +@stop @stop From 2171e668febc69549494825c19da8bf73beb8c74 Mon Sep 17 00:00:00 2001 From: snipe <snipe@snipe.net> Date: Tue, 20 Oct 2015 19:51:52 -0700 Subject: [PATCH 053/120] Bumped version --- app/config/version.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/config/version.php b/app/config/version.php index 246801623e..89b3951ad0 100644 --- a/app/config/version.php +++ b/app/config/version.php @@ -1,5 +1,5 @@ <?php return array ( - 'app_version' => 'v2.0-230', - 'hash_version' => 'v2.0-230-g9264e7b', + 'app_version' => 'v2.0-234', + 'hash_version' => 'v2.0-234-gf4d8826', ); \ No newline at end of file From 93bd9120cc3654354e11895eb1ff5d3f1ff5d64a Mon Sep 17 00:00:00 2001 From: snipe <snipe@snipe.net> Date: Tue, 20 Oct 2015 19:57:31 -0700 Subject: [PATCH 054/120] Updated orderby for #1266 --- app/config/version.php | 4 ++-- app/controllers/admin/UsersController.php | 10 ++++++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/app/config/version.php b/app/config/version.php index 89b3951ad0..1df066c01e 100644 --- a/app/config/version.php +++ b/app/config/version.php @@ -1,5 +1,5 @@ <?php return array ( - 'app_version' => 'v2.0-234', - 'hash_version' => 'v2.0-234-gf4d8826', + 'app_version' => 'v2.0-235', + 'hash_version' => 'v2.0-235-g103c61d', ); \ No newline at end of file diff --git a/app/controllers/admin/UsersController.php b/app/controllers/admin/UsersController.php index 7b2226b794..c1ee48a95f 100755 --- a/app/controllers/admin/UsersController.php +++ b/app/controllers/admin/UsersController.php @@ -839,6 +839,12 @@ class UsersController extends AdminController { $limit = 50; } + if (Input::get('sort')=='name') { + $sort = 'first_name'; + } else { + $sort = e(Input::get('sort')); + } + $users = User::with('assets', 'accessories', 'consumables', 'licenses', 'manager', 'sentryThrottle', 'groups', 'userloc'); @@ -848,11 +854,11 @@ class UsersController extends AdminController { $allowed_columns = ['last_name','first_name','email','username','manager','location','assets','accessories', 'consumables','licenses','groups']; $order = Input::get('order') === 'asc' ? 'asc' : 'desc'; - $sort = in_array(Input::get('sort'), $allowed_columns) ? Input::get('sort') : 'last_name'; + $sort = in_array($sort, $allowed_columns) ? $sort : 'first_name'; $userCount = $users->count(); - $users = $users->skip($offset)->take($limit)->get(); + $users = $users->skip($offset)->take($limit)->orderBy($sort, $order)->get(); $rows = array(); From b39e617e964488712fc684da6a4d92986054e68b Mon Sep 17 00:00:00 2001 From: snipe <snipe@snipe.net> Date: Tue, 20 Oct 2015 20:02:18 -0700 Subject: [PATCH 055/120] Added inelegant nobr for actions column for #1266 --- app/config/version.php | 4 ++-- app/controllers/admin/UsersController.php | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/app/config/version.php b/app/config/version.php index 1df066c01e..27dacf849e 100644 --- a/app/config/version.php +++ b/app/config/version.php @@ -1,5 +1,5 @@ <?php return array ( - 'app_version' => 'v2.0-235', - 'hash_version' => 'v2.0-235-g103c61d', + 'app_version' => 'v2.0-236', + 'hash_version' => 'v2.0-236-g2171e66', ); \ No newline at end of file diff --git a/app/controllers/admin/UsersController.php b/app/controllers/admin/UsersController.php index c1ee48a95f..74a40d47d0 100755 --- a/app/controllers/admin/UsersController.php +++ b/app/controllers/admin/UsersController.php @@ -868,7 +868,7 @@ class UsersController extends AdminController { $group_names = ''; $inout = ''; - $actions = ''; + $actions = '<nobr>'; foreach ($user->groups as $group) { $group_names .= '<a href="' . Config::get('app.url') . '/admin/groups/' . $group->id . '/edit" class="label label-default">' . $group->name . '</a> '; @@ -892,6 +892,7 @@ class UsersController extends AdminController { $actions .= ' <span class="btn delete-asset btn-danger btn-sm disabled"><i class="fa fa-trash icon-white"></i></span>'; } } + $actions .= '</nobr>'; $rows[] = array( 'checkbox' =>'<div class="text-center"><input type="checkbox" name="edit_user['.$user->id.']" class="one_required"></div>', From 4beb3b024d6bb5e5cfa471c5a76d22e862be385b Mon Sep 17 00:00:00 2001 From: madd15 <joshdeakin@adam.com.au> Date: Wed, 21 Oct 2015 13:49:30 +1030 Subject: [PATCH 056/120] Change Categories Datatables - #1266 Convert categories index to new table. EULA is still not working correctly --- .../admin/CategoriesController.php | 54 +++++++++++-------- 1 file changed, 32 insertions(+), 22 deletions(-) diff --git a/app/controllers/admin/CategoriesController.php b/app/controllers/admin/CategoriesController.php index 66e948b70b..5514879126 100755 --- a/app/controllers/admin/CategoriesController.php +++ b/app/controllers/admin/CategoriesController.php @@ -218,30 +218,40 @@ class CategoriesController extends AdminController public function getDatatable() { // Grab all the categories - $categories = Category::orderBy('created_at', 'DESC')->get(); + $categories = Category::select(array('id', 'name', 'category_type', 'require_acceptance'))->whereNull('deleted_at'); - $actions = new \Chumper\Datatable\Columns\FunctionColumn('actions', function($categories) { - return '<a href="'.route('update/category', $categories->id).'" class="btn btn-warning btn-sm" style="margin-right:5px;"><i class="fa fa-pencil icon-white"></i></a><a data-html="false" class="btn delete-asset btn-danger btn-sm" data-toggle="modal" href="'.route('delete/category', $categories->id).'" data-content="'.Lang::get('admin/categories/message.delete.confirm').'" data-title="'.Lang::get('general.delete').' '.htmlspecialchars($categories->name).'?" onClick="return false;"><i class="fa fa-trash icon-white"></i></a>'; - }); + if (Input::has('search')) { + $categories = $categories->TextSearch(Input::get('search')); + } - return Datatable::collection($categories) - ->showColumns('name') - ->addColumn('category_type', function($categories) { - return ucwords($categories->category_type); - }) - ->addColumn('count', function($categories) { - return ($categories->category_type=='asset') ? link_to('/admin/settings/categories/'.$categories->id.'/view', $categories->assetscount()) : $categories->accessoriescount(); - }) - ->addColumn('acceptance', function($categories) { - return ($categories->require_acceptance=='1') ? '<i class="fa fa-check" style="margin-right:50%;margin-left:50%;"></i>' : ''; - }) - ->addColumn('eula', function($categories) { - return ($categories->getEula()) ? '<i class="fa fa-check" style="margin-right:50%;margin-left:50%;"></i></a>' : ''; - }) - ->addColumn($actions) - ->searchColumns('name','category_type','count','acceptance','eula','actions') - ->orderColumns('name','category_type','count','acceptance','eula','actions') - ->make(); + $allowed_columns = ['name','category_type']; + $order = Input::get('order') === 'asc' ? 'asc' : 'desc'; + $sort = in_array(Input::get('sort'), $allowed_columns) ? Input::get('sort') : 'created_at'; + + $categories = $categories->orderBy($sort, $order); + + $catCount = $categories->count(); + $categories = $categories->skip(Input::get('offset'))->take(Input::get('limit'))->get(); + + $rows = array(); + + foreach ($categories as $category) { + $actions = '<a href="'.route('update/category', $category->id).'" class="btn btn-warning btn-sm" style="margin-right:5px;"><i class="fa fa-pencil icon-white"></i></a><a data-html="false" class="btn delete-asset btn-danger btn-sm" data-toggle="modal" href="'.route('delete/category', $category->id).'" data-content="'.Lang::get('admin/categories/message.delete.confirm').'" data-title="'.Lang::get('general.delete').' '.htmlspecialchars($category->name).'?" onClick="return false;"><i class="fa fa-trash icon-white"></i></a>'; + + $rows[] = array( + 'name' => $category->name, + 'category_type' => ucwords($category->category_type), + 'count' => ($category->category_type=='asset') ? link_to('/admin/settings/categories/'.$category->id.'/view', $category->assetscount()) : $category->accessoriescount(), + 'acceptance' => ($category->require_acceptance=='1') ? '<i class="fa fa-check"></i>' : '', + //EULA is still not working correctly + 'eula' => ($category->getEula()) ? '<i class="fa fa-check"></i>' : '', + 'actions' => $actions + ); + } + + $data = array('total' => $catCount, 'rows' => $rows); + + return $data; } public function getDataView($categoryID) { From ca625418fed084111ad2feda5febaadd5d5bc7cc Mon Sep 17 00:00:00 2001 From: madd15 <joshdeakin@adam.com.au> Date: Wed, 21 Oct 2015 13:54:05 +1030 Subject: [PATCH 057/120] Change Categories Datatables - #1266 --- app/views/backend/categories/index.blade.php | 83 ++++++++++++-------- 1 file changed, 51 insertions(+), 32 deletions(-) diff --git a/app/views/backend/categories/index.blade.php b/app/views/backend/categories/index.blade.php index 8f2a7ccd6b..c4c44d748d 100755 --- a/app/views/backend/categories/index.blade.php +++ b/app/views/backend/categories/index.blade.php @@ -19,38 +19,19 @@ <div class="user-profile"> <div class="row profile"> <div class="col-md-9 bio"> - {{ Datatable::table() - ->addColumn(Lang::get('admin/categories/table.title'), - Lang::get('general.type'), - Lang::get('general.assets'), - Lang::get('admin/categories/table.require_acceptance'), - Lang::get('admin/categories/table.eula_text'), - Lang::get('table.actions')) - ->setOptions( - array( - 'language' => array( - 'search' => Lang::get('general.search'), - 'lengthMenu' => Lang::get('general.page_menu'), - 'loadingRecords' => Lang::get('general.loading'), - 'zeroRecords' => Lang::get('general.no_results'), - 'info' => Lang::get('general.pagination_info'), - 'processing' => Lang::get('general.processing'), - 'paginate'=> array( - 'first'=>Lang::get('general.first'), - 'previous'=>Lang::get('general.previous'), - 'next'=>Lang::get('general.next'), - 'last'=>Lang::get('general.last'), - ), - ), - 'sAjaxSource'=> route('api.categories.list'), - 'dom' =>'CT<"clear">lfrtip', - 'colVis'=> array('showAll'=>'Show All','restore'=>'Restore','exclude'=>array(5),'activate'=>'mouseover'), - 'columnDefs'=> array(array('bSortable'=>false,'targets'=>array(5))), - 'order'=>array(array(0,'asc')), - ) - ) - ->render() }} - </div> + <table name="models" id="table" data-url="{{route('api.categories.list')}}"> + <thead> + <tr> + <th data-sortable="true" data-field="name">{{Lang::get('admin/categories/table.title')}}</th> + <th data-sortable="true" data-field="category_type">{{Lang::get('general.type')}}</th> + <th data-searchable="false" data-sortable="false" data-field="count">{{Lang::get('general.assets')}}</th> + <th data-searchable="false" data-sortable="false" data-field="acceptance">{{Lang::get('admin/categories/table.require_acceptance')}}</th> + <th data-searchable="false" data-sortable="false" data-field="eula">{{Lang::get('admin/categories/table.eula_text')}}</th> + <th data-switchable="false" data-searchable="false" data-sortable="false" data-field="actions">{{ Lang::get('table.actions') }}</th> + </tr> + </thead> + </table> + </div> <!-- side address column --> @@ -61,4 +42,42 @@ </div> </div> </div> + +@section('moar_scripts') +<script src="{{ asset('assets/js/bootstrap-table.js') }}"></script> +<script src="{{ asset('assets/js/extensions/mobile/bootstrap-table-mobile.js') }}"></script> +<script src="{{ asset('assets/js/extensions/export/bootstrap-table-export.js?v=1') }}"></script> +<script src="{{ asset('assets/js/extensions/cookie/bootstrap-table-cookie.js?v=1') }}"></script> +<script src="//rawgit.com/kayalshri/tableExport.jquery.plugin/master/tableExport.js?v=1') }}"></script> +<script src="//rawgit.com/kayalshri/tableExport.jquery.plugin/master/jquery.base64.js?v=1') }}"></script> +<script type="text/javascript"> + $('#table').bootstrapTable({ + classes: 'table table-hover table-no-bordered', + undefinedText: '', + iconsPrefix: 'fa', + showRefresh: true, + search: true, + pageSize: {{{ Setting::getSettings()->per_page }}}, + pagination: true, + sidePagination: 'server', + sortable: true, + mobileResponsive: true, + showExport: true, + showColumns: true, + maintainSelected: true, + paginationFirstText: "@lang('general.first')", + paginationLastText: "@lang('general.last')", + paginationPreText: "@lang('general.previous')", + paginationNextText: "@lang('general.next')", + pageList: ['10','25','50','100','150','200'], + icons: { + paginationSwitchDown: 'fa-caret-square-o-down', + paginationSwitchUp: 'fa-caret-square-o-up', + columns: 'fa-columns', + refresh: 'fa-refresh' + }, + }); +</script> +@stop + @stop From 84c12e5f01e0894156e24de4347478989e6806a5 Mon Sep 17 00:00:00 2001 From: snipe <snipe@snipe.net> Date: Tue, 20 Oct 2015 20:45:52 -0700 Subject: [PATCH 058/120] Revert "Change Categories Datatables - #1266" This reverts commit 4beb3b024d6bb5e5cfa471c5a76d22e862be385b. --- .../admin/CategoriesController.php | 54 ++++++++----------- 1 file changed, 22 insertions(+), 32 deletions(-) diff --git a/app/controllers/admin/CategoriesController.php b/app/controllers/admin/CategoriesController.php index 5514879126..66e948b70b 100755 --- a/app/controllers/admin/CategoriesController.php +++ b/app/controllers/admin/CategoriesController.php @@ -218,40 +218,30 @@ class CategoriesController extends AdminController public function getDatatable() { // Grab all the categories - $categories = Category::select(array('id', 'name', 'category_type', 'require_acceptance'))->whereNull('deleted_at'); + $categories = Category::orderBy('created_at', 'DESC')->get(); - if (Input::has('search')) { - $categories = $categories->TextSearch(Input::get('search')); - } + $actions = new \Chumper\Datatable\Columns\FunctionColumn('actions', function($categories) { + return '<a href="'.route('update/category', $categories->id).'" class="btn btn-warning btn-sm" style="margin-right:5px;"><i class="fa fa-pencil icon-white"></i></a><a data-html="false" class="btn delete-asset btn-danger btn-sm" data-toggle="modal" href="'.route('delete/category', $categories->id).'" data-content="'.Lang::get('admin/categories/message.delete.confirm').'" data-title="'.Lang::get('general.delete').' '.htmlspecialchars($categories->name).'?" onClick="return false;"><i class="fa fa-trash icon-white"></i></a>'; + }); - $allowed_columns = ['name','category_type']; - $order = Input::get('order') === 'asc' ? 'asc' : 'desc'; - $sort = in_array(Input::get('sort'), $allowed_columns) ? Input::get('sort') : 'created_at'; - - $categories = $categories->orderBy($sort, $order); - - $catCount = $categories->count(); - $categories = $categories->skip(Input::get('offset'))->take(Input::get('limit'))->get(); - - $rows = array(); - - foreach ($categories as $category) { - $actions = '<a href="'.route('update/category', $category->id).'" class="btn btn-warning btn-sm" style="margin-right:5px;"><i class="fa fa-pencil icon-white"></i></a><a data-html="false" class="btn delete-asset btn-danger btn-sm" data-toggle="modal" href="'.route('delete/category', $category->id).'" data-content="'.Lang::get('admin/categories/message.delete.confirm').'" data-title="'.Lang::get('general.delete').' '.htmlspecialchars($category->name).'?" onClick="return false;"><i class="fa fa-trash icon-white"></i></a>'; - - $rows[] = array( - 'name' => $category->name, - 'category_type' => ucwords($category->category_type), - 'count' => ($category->category_type=='asset') ? link_to('/admin/settings/categories/'.$category->id.'/view', $category->assetscount()) : $category->accessoriescount(), - 'acceptance' => ($category->require_acceptance=='1') ? '<i class="fa fa-check"></i>' : '', - //EULA is still not working correctly - 'eula' => ($category->getEula()) ? '<i class="fa fa-check"></i>' : '', - 'actions' => $actions - ); - } - - $data = array('total' => $catCount, 'rows' => $rows); - - return $data; + return Datatable::collection($categories) + ->showColumns('name') + ->addColumn('category_type', function($categories) { + return ucwords($categories->category_type); + }) + ->addColumn('count', function($categories) { + return ($categories->category_type=='asset') ? link_to('/admin/settings/categories/'.$categories->id.'/view', $categories->assetscount()) : $categories->accessoriescount(); + }) + ->addColumn('acceptance', function($categories) { + return ($categories->require_acceptance=='1') ? '<i class="fa fa-check" style="margin-right:50%;margin-left:50%;"></i>' : ''; + }) + ->addColumn('eula', function($categories) { + return ($categories->getEula()) ? '<i class="fa fa-check" style="margin-right:50%;margin-left:50%;"></i></a>' : ''; + }) + ->addColumn($actions) + ->searchColumns('name','category_type','count','acceptance','eula','actions') + ->orderColumns('name','category_type','count','acceptance','eula','actions') + ->make(); } public function getDataView($categoryID) { From a90f7218de89051b20bf94f135476f25b2d98212 Mon Sep 17 00:00:00 2001 From: snipe <snipe@snipe.net> Date: Tue, 20 Oct 2015 20:45:52 -0700 Subject: [PATCH 059/120] Revert "Change Categories Datatables - #1266" This reverts commit ca625418fed084111ad2feda5febaadd5d5bc7cc. --- app/views/backend/categories/index.blade.php | 83 ++++++++------------ 1 file changed, 32 insertions(+), 51 deletions(-) diff --git a/app/views/backend/categories/index.blade.php b/app/views/backend/categories/index.blade.php index c4c44d748d..8f2a7ccd6b 100755 --- a/app/views/backend/categories/index.blade.php +++ b/app/views/backend/categories/index.blade.php @@ -19,19 +19,38 @@ <div class="user-profile"> <div class="row profile"> <div class="col-md-9 bio"> - <table name="models" id="table" data-url="{{route('api.categories.list')}}"> - <thead> - <tr> - <th data-sortable="true" data-field="name">{{Lang::get('admin/categories/table.title')}}</th> - <th data-sortable="true" data-field="category_type">{{Lang::get('general.type')}}</th> - <th data-searchable="false" data-sortable="false" data-field="count">{{Lang::get('general.assets')}}</th> - <th data-searchable="false" data-sortable="false" data-field="acceptance">{{Lang::get('admin/categories/table.require_acceptance')}}</th> - <th data-searchable="false" data-sortable="false" data-field="eula">{{Lang::get('admin/categories/table.eula_text')}}</th> - <th data-switchable="false" data-searchable="false" data-sortable="false" data-field="actions">{{ Lang::get('table.actions') }}</th> - </tr> - </thead> - </table> - </div> + {{ Datatable::table() + ->addColumn(Lang::get('admin/categories/table.title'), + Lang::get('general.type'), + Lang::get('general.assets'), + Lang::get('admin/categories/table.require_acceptance'), + Lang::get('admin/categories/table.eula_text'), + Lang::get('table.actions')) + ->setOptions( + array( + 'language' => array( + 'search' => Lang::get('general.search'), + 'lengthMenu' => Lang::get('general.page_menu'), + 'loadingRecords' => Lang::get('general.loading'), + 'zeroRecords' => Lang::get('general.no_results'), + 'info' => Lang::get('general.pagination_info'), + 'processing' => Lang::get('general.processing'), + 'paginate'=> array( + 'first'=>Lang::get('general.first'), + 'previous'=>Lang::get('general.previous'), + 'next'=>Lang::get('general.next'), + 'last'=>Lang::get('general.last'), + ), + ), + 'sAjaxSource'=> route('api.categories.list'), + 'dom' =>'CT<"clear">lfrtip', + 'colVis'=> array('showAll'=>'Show All','restore'=>'Restore','exclude'=>array(5),'activate'=>'mouseover'), + 'columnDefs'=> array(array('bSortable'=>false,'targets'=>array(5))), + 'order'=>array(array(0,'asc')), + ) + ) + ->render() }} + </div> <!-- side address column --> @@ -42,42 +61,4 @@ </div> </div> </div> - -@section('moar_scripts') -<script src="{{ asset('assets/js/bootstrap-table.js') }}"></script> -<script src="{{ asset('assets/js/extensions/mobile/bootstrap-table-mobile.js') }}"></script> -<script src="{{ asset('assets/js/extensions/export/bootstrap-table-export.js?v=1') }}"></script> -<script src="{{ asset('assets/js/extensions/cookie/bootstrap-table-cookie.js?v=1') }}"></script> -<script src="//rawgit.com/kayalshri/tableExport.jquery.plugin/master/tableExport.js?v=1') }}"></script> -<script src="//rawgit.com/kayalshri/tableExport.jquery.plugin/master/jquery.base64.js?v=1') }}"></script> -<script type="text/javascript"> - $('#table').bootstrapTable({ - classes: 'table table-hover table-no-bordered', - undefinedText: '', - iconsPrefix: 'fa', - showRefresh: true, - search: true, - pageSize: {{{ Setting::getSettings()->per_page }}}, - pagination: true, - sidePagination: 'server', - sortable: true, - mobileResponsive: true, - showExport: true, - showColumns: true, - maintainSelected: true, - paginationFirstText: "@lang('general.first')", - paginationLastText: "@lang('general.last')", - paginationPreText: "@lang('general.previous')", - paginationNextText: "@lang('general.next')", - pageList: ['10','25','50','100','150','200'], - icons: { - paginationSwitchDown: 'fa-caret-square-o-down', - paginationSwitchUp: 'fa-caret-square-o-up', - columns: 'fa-columns', - refresh: 'fa-refresh' - }, - }); -</script> -@stop - @stop From 46a02b25daa2831f02f6ff75cf57ca14dd8da8c1 Mon Sep 17 00:00:00 2001 From: madd15 <joshdeakin@adam.com.au> Date: Wed, 21 Oct 2015 14:24:25 +1030 Subject: [PATCH 060/120] Update getDatatable and getDataView --- app/controllers/admin/ModelsController.php | 110 ++++++++++----------- 1 file changed, 55 insertions(+), 55 deletions(-) diff --git a/app/controllers/admin/ModelsController.php b/app/controllers/admin/ModelsController.php index efc4cc6534..3cc5e3e17d 100755 --- a/app/controllers/admin/ModelsController.php +++ b/app/controllers/admin/ModelsController.php @@ -368,40 +368,44 @@ class ModelsController extends AdminController { $models = Model::orderBy('created_at', 'DESC')->with('category','assets','depreciation'); ($status != 'Deleted') ?: $models->withTrashed()->Deleted();; - $models = $models->get(); - $actions = new \Chumper\Datatable\Columns\FunctionColumn('actions', function($models) { - if($models->deleted_at=='') { - return '<a href="'.route('update/model', $models->id).'" class="btn btn-warning btn-sm" style="margin-right:5px;"><i class="fa fa-pencil icon-white"></i></a><a data-html="false" class="btn delete-asset btn-danger btn-sm" data-toggle="modal" href="'.route('delete/model', $models->id).'" data-content="'.Lang::get('admin/models/message.delete.confirm').'" data-title="'.Lang::get('general.delete').' '.htmlspecialchars($models->name).'?" onClick="return false;"><i class="fa fa-trash icon-white"></i></a>'; + if (Input::has('search')) { + $models = $models->TextSearch(Input::get('search')); + } + + $allowed_columns = ['name']; + $order = Input::get('order') === 'asc' ? 'asc' : 'desc'; + $sort = in_array(Input::get('sort'), $allowed_columns) ? Input::get('sort') : 'created_at'; + + $models = $models->orderBy($sort, $order); + + $modelCount = $models->count(); + $models = $models->skip(Input::get('offset'))->take(Input::get('limit'))->get(); + + $rows = array(); + + foreach ($models as $model) { + if ($model->deleted_at == '') { + $actions = '<a href="'.route('update/model', $model->id).'" class="btn btn-warning btn-sm" style="margin-right:5px;"><i class="fa fa-pencil icon-white"></i></a><a data-html="false" class="btn delete-asset btn-danger btn-sm" data-toggle="modal" href="'.route('delete/model', $model->id).'" data-content="'.Lang::get('admin/models/message.delete.confirm').'" data-title="'.Lang::get('general.delete').' '.htmlspecialchars($model->name).'?" onClick="return false;"><i class="fa fa-trash icon-white"></i></a>'; } else { - return '<a href="'.route('restore/model', $models->id).'" class="btn btn-warning btn-sm"><i class="fa fa-recycle icon-white"></i></a>'; + $actions = '<a href="'.route('restore/model', $model->id).'" class="btn btn-warning btn-sm"><i class="fa fa-recycle icon-white"></i></a>'; } - }); - return Datatable::collection($models) - ->addColumn('manufacturer', function($models) { - return $models->manufacturer->name; - }) - ->addColumn('name', function ($models) { - return link_to('/hardware/models/'.$models->id.'/view', $models->name); - }) - ->showColumns('modelno') - ->addColumn('asset_count', function($models) { - return $models->assets->count(); - }) - ->addColumn('depreciation', function($models) { - return (($models->depreciation)&&($models->depreciation->id > 0)) ? $models->depreciation->name.' ('.$models->depreciation->months.')' : Lang::get('general.no_depreciation'); - }) - ->addColumn('category', function($models) { - return ($models->category) ? $models->category->name : ''; - }) - ->addColumn('eol', function($models) { - return ($models->eol) ? $models->eol.' '.Lang::get('general.months') : ''; - }) - ->addColumn($actions) - ->searchColumns('name','modelno','asset_count','depreciation','category','eol','actions') - ->orderColumns('name','modelno','asset_count','depreciation','category','eol','actions') - ->make(); + $rows[] = array( + 'manufacturer' => $model->manufacturer->name, + 'name' => link_to('/hardware/models/'.$model->id.'/view', $model->name), + 'modelnumber' => $model->modelno, + 'numassets' => $model->assets->count(), + 'depreciation' => (($model->depreciation)&&($model->depreciation->id > 0)) ? $model->depreciation->name.' ('.$model->depreciation->months.')' : Lang::get('general.no_depreciation'), + 'category' => ($model->category) ? $model->category->name : '', + 'eol' => ($model->eol) ? $model->eol.' '.Lang::get('general.months') : '', + 'actions' => $actions + ); + } + + $data = array('total' => $modelCount, 'rows' => $rows); + + return $data; } @@ -410,33 +414,29 @@ class ModelsController extends AdminController $model = Model::withTrashed()->find($modelID); $modelassets = $model->assets; - $actions = new \Chumper\Datatable\Columns\FunctionColumn('actions', function ($modelassets) - { - if (($modelassets->assigned_to !='') && ($modelassets->assigned_to > 0)) { - return '<a href="'.route('checkin/hardware', $modelassets->id).'" class="btn btn-primary btn-sm">'.Lang::get('general.checkin').'</a>'; - } else { - return '<a href="'.route('checkout/hardware', $modelassets->id).'" class="btn btn-info btn-sm">'.Lang::get('general.checkout').'</a>'; - } - }); + $modelassetsCount = $modelassets->Count(); - return Datatable::collection($modelassets) - ->addColumn('name', function ($modelassets) { - return link_to('/hardware/'.$modelassets->id.'/view', $modelassets->showAssetName()); - // return $modelassets->name; - }) - ->addColumn('asset_tag', function ($modelassets) { - return link_to('/hardware/'.$modelassets->id.'/view', $modelassets->asset_tag); - }) - ->showColumns('serial') - ->addColumn('assigned_to', function ($modelassets) { - if ($modelassets->assigned_to) { - return link_to('/admin/users/'.$modelassets->assigned_to.'/view', $modelassets->assigneduser->fullName()); + $rows = array(); + + foreach ($modelassets as $asset) { + if (($asset->assigned_to !='') && ($asset->assigned_to > 0)) { + $actions = '<a href="'.route('checkin/hardware', $asset->id).'" class="btn btn-primary btn-sm">'.Lang::get('general.checkin').'</a>'; + } else { + $actions = '<a href="'.route('checkout/hardware', $asset->id).'" class="btn btn-info btn-sm">'.Lang::get('general.checkout').'</a>'; } - }) - ->addColumn($actions) - ->searchColumns('name','asset_tag','serial','assigned_to','actions') - ->orderColumns('name','asset_tag','serial','assigned_to','actions') - ->make(); + + $rows[] = array( + 'name' => link_to('/hardware/'.$asset->id.'/view', $asset->showAssetName()), + 'asset_tag' => link_to('hardware/'.$asset->id.'/view', $asset->asset_tag), + 'serial' => $asset->serial, + 'assigned_to' => ($asset->assigned_to) ? link_to('/admin/users/'.$asset->assigned_to.'/view', $asset->assigneduser->fullName()) : '', + 'actions' => $actions + ); + } + + $data = array('total' => $modelassetsCount, 'rows' => $rows); + + return $data; } } From de0e1627c708dc883df68552f815af724bf5ae27 Mon Sep 17 00:00:00 2001 From: madd15 <joshdeakin@adam.com.au> Date: Wed, 21 Oct 2015 14:28:20 +1030 Subject: [PATCH 061/120] Change Models Datatables - #1266 --- app/views/backend/models/index.blade.php | 84 ++++++++++++++---------- 1 file changed, 51 insertions(+), 33 deletions(-) diff --git a/app/views/backend/models/index.blade.php b/app/views/backend/models/index.blade.php index 9695b6c0da..7ead7cb695 100755 --- a/app/views/backend/models/index.blade.php +++ b/app/views/backend/models/index.blade.php @@ -22,38 +22,56 @@ </div> <div class="row form-wrapper"> - {{ Datatable::table() - ->addColumn(Lang::get('general.manufacturer'), - Lang::get('admin/models/table.title'), - Lang::get('admin/models/table.modelnumber'), - Lang::get('admin/models/table.numassets'), - Lang::get('general.depreciation'), - Lang::get('general.category'), - Lang::get('general.eol'), - Lang::get('table.actions')) - ->setOptions( - array( - 'language' => array( - 'search' => Lang::get('general.search'), - 'lengthMenu' => Lang::get('general.page_menu'), - 'loadingRecords' => Lang::get('general.loading'), - 'zeroRecords' => Lang::get('general.no_results'), - 'info' => Lang::get('general.pagination_info'), - 'processing' => Lang::get('general.processing'), - 'paginate'=> array( - 'first'=>Lang::get('general.first'), - 'previous'=>Lang::get('general.previous'), - 'next'=>Lang::get('general.next'), - 'last'=>Lang::get('general.last'), - ), - ), - 'sAjaxSource'=> route('api.models.list', Input::get('status')), - 'dom' =>'CT<"clear">lfrtip', - 'colVis'=> array('showAll'=>'Show All','restore'=>'Restore','exclude'=>array(6),'activate'=>'mouseover'), - 'columnDefs'=> array(array('bSortable'=>false,'targets'=>array(6))), - 'order'=>array(array(0,'asc')), - ) - ) - ->render() }} + <table name="models" id="table" data-url="{{route('api.models.list', Input::get('status'))}}"> + <thead> + <tr> + <th data-sortable="true" data-field="manufacturer">{{Lang::get('general.manufacturer')}}</th> + <th data-sortable="true" data-field="name">{{Lang::get('admin/models/table.title')}}</th> + <th data-sortable="true" data-field="modelnumber">{{Lang::get('admin/models/table.modelnumber')}}</th> + <th data-sortable="true" data-field="numassets">{{Lang::get('admin/models/table.numassets')}}</th> + <th data-sortable="true" data-field="depreciation">{{Lang::get('general.depreciation')}}</th> + <th data-sortable="true" data-field="category">{{Lang::get('general.category')}}</th> + <th data-sortable="true" data-field="eol">{{Lang::get('general.eol')}}</th> + <th data-switchable="false" data-searchable="false" data-sortable="false" data-field="actions">{{ Lang::get('table.actions') }}</th> + </tr> + </thead> + </table> + +@section('moar_scripts') +<script src="{{ asset('assets/js/bootstrap-table.js') }}"></script> +<script src="{{ asset('assets/js/extensions/mobile/bootstrap-table-mobile.js') }}"></script> +<script src="{{ asset('assets/js/extensions/export/bootstrap-table-export.js?v=1') }}"></script> +<script src="{{ asset('assets/js/extensions/cookie/bootstrap-table-cookie.js?v=1') }}"></script> +<script src="//rawgit.com/kayalshri/tableExport.jquery.plugin/master/tableExport.js?v=1') }}"></script> +<script src="//rawgit.com/kayalshri/tableExport.jquery.plugin/master/jquery.base64.js?v=1') }}"></script> +<script type="text/javascript"> + $('#table').bootstrapTable({ + classes: 'table table-hover table-no-bordered', + undefinedText: '', + iconsPrefix: 'fa', + showRefresh: true, + search: true, + pageSize: {{{ Setting::getSettings()->per_page }}}, + pagination: true, + sidePagination: 'server', + sortable: true, + mobileResponsive: true, + showExport: true, + showColumns: true, + maintainSelected: true, + paginationFirstText: "@lang('general.first')", + paginationLastText: "@lang('general.last')", + paginationPreText: "@lang('general.previous')", + paginationNextText: "@lang('general.next')", + pageList: ['10','25','50','100','150','200'], + icons: { + paginationSwitchDown: 'fa-caret-square-o-down', + paginationSwitchUp: 'fa-caret-square-o-up', + columns: 'fa-columns', + refresh: 'fa-refresh' + }, + }); +</script> +@stop @stop From f96e4ebd4cfc034f5b9175bd961c460543b27e77 Mon Sep 17 00:00:00 2001 From: madd15 <joshdeakin@adam.com.au> Date: Wed, 21 Oct 2015 14:30:32 +1030 Subject: [PATCH 062/120] Add scopeTextSearch --- app/models/Model.php | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/app/models/Model.php b/app/models/Model.php index 55a4601c0f..c30a43316c 100755 --- a/app/models/Model.php +++ b/app/models/Model.php @@ -75,5 +75,23 @@ class Model extends Elegant return $query->whereIn( 'category_id', $categoryIdListing ); } + + /** + * Query builder scope to search on text + * + * @param Illuminate\Database\Query\Builder $query Query builder instance + * @param text $search Search term + * + * @return Illuminate\Database\Query\Builder Modified query builder + */ + public function scopeTextSearch($query, $search) + { + + return $query->where(function($query) use ($search) + { + $query->where('name', 'LIKE', '%'.$search.'%') + ->orWhere('modelno', 'LIKE', '%'.$search.'%'); + }); + } } From 07f1c5774e546011000c7cda8a585522704d81ae Mon Sep 17 00:00:00 2001 From: madd15 <joshdeakin@adam.com.au> Date: Wed, 21 Oct 2015 14:31:26 +1030 Subject: [PATCH 063/120] Add scopeTextSearch --- app/models/Category.php | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/app/models/Category.php b/app/models/Category.php index 77a59b5c69..6df3fcee5a 100755 --- a/app/models/Category.php +++ b/app/models/Category.php @@ -74,5 +74,23 @@ class Category extends Elegant return $query->where( 'require_acceptance', '=', true ); } + + /** + * Query builder scope to search on text + * + * @param Illuminate\Database\Query\Builder $query Query builder instance + * @param text $search Search term + * + * @return Illuminate\Database\Query\Builder Modified query builder + */ + public function scopeTextSearch($query, $search) + { + + return $query->where(function($query) use ($search) + { + $query->where('name', 'LIKE', '%'.$search.'%') + ->orWhere('category_type', 'LIKE', '%'.$search.'%'); + }); + } } From d61983efdf6c039187d7810c56718a1389acdeed Mon Sep 17 00:00:00 2001 From: madd15 <joshdeakin@adam.com.au> Date: Wed, 21 Oct 2015 14:35:51 +1030 Subject: [PATCH 064/120] Change to Bootstrap Table --- app/views/backend/models/view.blade.php | 32 ++++++++++--------------- 1 file changed, 13 insertions(+), 19 deletions(-) diff --git a/app/views/backend/models/view.blade.php b/app/views/backend/models/view.blade.php index 215914ba2b..a5bc39fa78 100755 --- a/app/views/backend/models/view.blade.php +++ b/app/views/backend/models/view.blade.php @@ -52,25 +52,18 @@ <!-- checked out models table --> @if (count($model->assets) > 0) - {{ Datatable::table() - ->addColumn(Lang::get('general.name'), - Lang::get('general.asset_tag'), - Lang::get('admin/hardware/table.serial'), - Lang::get('general.user'), - Lang::get('table.actions')) - ->setOptions( - array( - 'sAjaxSource'=>route('api.models.view', $model->id), - 'dom' =>'CT<"clear">lfrtip', - 'colVis'=> array('showAll'=>'Show All','restore'=>'Restore','exclude'=>array(4),'activate'=>'mouseover'), - 'columnDefs'=> array( - array('bSortable'=>false,'targets'=>array(4)), - array('width'=>'auto','targets'=>array(4)), - ), - 'order'=>array(array(0,'asc')), - ) - ) - ->render() }} + <table name="modelassets" id="table" data-url="{{route('api.models.view', $model->id)}}"> + <thead> + <tr> + + <th data-sortable="true" data-field="name">{{Lang::get('general.name')}}</th> + <th data-sortable="true" data-field="asset_tag">{{Lang::get('general.asset_tag')}}</th> + <th data-sortable="true" data-field="serial">{{Lang::get('admin/hardware/table.serial')}}</th> + <th data-sortable="true" data-field="assigned_to">{{Lang::get('general.user')}}</th> + <th data-switchable="false" data-searchable="false" data-sortable="false" data-field="actions">{{ Lang::get('table.actions') }}</th> + </tr> + </thead> + </table> @else <div class="col-md-9"> <div class="alert alert-info alert-block"> @@ -80,6 +73,7 @@ </div> @endif + </div> From c346dbaff697aad8d09cbdcbf836f0febfb29a33 Mon Sep 17 00:00:00 2001 From: snipe <snipe@snipe.net> Date: Tue, 20 Oct 2015 21:50:58 -0700 Subject: [PATCH 065/120] Location search, deleted users for #1266 --- app/controllers/admin/UsersController.php | 9 ++++++- app/models/User.php | 33 ++++++++++++++++------- app/views/backend/users/index.blade.php | 32 ++++++++++++---------- 3 files changed, 50 insertions(+), 24 deletions(-) diff --git a/app/controllers/admin/UsersController.php b/app/controllers/admin/UsersController.php index 74a40d47d0..5ab108e081 100755 --- a/app/controllers/admin/UsersController.php +++ b/app/controllers/admin/UsersController.php @@ -847,6 +847,13 @@ class UsersController extends AdminController { $users = User::with('assets', 'accessories', 'consumables', 'licenses', 'manager', 'sentryThrottle', 'groups', 'userloc'); + switch ($status) { + case 'deleted': + $users = $users->withTrashed()->Deleted(); + break; + } + + if (Input::has('search')) { $users = $users->TextSearch(Input::get('search')); @@ -896,7 +903,7 @@ class UsersController extends AdminController { $rows[] = array( 'checkbox' =>'<div class="text-center"><input type="checkbox" name="edit_user['.$user->id.']" class="one_required"></div>', - 'name' => '<a title="'.$user->fullName().'" href="hardware/'.$user->id.'/view">'.$user->fullName().'</a>', + 'name' => '<a title="'.$user->fullName().'" href="../admin/users/'.$user->id.'/view">'.$user->fullName().'</a>', 'email' => ($user->email!='') ? '<a href="mailto:'.$user->email.'"><i class="fa fa-envelope"></i></a>' : '', 'username' => $user->username, 'location' => ($user->location_id!='') ? $user->userloc->name : '', diff --git a/app/models/User.php b/app/models/User.php index 1990c690a0..2d99d132fd 100755 --- a/app/models/User.php +++ b/app/models/User.php @@ -211,17 +211,32 @@ class User extends SentryUserModel public function scopeTextsearch($query, $q) { - return $query->where(function($query) use ($q) - { - - $query->orWhere('first_name', 'LIKE', "%$q%") - ->orWhere('first_name', 'LIKE', "%$q%") - ->orWhere('email', 'LIKE', "%$q%") - ->orWhere('username', 'LIKE', "%$q%") - ->orWhere('notes', 'LIKE', "%$q%"); - }); + return $query->where('first_name', 'LIKE', "%$q%") + ->orWhere('last_name', 'LIKE', "%$q%") + ->orWhere('email', 'LIKE', "%$q%") + ->orWhere('username', 'LIKE', "%$q%") + ->orWhere('notes', 'LIKE', "%$q%") + ->orWhere(function($query) use ($q) { + $query->whereHas('userloc', function($query) use ($q) { + $query->where('name','LIKE','%'.$q.'%'); + }); + }); } + /** + * Query builder scope for Deleted users + * + * @param Illuminate\Database\Query\Builder $query Query builder instance + * + * @return Illuminate\Database\Query\Builder Modified query builder + */ + + public function scopeDeleted($query) + { + return $query->whereNotNull('deleted_at'); + } + + } diff --git a/app/views/backend/users/index.blade.php b/app/views/backend/users/index.blade.php index d6f7e7963e..22a5ee3a87 100755 --- a/app/views/backend/users/index.blade.php +++ b/app/views/backend/users/index.blade.php @@ -39,20 +39,26 @@ 'route' => ['users/bulkedit'], 'class' => 'form-horizontal' ]) }} - <table name="assets" id="table" data-url="{{route('api.users.list') }}"> + <table + name="assets" + id="table" + data-toggle="table" + data-url="{{ route('api.users.list', array(''=>Input::get('status'))) }}" + data-cookie="true" + data-cookie-id-table="userTable"> <thead> <tr> <th data-class="hidden-xs" data-switchable="false" data-searchable="false" data-sortable="false" data-field="checkbox"><div class="text-center"><input type="checkbox" id="checkAll" style="padding-left: 0px;"></div></th> <th data-sortable="true" data-field="name">{{ Lang::get('admin/users/table.name') }}</th> <th data-sortable="true" data-field="email"><i class="fa fa-envelope fa-lg"></i></th> <th data-sortable="true" data-field="username">{{ Lang::get('admin/users/table.username') }}</th> - <th data-sortable="true" data-field="manager">{{ Lang::get('admin/users/table.manager') }}</th> - <th data-sortable="true" data-field="location">{{ Lang::get('admin/users/table.location') }}</th> - <th data-sortable="true" data-field="assets"><i class="fa fa-barcode fa-lg"></i></th> - <th data-sortable="true" data-field="licenses"><i class="fa fa-certificate fa-lg"></i></th> - <th data-sortable="true" data-field="accessories"><i class="fa fa-keyboard-o fa-lg"></i></th> - <th data-sortable="true" data-field="consumables"><i class="fa fa-tint fa-lg"></i></th> - <th data-sortable="true" data-field="groups">{{ Lang::get('general.groups') }}</th> + <th data-sortable="false" data-field="manager">{{ Lang::get('admin/users/table.manager') }}</th> + <th data-sortable="false" data-field="location">{{ Lang::get('admin/users/table.location') }}</th> + <th data-sortable="false" data-field="assets"><i class="fa fa-barcode fa-lg"></i></th> + <th data-sortable="false" data-field="licenses"><i class="fa fa-certificate fa-lg"></i></th> + <th data-sortable="false" data-field="accessories"><i class="fa fa-keyboard-o fa-lg"></i></th> + <th data-sortable="false" data-field="consumables"><i class="fa fa-tint fa-lg"></i></th> + <th data-sortable="false" data-field="groups">{{ Lang::get('general.groups') }}</th> <th data-sortable="true" data-field="notes">{{ Lang::get('general.notes') }}</th> <th data-switchable="false" data-searchable="false" data-sortable="false" data-field="actions" >{{ Lang::get('table.actions') }}</th> </tr> @@ -74,11 +80,11 @@ </div> @section('moar_scripts') <script src="{{ asset('assets/js/bootstrap-table.js') }}"></script> +<script src="{{ asset('assets/js/extensions/cookie/bootstrap-table-cookie.js') }}"></script> <script src="{{ asset('assets/js/extensions/mobile/bootstrap-table-mobile.js') }}"></script> -<script src="{{ asset('assets/js/extensions/export/bootstrap-table-export.js?v=1') }}"></script> -<script src="{{ asset('assets/js/extensions/cookie/bootstrap-table-cookie.js?v=1') }}"></script> -<script src="//rawgit.com/kayalshri/tableExport.jquery.plugin/master/tableExport.js?v=1') }}"></script> -<script src="//rawgit.com/kayalshri/tableExport.jquery.plugin/master/jquery.base64.js?v=1') }}"></script> +<script src="{{ asset('assets/js/extensions/export/bootstrap-table-export.js') }}"></script> +<script src="//rawgit.com/kayalshri/tableExport.jquery.plugin/master/tableExport.js') }}"></script> +<script src="//rawgit.com/kayalshri/tableExport.jquery.plugin/master/jquery.base64.js') }}"></script> <script type="text/javascript"> $('#table').bootstrapTable({ classes: 'table table-responsive table-no-bordered', @@ -92,9 +98,7 @@ sortable: true, cookie: true, mobileResponsive: true, - columnsHidden: ['name'], showExport: true, - exportLabel: 'Export', showColumns: true, maintainSelected: true, paginationFirstText: "@lang('general.first')", From 03e36736c22129f94076a0e54866b007e3bd471a Mon Sep 17 00:00:00 2001 From: snipe <snipe@snipe.net> Date: Tue, 20 Oct 2015 22:11:06 -0700 Subject: [PATCH 066/120] Nicer responsive display --- app/controllers/admin/UsersController.php | 4 ++-- app/views/backend/users/index.blade.php | 27 ++++++++++++++++++----- 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/app/controllers/admin/UsersController.php b/app/controllers/admin/UsersController.php index 5ab108e081..746f68c1b3 100755 --- a/app/controllers/admin/UsersController.php +++ b/app/controllers/admin/UsersController.php @@ -902,9 +902,9 @@ class UsersController extends AdminController { $actions .= '</nobr>'; $rows[] = array( - 'checkbox' =>'<div class="text-center"><input type="checkbox" name="edit_user['.$user->id.']" class="one_required"></div>', + 'checkbox' =>'<div class="text-center hidden-xs hidden-sm"><input type="checkbox" name="edit_user['.$user->id.']" class="one_required"></div>', 'name' => '<a title="'.$user->fullName().'" href="../admin/users/'.$user->id.'/view">'.$user->fullName().'</a>', - 'email' => ($user->email!='') ? '<a href="mailto:'.$user->email.'"><i class="fa fa-envelope"></i></a>' : '', + 'email' => ($user->email!='') ? '<span class="hidden-md hidden-lg" style="display: inline !important;"><a href="mailto:'.$user->email.'">'.$user->email.'</a></span> <span class="hidden-xs hidden-sm"><a href="mailto:'.$user->email.'"><i class="fa fa-envelope"></i></a></span>' : '', 'username' => $user->username, 'location' => ($user->location_id!='') ? $user->userloc->name : '', 'manager' => ($user->manager_id!='') ? '<a title="' . $user->manager->fullName() . '" href="users/' . $user->manager->id . '/view">' . $user->manager->fullName() . '</a>' : '', diff --git a/app/views/backend/users/index.blade.php b/app/views/backend/users/index.blade.php index 22a5ee3a87..7aab64b339 100755 --- a/app/views/backend/users/index.blade.php +++ b/app/views/backend/users/index.blade.php @@ -48,16 +48,31 @@ data-cookie-id-table="userTable"> <thead> <tr> - <th data-class="hidden-xs" data-switchable="false" data-searchable="false" data-sortable="false" data-field="checkbox"><div class="text-center"><input type="checkbox" id="checkAll" style="padding-left: 0px;"></div></th> + <th data-class="hidden-xs hidden-sm" data-switchable="false" data-searchable="false" data-sortable="false" data-field="checkbox"><div class="text-center"><input type="checkbox" id="checkAll" style="padding-left: 0px;" style="hidden-xs hidden-sm"></div></th> <th data-sortable="true" data-field="name">{{ Lang::get('admin/users/table.name') }}</th> - <th data-sortable="true" data-field="email"><i class="fa fa-envelope fa-lg"></i></th> + <th data-sortable="true" data-field="email"> + <span class="hidden-md hidden-lg">Email</span> + <span class="hidden-xs"><i class="fa fa-envelope fa-lg"></i></span> + </th> <th data-sortable="true" data-field="username">{{ Lang::get('admin/users/table.username') }}</th> <th data-sortable="false" data-field="manager">{{ Lang::get('admin/users/table.manager') }}</th> <th data-sortable="false" data-field="location">{{ Lang::get('admin/users/table.location') }}</th> - <th data-sortable="false" data-field="assets"><i class="fa fa-barcode fa-lg"></i></th> - <th data-sortable="false" data-field="licenses"><i class="fa fa-certificate fa-lg"></i></th> - <th data-sortable="false" data-field="accessories"><i class="fa fa-keyboard-o fa-lg"></i></th> - <th data-sortable="false" data-field="consumables"><i class="fa fa-tint fa-lg"></i></th> + <th data-sortable="false" data-field="assets"> + <span class="hidden-md hidden-lg">Assets</span> + <span class="hidden-xs"><i class="fa fa-barcode fa-lg"></i></span> + </th> + <th data-sortable="false" data-field="licenses"> + <span class="hidden-md hidden-lg">Licenses</span> + <span class="hidden-xs"><i class="fa fa-certificate fa-lg"></i></span> + </th> + <th data-sortable="false" data-field="accessories"> + <span class="hidden-md hidden-lg">Accessories</span> + <span class="hidden-xs"><i class="fa fa-keyboard-o fa-lg"></i></span> + </th> + <th data-sortable="false" data-field="consumables"> + <span class="hidden-md hidden-lg">Consumables</span> + <span class="hidden-xs"><i class="fa fa-tint fa-lg"></i></span> + </th> <th data-sortable="false" data-field="groups">{{ Lang::get('general.groups') }}</th> <th data-sortable="true" data-field="notes">{{ Lang::get('general.notes') }}</th> <th data-switchable="false" data-searchable="false" data-sortable="false" data-field="actions" >{{ Lang::get('table.actions') }}</th> From dfca1386ac2c66750faa0a7100617d8cb1d622db Mon Sep 17 00:00:00 2001 From: snipe <snipe@snipe.net> Date: Wed, 21 Oct 2015 13:05:14 -0700 Subject: [PATCH 067/120] Accessories bootstrap tables for #1266 --- app/models/Accessory.php | 6 +++--- app/views/backend/accessories/view.blade.php | 19 +++++++++++++++---- app/views/backend/hardware/index.blade.php | 4 ---- 3 files changed, 18 insertions(+), 11 deletions(-) diff --git a/app/models/Accessory.php b/app/models/Accessory.php index 9ccd5e1250..0abed13fcb 100755 --- a/app/models/Accessory.php +++ b/app/models/Accessory.php @@ -67,7 +67,7 @@ class Accessory extends Elegant $remaining = $total - $checkedout; return $remaining; } - + /** * Query builder scope to search on text * @@ -81,8 +81,8 @@ class Accessory extends Elegant return $query->where(function($query) use ($search) { - $query->where('name', 'LIKE', '%'.$s.'%'); + $query->where('name', 'LIKE', '%'.$search.'%'); }); } - + } diff --git a/app/views/backend/accessories/view.blade.php b/app/views/backend/accessories/view.blade.php index bf74053255..62191f2ef5 100644 --- a/app/views/backend/accessories/view.blade.php +++ b/app/views/backend/accessories/view.blade.php @@ -58,20 +58,29 @@ </div> +@section('moar_scripts') +<script src="{{ asset('assets/js/bootstrap-table.js') }}"></script> +<script src="{{ asset('assets/js/extensions/mobile/bootstrap-table-mobile.js') }}"></script> +<script src="{{ asset('assets/js/extensions/export/bootstrap-table-export.js?v=1') }}"></script> +<script src="{{ asset('assets/js/extensions/cookie/bootstrap-table-cookie.js?v=1') }}"></script> +<script src="//rawgit.com/kayalshri/tableExport.jquery.plugin/master/tableExport.js?v=1') }}"></script> +<script src="//rawgit.com/kayalshri/tableExport.jquery.plugin/master/jquery.base64.js?v=1') }}"></script> <script type="text/javascript"> $('#table').bootstrapTable({ - classes: 'table table-hover table-no-bordered', - undefinedText: 'undefined', + classes: 'table table-responsive table-no-bordered', + undefinedText: '', iconsPrefix: 'fa', showRefresh: true, - search: false, + search: true, pageSize: {{{ Setting::getSettings()->per_page }}}, pagination: true, sidePagination: 'server', sortable: true, + cookie: true, mobileResponsive: true, + columnsHidden: ['name'], showExport: true, - showColumns: false, + exportLabel: 'Export', maintainSelected: true, paginationFirstText: "@lang('general.first')", paginationLastText: "@lang('general.last')", @@ -84,7 +93,9 @@ columns: 'fa-columns', refresh: 'fa-refresh' }, + }); </script> +@stop @stop diff --git a/app/views/backend/hardware/index.blade.php b/app/views/backend/hardware/index.blade.php index 906e1b5103..4b58be414c 100755 --- a/app/views/backend/hardware/index.blade.php +++ b/app/views/backend/hardware/index.blade.php @@ -33,10 +33,6 @@ {{-- Page content --}} @section('content') -<style> -.dataTables_filter {padding-right: 20px;} - -</style> <div class="row header"> <div class="col-md-12"> From 87adb5e0ca7628c829c4e70bbb07f013fb30dde1 Mon Sep 17 00:00:00 2001 From: snipe <snipe@snipe.net> Date: Wed, 21 Oct 2015 13:11:27 -0700 Subject: [PATCH 068/120] Use old Datatables for maintenances until we can build the bootstrap tables API --- app/config/version.php | 4 ++-- app/views/backend/asset_maintenances/index.blade.php | 12 ++++++++++++ app/views/backend/layouts/default.blade.php | 6 +++--- 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/app/config/version.php b/app/config/version.php index 27dacf849e..5f395adfd7 100644 --- a/app/config/version.php +++ b/app/config/version.php @@ -1,5 +1,5 @@ <?php return array ( - 'app_version' => 'v2.0-236', - 'hash_version' => 'v2.0-236-g2171e66', + 'app_version' => 'v2.0-250', + 'hash_version' => 'v2.0-250-g03e3673', ); \ No newline at end of file diff --git a/app/views/backend/asset_maintenances/index.blade.php b/app/views/backend/asset_maintenances/index.blade.php index d05862f426..f3bbe4c6f4 100644 --- a/app/views/backend/asset_maintenances/index.blade.php +++ b/app/views/backend/asset_maintenances/index.blade.php @@ -7,6 +7,11 @@ {{-- Page content --}} @section('content') + + <link rel="stylesheet" href="https://demo.snipeitapp.com/assets/css/lib/jquery.dataTables.css" type="text/css" media="screen" /> + <link rel="stylesheet" href="https://demo.snipeitapp.com/assets/css/compiled/dataTables.colVis.css" type="text/css" media="screen" /> + <link rel="stylesheet" href="https://demo.snipeitapp.com/assets/css/compiled/dataTables.tableTools.css" type="text/css" media="screen" /> + <div class="row header"> <div class="col-md-12"> <a href="{{ route('create/asset_maintenances') }}" class="btn btn-success pull-right"><i class="fa fa-plus icon-white"></i> Create New</a> @@ -53,4 +58,11 @@ ) ->render() }} </div> + +@section('moar_scripts') +<script src="https://demo.snipeitapp.com/assets/js/jquery.dataTables.min.js"></script> +<script src="https://demo.snipeitapp.com/assets/js/dataTables.colVis.js"></script> +<script src="https://demo.snipeitapp.com/assets/js/dataTables.tableTools.js"></script> + +@stop @stop diff --git a/app/views/backend/layouts/default.blade.php b/app/views/backend/layouts/default.blade.php index cd9d84d036..f4dff6b422 100644 --- a/app/views/backend/layouts/default.blade.php +++ b/app/views/backend/layouts/default.blade.php @@ -43,6 +43,9 @@ <!-- global header javascripts --> + <script src="{{ asset('assets/js/jquery-latest.js') }}"></script> + <script src="{{ asset('assets/js/bootstrap.min.js') }}"></script> + <script> window.snipeit = { settings: { @@ -454,9 +457,6 @@ </div> <!-- scripts --> - - <script src="{{ asset('assets/js/jquery-latest.js') }}"></script> - <script src="{{ asset('assets/js/bootstrap.min.js') }}"></script> <script src="{{ asset('assets/js/jquery.knob.js') }}"></script> <script src="{{ asset('assets/js/select2.min.js') }}"></script> <script src="{{ asset('assets/js/jquery.uniform.min.js') }}"></script> From 21982a1d51c8696db44ca382f85cdc5ff23954da Mon Sep 17 00:00:00 2001 From: snipe <snipe@snipe.net> Date: Wed, 21 Oct 2015 13:14:56 -0700 Subject: [PATCH 069/120] Additional fields for text search on licenses --- app/config/version.php | 4 ++-- app/models/License.php | 9 +++++++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/app/config/version.php b/app/config/version.php index 5f395adfd7..966f869e62 100644 --- a/app/config/version.php +++ b/app/config/version.php @@ -1,5 +1,5 @@ <?php return array ( - 'app_version' => 'v2.0-250', - 'hash_version' => 'v2.0-250-g03e3673', + 'app_version' => 'v2.0-251', + 'hash_version' => 'v2.0-251-gdfca138', ); \ No newline at end of file diff --git a/app/models/License.php b/app/models/License.php index d2be54b610..08476fe646 100755 --- a/app/models/License.php +++ b/app/models/License.php @@ -176,7 +176,7 @@ public function freeSeat() ->get(); } - + /** * Query builder scope to search on text * @@ -190,7 +190,12 @@ public function freeSeat() return $query->where(function($query) use ($search) { - $query->where('name', 'LIKE', '%'.$search.'%'); + $query->where('name', 'LIKE', '%'.$search.'%') + ->orWhere('serial', 'LIKE', '%'.$search.'%') + ->orWhere('notes', 'LIKE', '%'.$search.'%') + ->orWhere('order_number', 'LIKE', '%'.$search.'%') + ->orWhere('purchase_date', 'LIKE', '%'.$search.'%') + ->orWhere('purchase_cost', 'LIKE', '%'.$search.'%'); }); } } From cf7571d3a6e796a8f5cf15536ed18fabf07b939e Mon Sep 17 00:00:00 2001 From: snipe <snipe@snipe.net> Date: Wed, 21 Oct 2015 13:27:40 -0700 Subject: [PATCH 070/120] Fixed inline display od checkboxes --- app/config/version.php | 4 ++-- public/assets/css/compiled/layout.css | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/app/config/version.php b/app/config/version.php index 966f869e62..8e4c15c7f2 100644 --- a/app/config/version.php +++ b/app/config/version.php @@ -1,5 +1,5 @@ <?php return array ( - 'app_version' => 'v2.0-251', - 'hash_version' => 'v2.0-251-gdfca138', + 'app_version' => 'v2.0-252', + 'hash_version' => 'v2.0-252-g87adb5e', ); \ No newline at end of file diff --git a/public/assets/css/compiled/layout.css b/public/assets/css/compiled/layout.css index 82291b03df..70c43e79d4 100644 --- a/public/assets/css/compiled/layout.css +++ b/public/assets/css/compiled/layout.css @@ -5,3 +5,7 @@ To remove this comment, please support us and upgrade to SiteFlow Pro. @media screen { body{font-family:'Open Sans', sans-serif;background-color:#f7f7f7;position:relative;margin:0px;font-size:12px;padding:0px}h1,h2,h3,h4,h5{margin:0;line-height:inherit;color:#29323d}h1 small,h2 small,h3 small,h4 small,h5 small{margin-left:15px;font-style:italic}body.menu{overflow-x:hidden}body.menu .content{margin-left:165px;position:fixed;width:850px}body.menu #sidebar-nav{position:absolute;left:0;border-right:0px;box-shadow:none}input.search{background:url("../../img/lens.png") #fcfcfc no-repeat 95%;box-shadow:none;height:25px;width:220px;font-size:13px;padding:2px 6px;border:1px solid #d0dde9;margin:0;border-radius:2px;top:11px}.header{margin-bottom:25px}.header h1,.header h2,.header h3,.header h4,.header h5{float:left;margin-top:5px}.navbar-inverse input.search{height:27px;width:220px;padding:3px 6px;background:url("../../img/lens.png") #0f1217 no-repeat 95%;border:1px solid #0f1217;position:relative;border-radius:4px;top:9px;color:#000;font-size:13px;margin-right:40px;-webkit-transition:all .3s linear;-moz-transition:all .3s linear;transition:all .3s linear}.navbar-inverse input.search:focus{background-color:#fff;border:0}.navbar-inverse .settings i{color:#9ba3ad;font-size:21px}.navbar-inverse .notification-dropdown{position:relative}.navbar-inverse .notification-dropdown>a:hover,.navbar-inverse .notification-dropdown>a.active{background:#254261 !important;box-shadow:inset 1px 0px 1px 0px #3e5a79}.navbar-inverse .notification-dropdown i{font-size:17px;color:#9ba3ad}.navbar-inverse .notification-dropdown .count{position:absolute;top:1px;left:58%;background:#35bac4;padding:0px 5px;border-radius:30px;color:#fff;line-height:16px;z-index:9999;text-align:center;font-size:11px}.navbar-inverse .pop-dialog{position:absolute;right:-10px;top:55px;display:none}.navbar-inverse .pop-dialog.is-visible{display:block;-webkit-animation:reveal .2s ease-out;-moz-animation:reveal .2s ease-out;animation:reveal .2s ease-out}.navbar-inverse .pop-dialog .body{box-shadow:0px 1px 9px 1px #c2c2c2}.navbar-inverse .pop-dialog .close-icon{float:right;text-decoration:none;z-index:9999;position:relative}.navbar-inverse .pop-dialog .footer{border-top:1px solid #e6e8e9;background-color:#eff4f7;margin:15px 0px -10px 0px;border-radius:0px 0px 5px 5px;padding:12px 20px;text-align:center}.navbar-inverse .pop-dialog .footer a{font-weight:600;color:#7d91a8}.navbar-inverse .pop-dialog .notifications{width:330px;margin:10px -10px 0px -10px}.navbar-inverse .pop-dialog .notifications h3{font-size:13px;color:#404951;font-weight:bold;padding-left:20px;margin-top:5px;margin-bottom:15px}.navbar-inverse .pop-dialog .notifications .item{display:block;padding:10px 0px 8px 20px;border-top:1px solid #e7e8ea;color:#363636;text-decoration:none;padding-left:50px;position:relative;transition:all .25s linear;-moz-transition:all .25s linear;-webkit-transition:all .25s linear;-o-transition:all .25s linear}.navbar-inverse .pop-dialog .notifications .item:hover{background:#f0f6ff}.navbar-inverse .pop-dialog .notifications .item>i{color:#fc827b;position:absolute;left:19px;font-size:18px}.navbar-inverse .pop-dialog .notifications .item>i.icon-user{left:18px}.navbar-inverse .pop-dialog .notifications .item .time{float:right;color:#82a3c1;font-style:italic;font-weight:600;font-size:11px;min-width:60px;margin-right:5px}.navbar-inverse .pop-dialog .notifications .item .time i{font-size:13px;color:#cfcfcf;margin-right:1px}.navbar-inverse .pop-dialog .messages{width:325px;margin:10px -10px 0px -10px}.navbar-inverse .pop-dialog .messages .item{display:block;padding:10px 20px 15px 20px;height:80px;border-bottom:1px solid #e7e8ea;color:#363636;text-decoration:none;position:relative;transition:all .25s linear;-moz-transition:all .25s linear;-webkit-transition:all .25s linear;-o-transition:all .25s linear}.navbar-inverse .pop-dialog .messages .item.last{border-bottom:0px}.navbar-inverse .pop-dialog .messages .item:hover{background:#f0f6ff}.navbar-inverse .pop-dialog .messages .item .display{float:left;border-radius:50px;margin-right:15px}.navbar-inverse .pop-dialog .messages .item .name{font-size:12px;color:#404951;font-weight:bold}.navbar-inverse .pop-dialog .messages .item .msg{font-size:11px;color:#636363;line-height:13px;position:relative;top:2px}.navbar-inverse .pop-dialog .messages .item .time{position:absolute;right:0px;bottom:6px;color:#82a3c1;font-style:italic;font-weight:600;font-size:11px;min-width:60px;margin-right:5px}.navbar-inverse .pop-dialog .messages .item .time i{font-size:13px;color:#cfcfcf;margin-right:1px}.navbar-inverse .pop-dialog .messages .footer{margin-top:6px}#sidebar-nav{position:absolute;width:180px;float:left;margin:0em;padding-top:0.5em}#sidebar-nav #dashboard-menu{list-style:none;padding-right:15px;padding-left:15px;margin-bottom:0;margin-left:20px}#sidebar-nav #dashboard-menu>li>a{display:block;padding:19px 14px 15px 14px;margin-left:-15px;margin-bottom:5px;border-bottom:1px solid #dae1e8;box-shadow:0 2px 1px -1px #FFFFFF;color:#6e829b;outline:0px;line-height:21px}#sidebar-nav #dashboard-menu>li{position:relative}#sidebar-nav #dashboard-menu>li .icon-group{font-size:22px}#sidebar-nav #dashboard-menu>li i{font-size:23px;top:17px}#sidebar-nav #dashboard-menu>li:hover i{opacity:1}#sidebar-nav #dashboard-menu>li.active>a,#sidebar-nav #dashboard-menu>li>a:hover{color:#33455a;text-decoration:none}#sidebar-nav #dashboard-menu>li.active a{font-weight:600;text-shadow:1px 1px 1px #fff}#sidebar-nav #dashboard-menu>li.active i{opacity:1}#sidebar-nav #dashboard-menu .pointer{position:absolute;right:9px;top:20px}#sidebar-nav #dashboard-menu .pointer .arrow,#sidebar-nav #dashboard-menu .pointer .arrow_border{border-color:transparent #fff transparent transparent;border-width:11px;border-style:solid;font-size:0;left:50%;line-height:0;margin:0 auto;position:absolute;top:0;width:0;z-index:1002;left:0;margin-left:45%}#sidebar-nav #dashboard-menu .pointer .arrow_border{border-color:transparent #c0d2dd transparent transparent;border-width:11px;margin-left:-1px;border-style:solid;z-index:1001;top:0px}#sidebar-nav #dashboard-menu a span{margin-left:35px;transition:color .1s linear;-moz-transition:color .1s linear;-webkit-transition:color .1s linear;-o-transition:color .1s linear}#sidebar-nav #dashboard-menu a.ui-elements span{margin-left:25px}#sidebar-nav #dashboard-menu a i{position:absolute;left:0;height:24px;width:24px;opacity:0.7;transition:opacity .1s ease;-moz-transition:opacity .1s ease;-webkit-transition:opacity .1s ease;-o-transition:opacity .1s ease}#sidebar-nav #dashboard-menu a i.icon-chevron-down{position:relative;float:right;top:5px;font-size:11px;color:#686868;width:initial;height:initial}#sidebar-nav #dashboard-menu>li.active .dropdown-toggle{border-bottom:0px;box-shadow:none}#sidebar-nav #dashboard-menu ul.submenu{list-style-type:none;display:none;margin-top:7px;margin-bottom:15px;margin-right:5px;margin-left:-15px;padding-left:15px;border-bottom:1px solid #dae1e8;box-shadow:0 2px 1px -1px #FFFFFF;padding-bottom:10px}#sidebar-nav #dashboard-menu ul.submenu.active{display:block}#sidebar-nav #dashboard-menu ul.submenu a{font-weight:normal;font-size:13px;color:#4c535a;text-decoration:none;display:block;margin-bottom:7px}#sidebar-nav #dashboard-menu ul.submenu a:hover{text-decoration:underline}#sidebar-nav #dashboard-menu ul.submenu a.active{font-weight:bold;text-shadow:none}#pad-wrapper{padding:0px 50px;margin-top:15px}#pad-wrapper h4{color:#696d73;font-style:italic}.content{min-width:400px;min-height:500px;margin-bottom:20px;padding-bottom:50px;overflow:hidden;position:relative;background:#fff;margin-left:177px;border-left:1px solid #dae3e9;border-bottom:1px solid #dae3e9;box-shadow:-3px 3px 3px -2px #f1f1f3;border-radius:0px 0px 0px 5px;-webkit-transition:margin-left .3s ease;-moz-transition:margin-left .3s ease;-o-transition:margin-left .3s ease;-ms-transition:margin-left .3s ease;transition:margin-left .3s ease}.content.wide-content{margin-left:0;border-radius:0}.content .skins-nav{opacity:1;-webkit-transition:right .3s;-moz-transition:right .3s;-ms-transition:right .3s;-o-transition:right .3s;transition:right .3s;position:fixed;right:-88px;top:135px;font-size:13px;z-index:9999}.content .skins-nav:hover{right:0}.content .skins-nav a{display:block;color:#fff;text-decoration:none;padding-left:10px;height:37px;-webkit-border-radius:4px 0 0 4px;-moz-border-radius:4px 0 0 4px;border-radius:4px 0 0 4px;margin-bottom:3px;-webkit-transition:all .5s;-moz-transition:all .5s;-ms-transition:all .5s;-o-transition:all .5s;transition:all .5s}.content .skins-nav a.first_nav{background:rgba(95,175,228,0.8)}.content .skins-nav a.first_nav:hover{background:#5fafe4}.content .skins-nav a.second_nav{background:rgba(36,43,77,0.8)}.content .skins-nav a.second_nav:hover{background:#242b4d}.content .skins-nav a .icon{float:left;width:9px;height:10px;background:url("../../img/skin-nav-bullets.png") 0 0 no-repeat;margin:15px 15px 0 5px}.content .skins-nav a.selected .icon{background-position:0 -9px}.content .skins-nav a .text{padding-right:12px;white-space:nowrap;display:block;width:115px;position:relative;top:9px;-webkit-transition:width .2s;-moz-transition:width .2s;-ms-transition:width .2s;-o-transition:width .2s;transition:width .2s}@media (max-width: 768px){#pad-wrapper{padding:0px 15px}.content{min-width:0px;margin:0}#dashboard-menu .pointer{display:none}#sidebar-nav{left:-200px;position:fixed;z-index:9999;background-color:#f7f7f7;padding-top:0px;border-right:1px solid #ccc;width:165px;box-shadow:1px 1px 4px 1px #e9e9e9;-webkit-transition:left .3s ease;-moz-transition:left .3s ease;-o-transition:left .3s ease;-ms-transition:left .3s ease;transition:left .3s ease}#sidebar-nav #dashboard-menu{margin-left:10px}#sidebar-nav #dashboard-menu li a span{visibility:visible}#sidebar-nav #dashboard-menu li:last-child a{border-bottom:0px;box-shadow:none}}@media (max-width: 822px){.navbar-inverse input.search{display:none}}@media (max-width: 767px){#main-stats .stat{width:50%;float:left}}.alert-msg{color:#b94a48} } + +div.checker { + display: inline; +} From d9ea718d51415d87f938f0810e994adda6337e78 Mon Sep 17 00:00:00 2001 From: snipe <snipe@snipe.net> Date: Wed, 21 Oct 2015 13:36:35 -0700 Subject: [PATCH 071/120] Added back missing div --- app/config/version.php | 4 ++-- app/views/backend/settings/edit.blade.php | 15 ++++++++------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/app/config/version.php b/app/config/version.php index 8e4c15c7f2..4474d10117 100644 --- a/app/config/version.php +++ b/app/config/version.php @@ -1,5 +1,5 @@ <?php return array ( - 'app_version' => 'v2.0-252', - 'hash_version' => 'v2.0-252-g87adb5e', + 'app_version' => 'v2.0-253', + 'hash_version' => 'v2.0-253-g21982a1', ); \ No newline at end of file diff --git a/app/views/backend/settings/edit.blade.php b/app/views/backend/settings/edit.blade.php index fa522defba..9b1c20a036 100755 --- a/app/views/backend/settings/edit.blade.php +++ b/app/views/backend/settings/edit.blade.php @@ -323,14 +323,15 @@ padding: 0px 20px; </form> </div> -</div> - - <!-- side address column --> - <div class="col-md-3 address pull-right"> - <br /><br /> - <p>@lang('admin/settings/general.info')</p> - </div> + </div> + + <!-- side address column --> + <div class="col-md-3 address pull-right"> + <br /><br /> + <p>@lang('admin/settings/general.info')</p> + + </div> </div> @stop From def6b4ff50187b005f73957028bd2fac35802400 Mon Sep 17 00:00:00 2001 From: snipe <snipe@snipe.net> Date: Wed, 21 Oct 2015 13:48:52 -0700 Subject: [PATCH 072/120] Categories for accessories in #1266 --- app/config/version.php | 4 ++-- .../admin/AccessoriesController.php | 18 ++++++++++++++++-- app/views/backend/accessories/index.blade.php | 3 +-- 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/app/config/version.php b/app/config/version.php index 4474d10117..73c194b908 100644 --- a/app/config/version.php +++ b/app/config/version.php @@ -1,5 +1,5 @@ <?php return array ( - 'app_version' => 'v2.0-253', - 'hash_version' => 'v2.0-253-g21982a1', + 'app_version' => 'v2.0-254', + 'hash_version' => 'v2.0-254-gcf7571d', ); \ No newline at end of file diff --git a/app/controllers/admin/AccessoriesController.php b/app/controllers/admin/AccessoriesController.php index 4e2e599959..18334edcb8 100755 --- a/app/controllers/admin/AccessoriesController.php +++ b/app/controllers/admin/AccessoriesController.php @@ -465,13 +465,26 @@ class AccessoriesController extends AdminController public function getDatatable() { - $accessories = Accessory::select(array('id','name','qty')) + $accessories = Accessory::select(array('id','name','qty','category_id'))->with('category') ->whereNull('deleted_at'); if (Input::has('search')) { $accessories = $accessories->TextSearch(Input::get('search')); } + if (Input::has('offset')) { + $offset = e(Input::get('offset')); + } else { + $offset = 0; + } + + if (Input::has('limit')) { + $limit = e(Input::get('limit')); + } else { + $limit = 50; + } + + $allowed_columns = ['name']; $order = Input::get('order') === 'asc' ? 'asc' : 'desc'; $sort = in_array(Input::get('sort'), $allowed_columns) ? Input::get('sort') : 'created_at'; @@ -479,7 +492,7 @@ class AccessoriesController extends AdminController $accessories = $accessories->orderBy($sort, $order); $accessCount = $accessories->count(); - $accessories = $accessories->skip(Input::get('offset'))->take(Input::get('limit'))->get(); + $accessories = $accessories->skip($offset)->take($limit)->get(); $rows = array(); @@ -488,6 +501,7 @@ class AccessoriesController extends AdminController $rows[] = array( 'name' => link_to('admin/accessories/'.$accessory->id.'/view', $accessory->name), + 'category' => $accessory->category->name, 'qty' => $accessory->qty, 'numRemaining' => $accessory->numRemaining(), 'actions' => $actions diff --git a/app/views/backend/accessories/index.blade.php b/app/views/backend/accessories/index.blade.php index 98117c9e00..8b45b07f0c 100755 --- a/app/views/backend/accessories/index.blade.php +++ b/app/views/backend/accessories/index.blade.php @@ -23,6 +23,7 @@ <thead> <tr> <th data-sortable="true" data-field="name">{{Lang::get('admin/accessories/table.title')}}</th> + <th data-switchable="false" data-searchable="false" data-sortable="false" data-field="category">{{Lang::get('admin/accessories/general.accessory_category')}}</th> <th data-switchable="false" data-searchable="false" data-sortable="false" data-field="qty">{{Lang::get('admin/accessories/general.total')}}</th> <th data-switchable="false" data-searchable="false" data-sortable="false" data-field="numRemaining">{{Lang::get('admin/accessories/general.remaining')}}</th> <th data-switchable="false" data-searchable="false" data-sortable="false" data-field="actions">{{Lang::get('table.actions')}}</th> @@ -64,8 +65,6 @@ mobileResponsive: true, columnsHidden: ['name'], showExport: true, - exportLabel: 'Export', - showColumns: true, maintainSelected: true, paginationFirstText: "@lang('general.first')", paginationLastText: "@lang('general.last')", From 47d6682098de4b706cdd987e3d42c2dcb4f2b304 Mon Sep 17 00:00:00 2001 From: snipe <snipe@snipe.net> Date: Wed, 21 Oct 2015 14:40:46 -0700 Subject: [PATCH 073/120] Updated cookie.js for #1266 --- .../cookie/bootstrap-table-cookie.js | 263 ++++++++++++------ 1 file changed, 180 insertions(+), 83 deletions(-) diff --git a/public/assets/js/extensions/cookie/bootstrap-table-cookie.js b/public/assets/js/extensions/cookie/bootstrap-table-cookie.js index b5a0c67754..c1dc348d30 100644 --- a/public/assets/js/extensions/cookie/bootstrap-table-cookie.js +++ b/public/assets/js/extensions/cookie/bootstrap-table-cookie.js @@ -1,7 +1,7 @@ /** * @author: Dennis Hernández * @webSite: http://djhvscf.github.io/Blog - * @version: v1.1.0 + * @version: v1.2.0 * * @update zhixin wen <wenzhixin2010@gmail.com> */ @@ -9,41 +9,80 @@ (function ($) { 'use strict'; - var idsStateSaveList = { + var cookieIds = { sortOrder: 'bs.table.sortOrder', sortName: 'bs.table.sortName', pageNumber: 'bs.table.pageNumber', pageList: 'bs.table.pageList', columns: 'bs.table.columns', - searchText: 'bs.table.searchText' + searchText: 'bs.table.searchText', + filterControl: 'bs.table.filterControl' + }; + + var getCurrentHeader = function (that) { + var header = that.$header; + if (that.options.height) { + header = that.$tableHeader; + } + + return header; + }; + + var getCurrentSearchControls = function (that) { + var searchControls = 'select, input'; + if (that.options.height) { + searchControls = 'table select, table input'; + } + + return searchControls; }; var cookieEnabled = function () { - return (navigator.cookieEnabled) ? true : false; + return !!(navigator.cookieEnabled); }; - var setCookie = function (that, cookieName, sValue, sPath, sDomain, bSecure) { - if ((!that.options.stateSave) || (!cookieEnabled()) || (that.options.stateSaveIdTable === '')) { + var inArrayCookiesEnabled = function (cookieName, cookiesEnabled) { + var index = -1; + + for (var i = 0; i < cookiesEnabled.length; i++) { + if (cookieName.toLowerCase() === cookiesEnabled[i].toLowerCase()) { + index = i; + break; + } + } + + return index; + }; + + var setCookie = function (that, cookieName, cookieValue) { + if ((!that.options.cookie) || (!cookieEnabled()) || (that.options.cookieIdTable === '')) { return; } - var tableName = that.options.stateSaveIdTable, - vEnd = that.options.stateSaveExpire; + if (inArrayCookiesEnabled(cookieName, that.options.cookiesEnabled) === -1) { + return; + } - cookieName = tableName + '.' + cookieName; + cookieName = that.options.cookieIdTable + '.' + cookieName; if (!cookieName || /^(?:expires|max\-age|path|domain|secure)$/i.test(cookieName)) { return false; } - document.cookie = encodeURIComponent(cookieName) + '=' + encodeURIComponent(sValue) + calculateExpiration(vEnd) + (sDomain ? '; domain=' + sDomain : '') + (sPath ? '; path=' + sPath : '') + (bSecure ? '; secure' : ''); + document.cookie = encodeURIComponent(cookieName) + '=' + encodeURIComponent(cookieValue) + calculateExpiration(that.options.cookieExpire) + (that.options.cookieDomain ? '; domain=' + that.options.cookieDomain : '') + (that.options.cookiePath ? '; path=' + that.options.cookiePath : '') + (that.cookieSecure ? '; secure' : ''); return true; }; - var getCookie = function (tableName, cookieName) { - cookieName = tableName + '.' + cookieName; + var getCookie = function (that, tableName, cookieName) { if (!cookieName) { return null; } + + if (inArrayCookiesEnabled(cookieName, that.options.cookiesEnabled) === -1) { + return null; + } + + cookieName = tableName + '.' + cookieName; + return decodeURIComponent(document.cookie.replace(new RegExp('(?:(?:^|.*;)\\s*' + encodeURIComponent(cookieName).replace(/[\-\.\+\*]/g, '\\$&') + '\\s*\\=\\s*([^;]*).*$)|^.*$'), '$1')) || null; }; @@ -63,46 +102,54 @@ return true; }; - var calculateExpiration = function(vEnd) { - var time = vEnd.replace(/[0-9]/, ''); //s,mi,h,d,m,y - vEnd = vEnd.replace(/[A-Za-z]/, ''); //number + var calculateExpiration = function(cookieExpire) { + var time = cookieExpire.replace(/[0-9]*/, ''); //s,mi,h,d,m,y + cookieExpire = cookieExpire.replace(/[A-Za-z]/, ''); //number switch (time.toLowerCase()) { case 's': - vEnd = +vEnd; + cookieExpire = +cookieExpire; break; case 'mi': - vEnd = vEnd * 60; + cookieExpire = cookieExpire * 60; break; case 'h': - vEnd = vEnd * 60 * 60; + cookieExpire = cookieExpire * 60 * 60; break; case 'd': - vEnd = vEnd * 24 * 60 * 60; + cookieExpire = cookieExpire * 24 * 60 * 60; break; case 'm': - vEnd = vEnd * 30 * 24 * 60 * 60; + cookieExpire = cookieExpire * 30 * 24 * 60 * 60; break; case 'y': - vEnd = vEnd * 365 * 30 * 24 * 60 * 60; + cookieExpire = cookieExpire * 365 * 30 * 24 * 60 * 60; break; default: - vEnd = undefined; + cookieExpire = undefined; break; } - return vEnd === undefined ? '' : '; max-age=' + vEnd; - } + return cookieExpire === undefined ? '' : '; max-age=' + cookieExpire; + }; $.extend($.fn.bootstrapTable.defaults, { - stateSave: false, - stateSaveExpire: '2h', - stateSaveIdTable: '' + cookie: false, + cookieExpire: '2h', + cookiePath: null, + cookieDomain: null, + cookieSecure: null, + cookieIdTable: '', + cookiesEnabled: ['bs.table.sortOrder', 'bs.table.sortName', 'bs.table.pageNumber', 'bs.table.pageList', 'bs.table.columns', 'bs.table.searchText', 'bs.table.filterControl'], + //internal variable + filterControls: [], + filterControlValuesLoaded: false }); $.fn.bootstrapTable.methods.push('deleteCookie'); var BootstrapTable = $.fn.bootstrapTable.Constructor, + _init = BootstrapTable.prototype.init, _initTable = BootstrapTable.prototype.initTable, _onSort = BootstrapTable.prototype.onSort, _onPageNumber = BootstrapTable.prototype.onPageNumber, @@ -112,96 +159,142 @@ _onPageNext = BootstrapTable.prototype.onPageNext, _onPageLast = BootstrapTable.prototype.onPageLast, _toggleColumn = BootstrapTable.prototype.toggleColumn, + _selectPage = BootstrapTable.prototype.selectPage, _onSearch = BootstrapTable.prototype.onSearch; - // init save data after initTable function - BootstrapTable.prototype.initTable = function () { - _initTable.apply(this, Array.prototype.slice.apply(arguments)); - this.initStateSave(); - }; + BootstrapTable.prototype.init = function () { + var timeoutId = 0; + this.options.filterControls = []; + this.options.filterControlValuesLoaded = false; - BootstrapTable.prototype.initStateSave = function () { - if (!this.options.stateSave) { - return; - } - if (!cookieEnabled()) { - return; - } + this.options.cookiesEnabled = typeof this.options.cookiesEnabled === 'string' ? + this.options.cookiesEnabled.replace('[', '').replace(']', '').replace(/ /g, '').toLowerCase().split(',') : this.options.cookiesEnabled; - if (this.options.stateSaveIdTable === '') { - return; - } + if (this.options.filterControl) { + var that = this; + this.$el.on('column-search.bs.table', function (e, field, text) { + var isNewField = true; - var sortOrderStateSave = getCookie(this.options.stateSaveIdTable, idsStateSaveList.sortOrder), - sortOrderStateName = getCookie(this.options.stateSaveIdTable, idsStateSaveList.sortName), - pageNumberStateSave = getCookie(this.options.stateSaveIdTable, idsStateSaveList.pageNumber), - pageListStateSave = getCookie(this.options.stateSaveIdTable, idsStateSaveList.pageList), - columnsStateSave = JSON.parse(getCookie(this.options.stateSaveIdTable, idsStateSaveList.columns)), - searchStateSave = getCookie(this.options.stateSaveIdTable, idsStateSaveList.searchText); + for (var i = 0; i < that.options.filterControls.length; i++) { + if (that.options.filterControls[i].field === field) { + that.options.filterControls[i].text = text; + isNewField = false; + break; + } + } + if (isNewField) { + that.options.filterControls.push({ + field: field, + text: text + }); + } - if (sortOrderStateSave) { - this.options.sortOrder = sortOrderStateSave; - this.options.sortName = sortOrderStateName; - } + setCookie(that, cookieIds.filterControl, JSON.stringify(that.options.filterControls)); + }).on('post-body.bs.table', function () { + setTimeout(function () { + if (!that.options.filterControlValuesLoaded) { + that.options.filterControlValuesLoaded = true; + var filterControl = JSON.parse(getCookie(that, that.options.cookieIdTable, cookieIds.filterControl)); + if (filterControl) { + var field = null, + result = [], + header = getCurrentHeader(that), + searchControls = getCurrentSearchControls(that); - if (pageNumberStateSave) { - this.options.pageNumber = +pageNumberStateSave; - } + header.find(searchControls).each(function (index, ele) { + field = $(this).parent().parent().parent().data('field'); + result = $.grep(filterControl, function (valueObj) { + return valueObj.field === field; + }); - if (pageListStateSave) { - this.options.pageSize = pageListStateSave === - this.options.formatAllRows() ? pageListStateSave : +pageListStateSave; - } - - if (columnsStateSave) { - $.each(this.options.columns, function (i, column) { - column.visible = columnsStateSave.indexOf(i) !== -1; + if (result.length > 0) { + $(this).val(result[0].text); + that.onColumnSearch({currentTarget: $(this)}); + } + }); + } + } + }, 250); }); } + _init.apply(this, Array.prototype.slice.apply(arguments)); + }; - if (searchStateSave) { - this.options.searchText = searchStateSave; + BootstrapTable.prototype.initTable = function () { + _initTable.apply(this, Array.prototype.slice.apply(arguments)); + this.initCookie(); + }; + + BootstrapTable.prototype.initCookie = function () { + if (!this.options.cookie) { + return; + } + + if ((this.options.cookieIdTable === '') || (this.options.cookieExpire === '') || (!cookieEnabled())) { + throw new Error("Configuration error. Please review the cookieIdTable, cookieExpire properties, if those properties are ok, then this browser does not support the cookies"); + return; + } + + var sortOrderCookie = getCookie(this, this.options.cookieIdTable, cookieIds.sortOrder), + sortOrderNameCookie = getCookie(this, this.options.cookieIdTable, cookieIds.sortName), + pageNumberCookie = getCookie(this, this.options.cookieIdTable, cookieIds.pageNumber), + pageListCookie = getCookie(this, this.options.cookieIdTable, cookieIds.pageList), + columnsCookie = JSON.parse(getCookie(this, this.options.cookieIdTable, cookieIds.columns)), + searchTextCookie = getCookie(this, this.options.cookieIdTable, cookieIds.searchText); + + //sortOrder + this.options.sortOrder = sortOrderCookie ? sortOrderCookie : 'asc'; + //sortName + this.options.sortName = sortOrderNameCookie ? sortOrderNameCookie : undefined; + //pageNumber + this.options.pageNumber = pageNumberCookie ? +pageNumberCookie : this.options.pageNumber; + //pageSize + this.options.pageSize = pageListCookie ? pageListCookie === this.options.formatAllRows() ? pageListCookie : +pageListCookie : this.options.pageSize; + //searchText + this.options.searchText = searchTextCookie ? searchTextCookie : ''; + + if (columnsCookie) { + $.each(this.columns, function (i, column) { + column.visible = $.inArray(column.field, columnsCookie) !== -1; + }); } }; BootstrapTable.prototype.onSort = function () { _onSort.apply(this, Array.prototype.slice.apply(arguments)); - - setCookie(this, idsStateSaveList.sortOrder, this.options.sortOrder); - setCookie(this, idsStateSaveList.sortName, this.options.sortName); + setCookie(this, cookieIds.sortOrder, this.options.sortOrder); + setCookie(this, cookieIds.sortName, this.options.sortName); }; BootstrapTable.prototype.onPageNumber = function () { _onPageNumber.apply(this, Array.prototype.slice.apply(arguments)); - - setCookie(this, idsStateSaveList.pageNumber, this.options.pageNumber); + setCookie(this, cookieIds.pageNumber, this.options.pageNumber); }; BootstrapTable.prototype.onPageListChange = function () { _onPageListChange.apply(this, Array.prototype.slice.apply(arguments)); - - setCookie(this, idsStateSaveList.pageList, this.options.pageSize); + setCookie(this, cookieIds.pageList, this.options.pageSize); }; BootstrapTable.prototype.onPageFirst = function () { _onPageFirst.apply(this, Array.prototype.slice.apply(arguments)); - setCookie(this, idsStateSaveList.pageNumber, this.options.pageNumber); + setCookie(this, cookieIds.pageNumber, this.options.pageNumber); }; BootstrapTable.prototype.onPagePre = function () { _onPagePre.apply(this, Array.prototype.slice.apply(arguments)); - setCookie(this, idsStateSaveList.pageNumber, this.options.pageNumber); + setCookie(this, cookieIds.pageNumber, this.options.pageNumber); }; BootstrapTable.prototype.onPageNext = function () { _onPageNext.apply(this, Array.prototype.slice.apply(arguments)); - setCookie(this, idsStateSaveList.pageNumber, this.options.pageNumber); + setCookie(this, cookieIds.pageNumber, this.options.pageNumber); }; BootstrapTable.prototype.onPageLast = function () { _onPageLast.apply(this, Array.prototype.slice.apply(arguments)); - setCookie(this, idsStateSaveList.pageNumber, this.options.pageNumber); + setCookie(this, cookieIds.pageNumber, this.options.pageNumber); }; BootstrapTable.prototype.toggleColumn = function () { @@ -209,19 +302,23 @@ var visibleColumns = []; - $.each(this.options.columns, function (i) { - if (this.visible) { - visibleColumns.push(i); + $.each(this.columns, function (i, column) { + if (column.visible) { + visibleColumns.push(column.field); } }); - setCookie(this, idsStateSaveList.columns, JSON.stringify(visibleColumns)); + setCookie(this, cookieIds.columns, JSON.stringify(visibleColumns)); + }; + + BootstrapTable.prototype.selectPage = function (page) { + _selectPage.apply(this, Array.prototype.slice.apply(arguments)); + setCookie(this, idsStateSaveList.pageNumber, page); }; BootstrapTable.prototype.onSearch = function () { _onSearch.apply(this, Array.prototype.slice.apply(arguments)); - - setCookie(this, idsStateSaveList.searchText, this.searchText); + setCookie(this, cookieIds.searchText, this.searchText); }; BootstrapTable.prototype.deleteCookie = function (cookieName) { @@ -229,6 +326,6 @@ return; } - deleteCookie(idsStateSaveList[cookieName]); + deleteCookie(this.options.cookieIdTable, cookieIds[cookieName], this.options.cookiePath, this.options.cookieDomain); }; })(jQuery); From 68005595967bdee3efbf35cec26154e5b40dc6a8 Mon Sep 17 00:00:00 2001 From: snipe <snipe@snipe.net> Date: Wed, 21 Oct 2015 14:41:00 -0700 Subject: [PATCH 074/120] Fixed dumb braces --- app/views/backend/users/index.blade.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/views/backend/users/index.blade.php b/app/views/backend/users/index.blade.php index 7aab64b339..8795671df3 100755 --- a/app/views/backend/users/index.blade.php +++ b/app/views/backend/users/index.blade.php @@ -98,8 +98,8 @@ <script src="{{ asset('assets/js/extensions/cookie/bootstrap-table-cookie.js') }}"></script> <script src="{{ asset('assets/js/extensions/mobile/bootstrap-table-mobile.js') }}"></script> <script src="{{ asset('assets/js/extensions/export/bootstrap-table-export.js') }}"></script> -<script src="//rawgit.com/kayalshri/tableExport.jquery.plugin/master/tableExport.js') }}"></script> -<script src="//rawgit.com/kayalshri/tableExport.jquery.plugin/master/jquery.base64.js') }}"></script> +<script src="//rawgit.com/kayalshri/tableExport.jquery.plugin/master/tableExport.js"></script> +<script src="//rawgit.com/kayalshri/tableExport.jquery.plugin/master/jquery.base64.js"></script> <script type="text/javascript"> $('#table').bootstrapTable({ classes: 'table table-responsive table-no-bordered', From 27735a88211d4fbe893e76201985c737d61de03f Mon Sep 17 00:00:00 2001 From: snipe <snipe@snipe.net> Date: Wed, 21 Oct 2015 14:48:59 -0700 Subject: [PATCH 075/120] Asset model text search for #1266 --- app/models/Model.php | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/app/models/Model.php b/app/models/Model.php index c30a43316c..23d7297583 100755 --- a/app/models/Model.php +++ b/app/models/Model.php @@ -75,7 +75,7 @@ class Model extends Elegant return $query->whereIn( 'category_id', $categoryIdListing ); } - + /** * Query builder scope to search on text * @@ -87,11 +87,24 @@ class Model extends Elegant public function scopeTextSearch($query, $search) { - return $query->where(function($query) use ($search) - { - $query->where('name', 'LIKE', '%'.$search.'%') - ->orWhere('modelno', 'LIKE', '%'.$search.'%'); - }); + return $query->where('name', 'LIKE', "%$search%") + ->orWhere('modelno', 'LIKE', "%$search%") + ->orWhere(function($query) use ($search) { + $query->whereHas('depreciation', function($query) use ($search) { + $query->where('name','LIKE','%'.$search.'%'); + }); + }) + ->orWhere(function($query) use ($search) { + $query->whereHas('category', function($query) use ($search) { + $query->where('name','LIKE','%'.$search.'%'); + }); + }) + ->orWhere(function($query) use ($search) { + $query->whereHas('manufacturer', function($query) use ($search) { + $query->where('name','LIKE','%'.$search.'%'); + }); + }); + } } From 4e3c19666453b8451d09f047775306b51d69e410 Mon Sep 17 00:00:00 2001 From: snipe <snipe@snipe.net> Date: Wed, 21 Oct 2015 14:49:09 -0700 Subject: [PATCH 076/120] Manager search for #1266 --- app/models/User.php | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/app/models/User.php b/app/models/User.php index 2d99d132fd..c44ebe25bd 100755 --- a/app/models/User.php +++ b/app/models/User.php @@ -80,7 +80,7 @@ class User extends SentryUserModel **/ public function manager() { - return $this->belongsTo('User','manager_id')->withTrashed(); + return $this->hasOne('User','manager_id')->withTrashed(); } @@ -208,17 +208,27 @@ class User extends SentryUserModel * * @return Illuminate\Database\Query\Builder Modified query builder */ - public function scopeTextsearch($query, $q) + public function scopeTextsearch($query, $search) { - return $query->where('first_name', 'LIKE', "%$q%") - ->orWhere('last_name', 'LIKE', "%$q%") - ->orWhere('email', 'LIKE', "%$q%") - ->orWhere('username', 'LIKE', "%$q%") - ->orWhere('notes', 'LIKE', "%$q%") - ->orWhere(function($query) use ($q) { - $query->whereHas('userloc', function($query) use ($q) { - $query->where('name','LIKE','%'.$q.'%'); + return $query->where('first_name', 'LIKE', "%$search%") + ->orWhere('last_name', 'LIKE', "%$search%") + ->orWhere('email', 'LIKE', "%$search%") + ->orWhere('username', 'LIKE', "%$search%") + ->orWhere('notes', 'LIKE', "%$search%") + ->orWhere(function($query) use ($search) { + $query->whereHas('userloc', function($query) use ($search) { + $query->where('name','LIKE','%'.$search.'%'); + }); + }) + + // This doesn't actually work - need to use a table alias maybe? + ->orWhere(function($query) use ($search) { + $query->whereHas('manager', function($query) use ($search) { + $query->where(function($query) use ($search) { + $query->where('first_name','LIKE','%'.$search.'%') + ->orWhere('last_name','LIKE','%'.$search.'%'); + }); }); }); From b25b3321f9dc06fcdf912fefa99d70c4878ab1b6 Mon Sep 17 00:00:00 2001 From: snipe <snipe@snipe.net> Date: Wed, 21 Oct 2015 14:49:24 -0700 Subject: [PATCH 077/120] Fixes skip/offset for #1266 --- app/controllers/admin/ModelsController.php | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/app/controllers/admin/ModelsController.php b/app/controllers/admin/ModelsController.php index 3cc5e3e17d..27faaadfac 100755 --- a/app/controllers/admin/ModelsController.php +++ b/app/controllers/admin/ModelsController.php @@ -373,6 +373,19 @@ class ModelsController extends AdminController $models = $models->TextSearch(Input::get('search')); } + if (Input::has('offset')) { + $offset = e(Input::get('offset')); + } else { + $offset = 0; + } + + if (Input::has('limit')) { + $limit = e(Input::get('limit')); + } else { + $limit = 50; + } + + $allowed_columns = ['name']; $order = Input::get('order') === 'asc' ? 'asc' : 'desc'; $sort = in_array(Input::get('sort'), $allowed_columns) ? Input::get('sort') : 'created_at'; @@ -380,7 +393,7 @@ class ModelsController extends AdminController $models = $models->orderBy($sort, $order); $modelCount = $models->count(); - $models = $models->skip(Input::get('offset'))->take(Input::get('limit'))->get(); + $models = $models->skip($offset)->take($limit)->get(); $rows = array(); From cab5dba7c2f1ec0f7d18af4c375ff7a3f2331d54 Mon Sep 17 00:00:00 2001 From: snipe <snipe@snipe.net> Date: Wed, 21 Oct 2015 14:49:39 -0700 Subject: [PATCH 078/120] Only show manager name if a manager is listed --- app/controllers/admin/UsersController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/admin/UsersController.php b/app/controllers/admin/UsersController.php index 746f68c1b3..6bdc2118c3 100755 --- a/app/controllers/admin/UsersController.php +++ b/app/controllers/admin/UsersController.php @@ -907,7 +907,7 @@ class UsersController extends AdminController { 'email' => ($user->email!='') ? '<span class="hidden-md hidden-lg" style="display: inline !important;"><a href="mailto:'.$user->email.'">'.$user->email.'</a></span> <span class="hidden-xs hidden-sm"><a href="mailto:'.$user->email.'"><i class="fa fa-envelope"></i></a></span>' : '', 'username' => $user->username, 'location' => ($user->location_id!='') ? $user->userloc->name : '', - 'manager' => ($user->manager_id!='') ? '<a title="' . $user->manager->fullName() . '" href="users/' . $user->manager->id . '/view">' . $user->manager->fullName() . '</a>' : '', + 'manager' => ($user->manager) ? '<a title="' . $user->manager->fullName() . '" href="users/' . $user->manager->id . '/view">' . $user->manager->fullName() . '</a>' : '', 'assets' => $user->assets->count(), 'licenses' => $user->licenses->count(), 'accessories' => $user->accessories->count(), From e12e2f2c7cdf71b4d9e8e91ae3159522a2671280 Mon Sep 17 00:00:00 2001 From: snipe <snipe@snipe.net> Date: Wed, 21 Oct 2015 14:49:58 -0700 Subject: [PATCH 079/120] Updated BS tables library --- app/config/version.php | 4 +- .../assets/css/bootstrap/bootstrap-table.css | 37 +- public/assets/js/bootstrap-table.js | 896 ++++++++++++------ .../js/extensions/accent-neutralise/README.md | 17 + .../bootstrap-table-accent-neutralise.js | 182 ++++ .../angular/bootstrap-table-angular.js | 105 ++ public/assets/js/extensions/cookie/README.md | 62 ++ .../cookie/bootstrap-table-cookie.js | 2 +- .../cookie/bootstrap-table-cookie.min.js | 7 - .../assets/js/extensions/editable/README.md | 53 ++ .../editable/bootstrap-table-editable.js | 30 +- .../editable/bootstrap-table-editable.min.js | 7 - public/assets/js/extensions/export/README.md | 35 + .../export/bootstrap-table-export.js | 30 +- .../export/bootstrap-table-export.min.js | 7 - .../js/extensions/filter-control/README.md | 49 + .../bootstrap-table-filter-control.js | 407 +++++--- .../bootstrap-table-filter-control.min.js | 7 - public/assets/js/extensions/filter/README.md | 17 + .../filter/bootstrap-table-filter.js | 2 +- .../filter/bootstrap-table-filter.min.js | 7 - .../assets/js/extensions/flat-json/README.md | 23 + .../flat-json/bootstrap-table-flat-json.js | 94 +- .../bootstrap-table-flat-json.min.js | 7 - .../assets/js/extensions/group-by/README.md | 62 ++ .../group-by/bootstrap-table-group-by.css | 53 ++ .../group-by/bootstrap-table-group-by.js | 243 +++++ .../assets/js/extensions/key-events/README.md | 24 + .../key-events/bootstrap-table-key-events.js | 1 - .../bootstrap-table-key-events.min.js | 7 - public/assets/js/extensions/mobile/README.md | 41 + .../mobile/bootstrap-table-mobile.js | 80 +- .../mobile/bootstrap-table-mobile.min.js | 7 - .../js/extensions/multiple-search/README.md | 17 + .../bootstrap-table-multiple-search.js | 67 ++ .../js/extensions/multiple-sort/README.md | 91 ++ .../bootstrap-table-multiple-sort.js | 116 +-- .../bootstrap-table-multiple-sort.min.js | 7 - .../js/extensions/natural-sorting/README.md | 13 + .../bootstrap-table-natural-sorting.js | 0 .../bootstrap-table-natural-sorting.min.js | 7 - .../js/extensions/reorder-columns/README.md | 41 + .../bootstrap-table-reorder-columns.js | 47 +- .../bootstrap-table-reorder-columns.min.js | 7 - .../js/extensions/reorder-rows/README.md | 74 ++ .../bootstrap-table-reorder-rows.css | 0 .../bootstrap-table-reorder-rows.js | 8 +- .../bootstrap-table-reorder-rows.min.js | 7 - .../assets/js/extensions/resizable/README.md | 66 ++ .../resizable/bootstrap-table-resizable.js | 0 .../bootstrap-table-resizable.min.js | 7 - public/assets/js/extensions/toolbar/README.md | 53 ++ .../toolbar/bootstrap-table-toolbar.js | 74 +- .../toolbar/bootstrap-table-toolbar.min.js | 7 - 54 files changed, 2589 insertions(+), 725 deletions(-) mode change 100644 => 100755 public/assets/css/bootstrap/bootstrap-table.css mode change 100644 => 100755 public/assets/js/bootstrap-table.js create mode 100755 public/assets/js/extensions/accent-neutralise/README.md create mode 100755 public/assets/js/extensions/accent-neutralise/bootstrap-table-accent-neutralise.js create mode 100755 public/assets/js/extensions/angular/bootstrap-table-angular.js create mode 100755 public/assets/js/extensions/cookie/README.md mode change 100644 => 100755 public/assets/js/extensions/cookie/bootstrap-table-cookie.js delete mode 100644 public/assets/js/extensions/cookie/bootstrap-table-cookie.min.js create mode 100755 public/assets/js/extensions/editable/README.md mode change 100644 => 100755 public/assets/js/extensions/editable/bootstrap-table-editable.js delete mode 100644 public/assets/js/extensions/editable/bootstrap-table-editable.min.js create mode 100755 public/assets/js/extensions/export/README.md mode change 100644 => 100755 public/assets/js/extensions/export/bootstrap-table-export.js delete mode 100644 public/assets/js/extensions/export/bootstrap-table-export.min.js create mode 100755 public/assets/js/extensions/filter-control/README.md mode change 100644 => 100755 public/assets/js/extensions/filter-control/bootstrap-table-filter-control.js delete mode 100644 public/assets/js/extensions/filter-control/bootstrap-table-filter-control.min.js create mode 100755 public/assets/js/extensions/filter/README.md mode change 100644 => 100755 public/assets/js/extensions/filter/bootstrap-table-filter.js delete mode 100644 public/assets/js/extensions/filter/bootstrap-table-filter.min.js create mode 100755 public/assets/js/extensions/flat-json/README.md mode change 100644 => 100755 public/assets/js/extensions/flat-json/bootstrap-table-flat-json.js delete mode 100644 public/assets/js/extensions/flat-json/bootstrap-table-flat-json.min.js create mode 100755 public/assets/js/extensions/group-by/README.md create mode 100755 public/assets/js/extensions/group-by/bootstrap-table-group-by.css create mode 100755 public/assets/js/extensions/group-by/bootstrap-table-group-by.js create mode 100755 public/assets/js/extensions/key-events/README.md mode change 100644 => 100755 public/assets/js/extensions/key-events/bootstrap-table-key-events.js delete mode 100644 public/assets/js/extensions/key-events/bootstrap-table-key-events.min.js create mode 100755 public/assets/js/extensions/mobile/README.md mode change 100644 => 100755 public/assets/js/extensions/mobile/bootstrap-table-mobile.js delete mode 100644 public/assets/js/extensions/mobile/bootstrap-table-mobile.min.js create mode 100755 public/assets/js/extensions/multiple-search/README.md create mode 100755 public/assets/js/extensions/multiple-search/bootstrap-table-multiple-search.js create mode 100755 public/assets/js/extensions/multiple-sort/README.md mode change 100644 => 100755 public/assets/js/extensions/multiple-sort/bootstrap-table-multiple-sort.js delete mode 100644 public/assets/js/extensions/multiple-sort/bootstrap-table-multiple-sort.min.js create mode 100755 public/assets/js/extensions/natural-sorting/README.md mode change 100644 => 100755 public/assets/js/extensions/natural-sorting/bootstrap-table-natural-sorting.js delete mode 100644 public/assets/js/extensions/natural-sorting/bootstrap-table-natural-sorting.min.js create mode 100755 public/assets/js/extensions/reorder-columns/README.md mode change 100644 => 100755 public/assets/js/extensions/reorder-columns/bootstrap-table-reorder-columns.js delete mode 100644 public/assets/js/extensions/reorder-columns/bootstrap-table-reorder-columns.min.js create mode 100755 public/assets/js/extensions/reorder-rows/README.md mode change 100644 => 100755 public/assets/js/extensions/reorder-rows/bootstrap-table-reorder-rows.css mode change 100644 => 100755 public/assets/js/extensions/reorder-rows/bootstrap-table-reorder-rows.js delete mode 100644 public/assets/js/extensions/reorder-rows/bootstrap-table-reorder-rows.min.js create mode 100755 public/assets/js/extensions/resizable/README.md mode change 100644 => 100755 public/assets/js/extensions/resizable/bootstrap-table-resizable.js delete mode 100644 public/assets/js/extensions/resizable/bootstrap-table-resizable.min.js create mode 100755 public/assets/js/extensions/toolbar/README.md mode change 100644 => 100755 public/assets/js/extensions/toolbar/bootstrap-table-toolbar.js delete mode 100644 public/assets/js/extensions/toolbar/bootstrap-table-toolbar.min.js diff --git a/app/config/version.php b/app/config/version.php index 73c194b908..49cd88aa75 100644 --- a/app/config/version.php +++ b/app/config/version.php @@ -1,5 +1,5 @@ <?php return array ( - 'app_version' => 'v2.0-254', - 'hash_version' => 'v2.0-254-gcf7571d', + 'app_version' => 'v2.0-261', + 'hash_version' => 'v2.0-261-gb25b332', ); \ No newline at end of file diff --git a/public/assets/css/bootstrap/bootstrap-table.css b/public/assets/css/bootstrap/bootstrap-table.css old mode 100644 new mode 100755 index 981f80d72f..dd589e5d8c --- a/public/assets/css/bootstrap/bootstrap-table.css +++ b/public/assets/css/bootstrap/bootstrap-table.css @@ -40,15 +40,7 @@ .fixed-table-footer, .fixed-table-header { - height: 37px; /*cellHeight*/ overflow: hidden; - border-radius: 4px 4px 0 0; - -webkit-border-radius: 4px 4px 0 0; - -moz-border-radius: 4px 4px 0 0; -} - -.fixed-table-header { - border-bottom: 1px solid #dddddd; } .fixed-table-footer { @@ -79,7 +71,8 @@ -moz-border-radius-topleft: 4px; } -.fixed-table-container thead th .th-inner { +.fixed-table-container thead th .th-inner, +.fixed-table-container tbody td .th-inner { padding: 8px; line-height: 24px; vertical-align: top; @@ -90,12 +83,23 @@ .fixed-table-container thead th .sortable { cursor: pointer; - background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAATCAQAAADYWf5HAAAAkElEQVQoz7X QMQ5AQBCF4dWQSJxC5wwax1Cq1e7BAdxD5SL+Tq/QCM1oNiJidwox0355mXnG/DrEtIQ6azioNZQxI0ykPhTQIwhCR+BmBYtlK7kLJYwWCcJA9M4qdrZrd8pPjZWPtOqdRQy320YSV17OatFC4euts6z39GYMKRPCTKY9UnPQ6P+GtMRfGtPnBCiqhAeJPmkqAAAAAElFTkSuQmCC'); background-position: right; background-repeat: no-repeat; padding-right: 30px; } +.fixed-table-container thead th .both { + background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAATCAQAAADYWf5HAAAAkElEQVQoz7X QMQ5AQBCF4dWQSJxC5wwax1Cq1e7BAdxD5SL+Tq/QCM1oNiJidwox0355mXnG/DrEtIQ6azioNZQxI0ykPhTQIwhCR+BmBYtlK7kLJYwWCcJA9M4qdrZrd8pPjZWPtOqdRQy320YSV17OatFC4euts6z39GYMKRPCTKY9UnPQ6P+GtMRfGtPnBCiqhAeJPmkqAAAAAElFTkSuQmCC'); +} + +.fixed-table-container thead th .asc { + background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAATCAYAAAByUDbMAAAAZ0lEQVQ4y2NgGLKgquEuFxBPAGI2ahhWCsS/gDibUoO0gPgxEP8H4ttArEyuQYxAPBdqEAxPBImTY5gjEL9DM+wTENuQahAvEO9DMwiGdwAxOymGJQLxTyD+jgWDxCMZRsEoGAVoAADeemwtPcZI2wAAAABJRU5ErkJggg=='); +} + +.fixed-table-container thead th .desc { + background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAATCAYAAAByUDbMAAAAZUlEQVQ4y2NgGAWjYBSggaqGu5FA/BOIv2PBIPFEUgxjB+IdQPwfC94HxLykus4GiD+hGfQOiB3J8SojEE9EM2wuSJzcsFMG4ttQgx4DsRalkZENxL+AuJQaMcsGxBOAmGvopk8AVz1sLZgg0bsAAAAASUVORK5CYII= '); +} + .fixed-table-container th.detail { width: 30px; } @@ -254,7 +258,7 @@ .bootstrap-table .table > thead > tr > th { vertical-align: bottom; - border-bottom: 2px solid #ddd; + border-bottom: 1px solid #ddd; } /* support bootstrap 3 */ @@ -263,6 +267,15 @@ margin: 0; } +.bootstrap-table .fixed-table-footer tbody > tr > td { + padding: 0 !important; +} + +.bootstrap-table .fixed-table-footer .table { + border-bottom: none; + border-radius: 0; +} + .pull-right .dropdown-menu { right: 0; left: auto; @@ -281,4 +294,4 @@ div.fixed-table-scroll-outer { width: 200px; height: 150px; overflow: hidden; -} +} \ No newline at end of file diff --git a/public/assets/js/bootstrap-table.js b/public/assets/js/bootstrap-table.js old mode 100644 new mode 100755 index 918045e4bb..6525f29443 --- a/public/assets/js/bootstrap-table.js +++ b/public/assets/js/bootstrap-table.js @@ -1,6 +1,6 @@ /** * @author zhixin wen <wenzhixin2010@gmail.com> - * version: 1.8.1 + * version: 1.9.0 * https://github.com/wenzhixin/bootstrap-table/ */ @@ -10,19 +10,7 @@ // TOOLS DEFINITION // ====================== - var cellHeight = 37, // update css if changed - cachedWidth = null, - arrowAsc = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAATCAYAAAByUDbMAAAAZ' + - '0lEQVQ4y2NgGLKgquEuFxBPAGI2ahhWCsS/gDibUoO0gPgxEP8H4ttArEyuQYxAPBd' + - 'qEAxPBImTY5gjEL9DM+wTENuQahAvEO9DMwiGdwAxOymGJQLxTyD+jgWDxCMZRsEoGAVo' + - 'AADeemwtPcZI2wAAAABJRU5ErkJggg==', - arrowBoth = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAATCAQAAADYWf5HAAAAkElEQVQoz7X' + - 'QMQ5AQBCF4dWQSJxC5wwax1Cq1e7BAdxD5SL+Tq/QCM1oNiJidwox0355mXnG/DrEtIQ6azio' + - 'NZQxI0ykPhTQIwhCR+BmBYtlK7kLJYwWCcJA9M4qdrZrd8pPjZWPtOqdRQy320YSV17OatFC4eut' + - 's6z39GYMKRPCTKY9UnPQ6P+GtMRfGtPnBCiqhAeJPmkqAAAAAElFTkSuQmCC', - arrowDesc = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAATCAYAAAByUDbMAAAAZUlEQVQ4y2NgGAWj' + - 'YBSggaqGu5FA/BOIv2PBIPFEUgxjB+IdQPwfC94HxLykus4GiD+hGfQOiB3J8SojEE9EM2wuSJ' + - 'zcsFMG4ttQgx4DsRalkZENxL+AuJQaMcsGxBOAmGvopk8AVz1sLZgg0bsAAAAASUVORK5CYII= '; + var cachedWidth = null; // it only does '%s', and return '' when arguments are undefined var sprintf = function (str) { @@ -67,6 +55,48 @@ return index; }; + // http://jsfiddle.net/wenyi/47nz7ez9/3/ + var setFieldIndex = function (columns) { + var i, j, k, + totalCol = 0, + flag = []; + + for (i = 0; i < columns[0].length; i++) { + totalCol += columns[0][i].colspan || 1; + } + + for (i = 0; i < columns.length; i++) { + flag[i] = []; + for (j = 0; j < totalCol; j++) { + flag[i][j] = false; + } + } + + for (i = 0; i < columns.length; i++) { + for (j = 0; j < columns[i].length; j++) { + var r = columns[i][j], + rowspan = r.rowspan || 1, + colspan = r.colspan || 1, + index = $.inArray(false, flag[i]); + + if (colspan === 1) { + r.fieldIndex = index; + // when field is undefined, use index instead + if (typeof r.field === 'undefined') { + r.field = index; + } + } + + for (k = 0; k < rowspan; k++) { + flag[i + k][index] = true; + } + for (k = 0; k < colspan; k++) { + flag[i][index + k] = true; + } + } + } + }; + var getScrollBarWidth = function () { if (cachedWidth === null) { var inner = $('<p/>').addClass('fixed-table-scroll-inner'), @@ -118,6 +148,35 @@ return defaultValue; }; + var compareObjects = function (objectA, objectB, compareLength) { + // Create arrays of property names + var objectAProperties = Object.getOwnPropertyNames(objectA), + objectBProperties = Object.getOwnPropertyNames(objectB), + propName = ''; + + if (compareLength) { + // If number of properties is different, objects are not equivalent + if (objectAProperties.length !== objectBProperties.length) { + return false; + } + } + + for (var i = 0; i < objectAProperties.length; i++) { + propName = objectAProperties[i]; + + // If the property is not in the object B properties, continue with the next property + if ($.inArray(propName, objectBProperties) > -1) { + // If values of same property are not equal, objects are not equivalent + if (objectA[propName] !== objectB[propName]) { + return false; + } + } + } + + // If we made it this far, objects are considered equivalent + return true; + }; + var escapeHTML = function (text) { if (typeof text === 'string') { return text @@ -152,6 +211,19 @@ return dataAttr; }; + var getItemField = function (item, field) { + var value = item; + + if (typeof field !== 'string' || item.hasOwnProperty(field)) { + return item[field]; + } + var props = field.split('.'); + for (var p in props) { + value = value[props[p]]; + } + return value; + }; + // BOOTSTRAP TABLE CLASS DEFINITION // ====================== @@ -167,13 +239,15 @@ BootstrapTable.DEFAULTS = { classes: 'table table-hover', + locale: undefined, height: undefined, undefinedText: '-', sortName: undefined, sortOrder: 'asc', striped: false, - columns: [], + columns: [[]], data: [], + dataField: 'rows', method: 'get', url: undefined, ajax: undefined, @@ -202,6 +276,7 @@ paginationNextText: '›', paginationLastText: '»', search: false, + strictSearch: false, searchAlign: 'right', selectItemName: 'btSelectItem', showHeader: true, @@ -227,6 +302,7 @@ toolbarAlign: 'left', checkboxHeader: true, sortable: true, + silentSort: true, maintainSelected: false, searchTimeOut: 500, searchText: '', @@ -237,7 +313,9 @@ paginationSwitchUp: 'glyphicon-collapse-up icon-chevron-up', refresh: 'glyphicon-refresh icon-refresh', toggle: 'glyphicon-list-alt icon-list-alt', - columns: 'glyphicon-th icon-th' + columns: 'glyphicon-th icon-th', + detailOpen: 'glyphicon-plus icon-plus', + detailClose: 'glyphicon-minus icon-minus' }, rowStyle: function (row, index) { @@ -278,10 +356,10 @@ onUncheckAll: function (rows) { return false; }, - onCheckSome: function(rows){ + onCheckSome: function (rows) { return false; }, - onUncheckSome: function(rows){ + onUncheckSome: function (rows) { return false; }, onLoadSuccess: function (data) { @@ -316,12 +394,18 @@ }, onCollapseRow: function (index, row) { return false; + }, + onRefreshOptions: function (options) { + return false; + }, + onResetView: function () { + return false; } }; BootstrapTable.LOCALES = []; - BootstrapTable.LOCALES['en-US'] = { + BootstrapTable.LOCALES['en-US'] = BootstrapTable.LOCALES['en'] = { formatLoadingMessage: function () { return 'Loading, please wait...'; }, @@ -362,6 +446,7 @@ checkboxEnabled: true, field: undefined, title: undefined, + titleTooltip: undefined, 'class': undefined, align: undefined, // left, right, center halign: undefined, // left, right, center @@ -380,6 +465,7 @@ sortName: undefined, cellStyle: undefined, searchable: true, + searchFormatter: true, cardVisible: true }; @@ -406,10 +492,13 @@ 'post-body.bs.table': 'onPostBody', 'post-header.bs.table': 'onPostHeader', 'expand-row.bs.table': 'onExpandRow', - 'collapse-row.bs.table': 'onCollapseRow' + 'collapse-row.bs.table': 'onCollapseRow', + 'refresh-options.bs.table': 'onRefreshOptions', + 'reset-view.bs.table': 'onResetView' }; BootstrapTable.prototype.init = function () { + this.initLocale(); this.initContainer(); this.initTable(); this.initHeader(); @@ -418,9 +507,28 @@ this.initToolbar(); this.initPagination(); this.initBody(); + this.initSearchText(); this.initServer(); }; + BootstrapTable.prototype.initLocale = function () { + if (this.options.locale) { + var parts = this.options.locale.split(/-|_/); + parts[0].toLowerCase(); + parts[1] && parts[1].toUpperCase(); + if ($.fn.bootstrapTable.locales[this.options.locale]) { + // locale as requested + $.extend(this.options, $.fn.bootstrapTable.locales[this.options.locale]); + } else if ($.fn.bootstrapTable.locales[parts.join('-')]) { + // locale with sep set to - (in case original was specified with _) + $.extend(this.options, $.fn.bootstrapTable.locales[parts.join('-')]); + } else if ($.fn.bootstrapTable.locales[parts[0]]) { + // short locale language code (i.e. 'en') + $.extend(this.options, $.fn.bootstrapTable.locales[parts[0]]); + } + } + }; + BootstrapTable.prototype.initContainer = function () { this.$container = $([ '<div class="bootstrap-table">', @@ -440,7 +548,8 @@ '<div class="fixed-table-pagination"></div>' : '', '</div>', - '</div>'].join('')); + '</div>' + ].join('')); this.$container.insertAfter(this.$el); this.$tableContainer = this.$container.find('.fixed-table-container'); @@ -468,25 +577,41 @@ columns = [], data = []; - this.$header = this.$el.find('thead'); + this.$header = this.$el.find('>thead'); if (!this.$header.length) { this.$header = $('<thead></thead>').appendTo(this.$el); } - if (!this.$header.find('tr').length) { - this.$header.append('<tr></tr>'); - } - this.$header.find('th').each(function () { - var column = $.extend({}, { - title: $(this).html(), - 'class': $(this).attr('class') - }, $(this).data()); + this.$header.find('tr').each(function () { + var column = []; + $(this).find('th').each(function () { + column.push($.extend({}, { + title: $(this).html(), + 'class': $(this).attr('class'), + titleTooltip: $(this).attr('title'), + rowspan: $(this).attr('rowspan') ? +$(this).attr('rowspan') : undefined, + colspan: $(this).attr('colspan') ? +$(this).attr('colspan') : undefined + }, $(this).data())); + }); columns.push(column); }); + if (!$.isArray(this.options.columns[0])) { + this.options.columns = [this.options.columns]; + } this.options.columns = $.extend(true, [], columns, this.options.columns); - $.each(this.options.columns, function (i, column) { - that.options.columns[i] = $.extend({}, BootstrapTable.COLUMN_DEFAULTS, - {field: i}, column); // when field is undefined, use index instead + this.columns = []; + + setFieldIndex(this.options.columns); + $.each(this.options.columns, function (i, columns) { + $.each(columns, function (j, column) { + column = $.extend({}, BootstrapTable.COLUMN_DEFAULTS, column); + + if (typeof column.fieldIndex !== 'undefined') { + that.columns[column.fieldIndex] = column; + } + + that.options.columns[i][j] = column; + }); }); // if options.data is setting, do not process tbody data @@ -494,7 +619,7 @@ return; } - this.$el.find('tbody tr').each(function () { + this.$el.find('>tbody>tr').each(function () { var row = {}; // save tr's id, class and data-* attributes @@ -503,13 +628,14 @@ row._data = getRealDataAttr($(this).data()); $(this).find('td').each(function (i) { - var field = that.options.columns[i].field; + var field = that.columns[i].field; row[field] = $(this).html(); // save td's id, class and data-* attributes row['_' + field + '_id'] = $(this).attr('id'); row['_' + field + '_class'] = $(this).attr('class'); row['_' + field + '_rowspan'] = $(this).attr('rowspan'); + row['_' + field + '_title'] = $(this).attr('title'); row['_' + field + '_data'] = getRealDataAttr($(this).data()); }); data.push(row); @@ -519,9 +645,8 @@ BootstrapTable.prototype.initHeader = function () { var that = this, - visibleColumns = [], - html = [], - timeoutId = 0; + visibleColumns = {}, + html = []; this.header = { fields: [], @@ -532,100 +657,106 @@ sorters: [], sortNames: [], cellStyles: [], - clickToSelects: [], searchables: [] }; - if (!this.options.cardView && this.options.detailView) { - html.push('<th class="detail"><div class="fht-cell"></div></th>'); - visibleColumns.push({}); - } + $.each(this.options.columns, function (i, columns) { + html.push('<tr>'); - $.each(this.options.columns, function (i, column) { - var text = '', - halign = '', // header align style - align = '', // body align style - style = '', - class_ = sprintf(' class="%s"', column['class']), - order = that.options.sortOrder || column.order, - unitWidth = 'px', - width = column.width; - - if (!column.visible) { - // Fix #229. Default Sort order is wrong - // if data-visible="false" is set on the field referenced by data-sort-name. - if (column.field === that.options.sortName) { - that.header.fields.push(column.field); - } - return; + if (i == 0 && !that.options.cardView && that.options.detailView) { + html.push(sprintf('<th class="detail" rowspan="%s"><div class="fht-cell"></div></th>', + that.options.columns.length)); } - if (that.options.cardView && (!column.cardVisible)) { - return; - } + $.each(columns, function (j, column) { + var text = '', + halign = '', // header align style + align = '', // body align style + style = '', + class_ = sprintf(' class="%s"', column['class']), + order = that.options.sortOrder || column.order, + unitWidth = 'px', + width = column.width; - if (column.width !== undefined && (!that.options.cardView)) { - if (typeof column.width === 'string') { - if (column.width.indexOf('%') !== -1) { - unitWidth = '%'; + if (column.width !== undefined && (!that.options.cardView)) { + if (typeof column.width === 'string') { + if (column.width.indexOf('%') !== -1) { + unitWidth = '%'; + } } } - } - if (column.width && typeof column.width === 'string') { - width = column.width.replace('%', '').replace('px', ''); - } - - halign = sprintf('text-align: %s; ', column.halign ? column.halign : column.align); - align = sprintf('text-align: %s; ', column.align); - style = sprintf('vertical-align: %s; ', column.valign); - style += sprintf('width: %s%s; ', column.checkbox || column.radio ? 36 : width, unitWidth); - - visibleColumns.push(column); - that.header.fields.push(column.field); - that.header.styles.push(align + style); - that.header.classes.push(class_); - that.header.formatters.push(column.formatter); - that.header.events.push(column.events); - that.header.sorters.push(column.sorter); - that.header.sortNames.push(column.sortName); - that.header.cellStyles.push(column.cellStyle); - that.header.clickToSelects.push(column.clickToSelect); - that.header.searchables.push(column.searchable); - - html.push('<th', - column.checkbox || column.radio ? - sprintf(' class="bs-checkbox %s"', column['class'] || '') : - class_, - sprintf(' style="%s"', halign + style), - '>'); - - html.push(sprintf('<div class="th-inner %s">', that.options.sortable && column.sortable ? - 'sortable' : '')); - - text = column.title; - - if (column.checkbox) { - if (!that.options.singleSelect && that.options.checkboxHeader) { - text = '<input name="btSelectAll" type="checkbox" />'; + if (column.width && typeof column.width === 'string') { + width = column.width.replace('%', '').replace('px', ''); } - that.header.stateField = column.field; - } - if (column.radio) { - text = ''; - that.header.stateField = column.field; - that.options.singleSelect = true; - } - html.push(text); - html.push('</div>'); - html.push('<div class="fht-cell"></div>'); - html.push('</div>'); - html.push('</th>'); + halign = sprintf('text-align: %s; ', column.halign ? column.halign : column.align); + align = sprintf('text-align: %s; ', column.align); + style = sprintf('vertical-align: %s; ', column.valign); + style += sprintf('width: %s; ', (column.checkbox || column.radio) && !width ? + '36px' : (width ? width + unitWidth : undefined)); + + if (typeof column.fieldIndex !== 'undefined') { + that.header.fields[column.fieldIndex] = column.field; + that.header.styles[column.fieldIndex] = align + style; + that.header.classes[column.fieldIndex] = class_; + that.header.formatters[column.fieldIndex] = column.formatter; + that.header.events[column.fieldIndex] = column.events; + that.header.sorters[column.fieldIndex] = column.sorter; + that.header.sortNames[column.fieldIndex] = column.sortName; + that.header.cellStyles[column.fieldIndex] = column.cellStyle; + that.header.searchables[column.fieldIndex] = column.searchable; + + if (!column.visible) { + return; + } + + if (that.options.cardView && (!column.cardVisible)) { + return; + } + + visibleColumns[column.field] = column; + } + + html.push('<th' + sprintf(' title="%s"', column.titleTooltip), + column.checkbox || column.radio ? + sprintf(' class="bs-checkbox %s"', column['class'] || '') : + class_, + sprintf(' style="%s"', halign + style), + sprintf(' rowspan="%s"', column.rowspan), + sprintf(' colspan="%s"', column.colspan), + sprintf(' data-field="%s"', column.field), + "tabindex='0'", + '>'); + + html.push(sprintf('<div class="th-inner %s">', that.options.sortable && column.sortable ? + 'sortable both' : '')); + + text = column.title; + + if (column.checkbox) { + if (!that.options.singleSelect && that.options.checkboxHeader) { + text = '<input name="btSelectAll" type="checkbox" />'; + } + that.header.stateField = column.field; + } + if (column.radio) { + text = ''; + that.header.stateField = column.field; + that.options.singleSelect = true; + } + + html.push(text); + html.push('</div>'); + html.push('<div class="fht-cell"></div>'); + html.push('</div>'); + html.push('</th>'); + }); + html.push('</tr>'); }); - this.$header.find('tr').html(html.join('')); - this.$header.find('th').each(function (i) { - $(this).data(visibleColumns[i]); + this.$header.html(html.join('')); + this.$header.find('th[data-field]').each(function (i) { + $(this).data(visibleColumns[$(this).data('field')]); }); this.$container.off('click', '.th-inner').on('click', '.th-inner', function (event) { if (that.options.sortable && $(this).parent().data().sortable) { @@ -633,6 +764,15 @@ } }); + this.$header.children().children().off('keypress').on('keypress', function (event) { + if (that.options.sortable && $(this).data().sortable) { + var code = event.keyCode || event.which; + if (code == 13) { //Enter keycode + that.onSort(event); + } + } + }); + if (!this.options.showHeader || this.options.cardView) { this.$header.hide(); this.$tableHeader.hide(); @@ -640,9 +780,9 @@ } else { this.$header.show(); this.$tableHeader.show(); - this.$tableLoading.css('top', cellHeight + 'px'); + this.$tableLoading.css('top', this.$header.outerHeight() + 1); // Assign the correct sortable arrow - this.getCaretHtml(); + this.getCaret(); } this.$selectAll = this.$header.find('[name="btSelectAll"]'); @@ -700,8 +840,8 @@ if (that.header.sortNames[index]) { name = that.header.sortNames[index]; } - var aa = a[name], - bb = b[name], + var aa = getItemField(a, name), + bb = getItemField(b, name), value = calculateObjectValue(that.header, that.header.sorters[index], [aa, bb]); if (value !== undefined) { @@ -746,7 +886,7 @@ }; BootstrapTable.prototype.onSort = function (event) { - var $this = $(event.currentTarget).parent(), + var $this = event.type === "keypress" ? $(event.currentTarget) : $(event.currentTarget).parent(), $this_ = this.$header.find('th').eq($this.index()); this.$header.add(this.$header_).find('span.order').remove(); @@ -762,10 +902,10 @@ $this.add($this_).data('order', this.options.sortOrder); // Assign the correct sortable arrow - this.getCaretHtml(); + this.getCaret(); if (this.options.sidePagination === 'server') { - this.initServer(); + this.initServer(this.options.silentSort); return; } @@ -783,7 +923,7 @@ this.$toolbar.html(''); - if (typeof this.options.toolbar === 'string') { + if (typeof this.options.toolbar === 'string' || typeof this.options.toolbar === 'object') { $(sprintf('<div class="bars pull-%s"></div>', this.options.toolbarAlign)) .appendTo(this.$toolbar) .append($(this.options.toolbar)); @@ -799,35 +939,35 @@ if (this.options.showPaginationSwitch) { html.push(sprintf('<button class="btn btn-default" type="button" name="paginationSwitch" title="%s">', - this.options.formatPaginationSwitch()), + this.options.formatPaginationSwitch()), sprintf('<i class="%s %s"></i>', this.options.iconsPrefix, this.options.icons.paginationSwitchDown), '</button>'); } if (this.options.showRefresh) { html.push(sprintf('<button class="btn btn-default' + (this.options.iconSize === undefined ? '' : ' btn-' + this.options.iconSize) + '" type="button" name="refresh" title="%s">', - this.options.formatRefresh()), + this.options.formatRefresh()), sprintf('<i class="%s %s"></i>', this.options.iconsPrefix, this.options.icons.refresh), '</button>'); } if (this.options.showToggle) { html.push(sprintf('<button class="btn btn-default' + (this.options.iconSize === undefined ? '' : ' btn-' + this.options.iconSize) + '" type="button" name="toggle" title="%s">', - this.options.formatToggle()), + this.options.formatToggle()), sprintf('<i class="%s %s"></i>', this.options.iconsPrefix, this.options.icons.toggle), '</button>'); } if (this.options.showColumns) { html.push(sprintf('<div class="keep-open btn-group" title="%s">', - this.options.formatColumns()), + this.options.formatColumns()), '<button type="button" class="btn btn-default' + (this.options.iconSize == undefined ? '' : ' btn-' + this.options.iconSize) + ' dropdown-toggle" data-toggle="dropdown">', sprintf('<i class="%s %s"></i>', this.options.iconsPrefix, this.options.icons.columns), ' <span class="caret"></span>', '</button>', '<ul class="dropdown-menu" role="menu">'); - $.each(this.options.columns, function (i, column) { + $.each(this.columns, function (i, column) { if (column.radio || column.checkbox) { return; } @@ -886,7 +1026,8 @@ $keepOpen.find('input').off('click').on('click', function () { var $this = $(this); - that.toggleColumn(getFieldIndex(that.options.columns, $(this).data('field')), $this.prop('checked'), false); + that.toggleColumn(getFieldIndex(that.columns, + $(this).data('field')), $this.prop('checked'), false); that.trigger('column-switch', $(this).data('field'), $this.prop('checked')); }); } @@ -907,14 +1048,6 @@ that.onSearch(event); }, that.options.searchTimeOut); }); - - if (this.options.searchText !== '') { - $search.val(this.options.searchText); - clearTimeout(timeoutId); // doesn't matter if it's 0 - timeoutId = setTimeout(function () { - $search.trigger('keyup'); - }, that.options.searchTimeOut); - } } }; @@ -958,20 +1091,26 @@ for (var key in item) { key = $.isNumeric(key) ? parseInt(key, 10) : key; var value = item[key], - column = that.options.columns[getFieldIndex(that.options.columns, key)], + column = that.columns[getFieldIndex(that.columns, key)], j = $.inArray(key, that.header.fields); // Fix #142: search use formated data - value = calculateObjectValue(column, - that.header.formatters[j], - [value, item, i], value); + if (column && column.searchFormatter) { + value = calculateObjectValue(column, + that.header.formatters[j], [value, item, i], value); + } var index = $.inArray(key, that.header.fields); - if (index !== -1 && that.header.searchables[index] && - (typeof value === 'string' || - typeof value === 'number') && - (value + '').toLowerCase().indexOf(s) !== -1) { - return true; + if (index !== -1 && that.header.searchables[index] && (typeof value === 'string' || typeof value === 'number')) { + if (that.options.strictSearch) { + if ((value + '').toLowerCase() === s) { + return true; + } + } else { + if ((value + '').toLowerCase().indexOf(s) !== -1) { + return true; + } + } } } return false; @@ -1007,10 +1146,11 @@ this.options.pageSize = this.options.totalRows; $allSelected = true; } else if (this.options.pageSize === this.options.totalRows) { - // Fix #667 Table with pagination, multiple pages and a search that matches to one page throws exception + // Fix #667 Table with pagination, + // multiple pages and a search that matches to one page throws exception var pageLst = typeof this.options.pageList === 'string' ? - this.options.pageList.replace('[', '').replace(']', '').replace(/ /g, '').toLowerCase().split(',') : - this.options.pageList; + this.options.pageList.replace('[', '').replace(']', '') + .replace(/ /g, '').toLowerCase().split(',') : this.options.pageList; if (pageLst.indexOf(this.options.formatAllRows().toLowerCase()) > -1) { $allSelected = true; } @@ -1039,19 +1179,24 @@ html.push('<span class="page-list">'); var pageNumber = [ - sprintf('<span class="btn-group %s">', this.options.paginationVAlign === 'top' || this.options.paginationVAlign === 'both' ? - 'dropdown' : 'dropup'), - '<button type="button" class="btn btn-default ' + (this.options.iconSize === undefined ? '' : ' btn-' + this.options.iconSize) + ' dropdown-toggle" data-toggle="dropdown">', + sprintf('<span class="btn-group %s">', + this.options.paginationVAlign === 'top' || this.options.paginationVAlign === 'both' ? + 'dropdown' : 'dropup'), + '<button type="button" class="btn btn-default ' + + (this.options.iconSize === undefined ? '' : ' btn-' + this.options.iconSize) + + ' dropdown-toggle" data-toggle="dropdown">', '<span class="page-size">', $allSelected ? this.options.formatAllRows() : this.options.pageSize, '</span>', ' <span class="caret"></span>', '</button>', - '<ul class="dropdown-menu" role="menu">'], + '<ul class="dropdown-menu" role="menu">' + ], pageList = this.options.pageList; if (typeof this.options.pageList === 'string') { - var list = this.options.pageList.replace('[', '').replace(']', '').replace(/ /g, '').split(','); + var list = this.options.pageList.replace('[', '').replace(']', '') + .replace(/ /g, '').split(','); pageList = []; $.each(list, function (i, value) { @@ -1214,7 +1359,7 @@ this.trigger('pre-body', data); - this.$body = this.$el.find('tbody'); + this.$body = this.$el.find('>tbody'); if (!this.$body.length) { this.$body = $('<tbody></tbody>').appendTo(this.$el); } @@ -1279,21 +1424,26 @@ if (!this.options.cardView && this.options.detailView) { html.push('<td>', '<a class="detail-icon" href="javascript:">', - '<i class="glyphicon glyphicon-plus icon-plus"></i>', + sprintf('<i class="%s %s"></i>', this.options.iconsPrefix, this.options.icons.detailOpen), '</a>', '</td>'); } $.each(this.header.fields, function (j, field) { var text = '', - value = item[field], + value = getItemField(item, field), type = '', cellStyle = {}, id_ = '', class_ = that.header.classes[j], data_ = '', rowspan_ = '', - column = that.options.columns[getFieldIndex(that.options.columns, field)]; + title_ = '', + column = that.columns[getFieldIndex(that.columns, field)]; + + if (!column.visible) { + return; + } style = sprintf('style="%s"', csses.concat(that.header.styles[j]).join('; ')); @@ -1310,6 +1460,9 @@ if (item['_' + field + '_rowspan']) { rowspan_ = sprintf(' rowspan="%s"', item['_' + field + '_rowspan']); } + if (item['_' + field + '_title']) { + title_ = sprintf(' title="%s"', item['_' + field + '_title']); + } cellStyle = calculateObjectValue(that.header, that.header.cellStyles[j], [value, item, i], cellStyle); if (cellStyle.classes) { @@ -1340,31 +1493,33 @@ text = [that.options.cardView ? '<div class="card-view">' : '<td class="bs-checkbox">', '<input' + - sprintf(' data-index="%s"', i) + - sprintf(' name="%s"', that.options.selectItemName) + - sprintf(' type="%s"', type) + - sprintf(' value="%s"', item[that.options.idField]) + - sprintf(' checked="%s"', value === true || - (value && value.checked) ? 'checked' : undefined) + - sprintf(' disabled="%s"', !column.checkboxEnabled || - (value && value.disabled) ? 'disabled' : undefined) + - ' />', - that.options.cardView ? '</div>' : '</td>'].join(''); + sprintf(' data-index="%s"', i) + + sprintf(' name="%s"', that.options.selectItemName) + + sprintf(' type="%s"', type) + + sprintf(' value="%s"', item[that.options.idField]) + + sprintf(' checked="%s"', value === true || + (value && value.checked) ? 'checked' : undefined) + + sprintf(' disabled="%s"', !column.checkboxEnabled || + (value && value.disabled) ? 'disabled' : undefined) + + ' />', + that.header.formatters[j] && typeof value === 'string' ? value : '', + that.options.cardView ? '</div>' : '</td>' + ].join(''); item[that.header.stateField] = value === true || (value && value.checked); } else { value = typeof value === 'undefined' || value === null ? that.options.undefinedText : value; - text = that.options.cardView ? - ['<div class="card-view">', - that.options.showHeader ? sprintf('<span class="title" %s>%s</span>', style, - getPropertyFromOther(that.options.columns, 'field', 'title', field)) : '', - sprintf('<span class="value">%s</span>', value), - '</div>'].join('') : - [sprintf('<td%s %s %s %s %s>', id_, class_, style, data_, rowspan_), - value, - '</td>'].join(''); + text = that.options.cardView ? ['<div class="card-view">', + that.options.showHeader ? sprintf('<span class="title" %s>%s</span>', style, + getPropertyFromOther(that.columns, 'field', 'title', field)) : '', + sprintf('<span class="value">%s</span>', value), + '</div>' + ].join('') : [sprintf('<td%s %s %s %s %s %s>', id_, class_, style, data_, rowspan_, title_), + value, + '</td>' + ].join(''); // Hide empty data on Card view when smartDisplay is set to true. if (that.options.cardView && that.options.smartDisplay && value === '') { @@ -1397,49 +1552,44 @@ } // click to select by column - this.$body.find('> tr > td').off('click').on('click', function () { + this.$body.find('> tr[data-index] > td').off('click dblclick').on('click dblclick', function (e) { var $td = $(this), $tr = $td.parent(), item = that.data[$tr.data('index')], - cellIndex = $td[0].cellIndex, - $headerCell = that.$header.find('th:eq(' + cellIndex + ')'), - field = $headerCell.data('field'), - value = item[field]; - that.trigger('click-cell', field, value, item, $td); - that.trigger('click-row', item, $tr); + index = $td[0].cellIndex, + field = that.header.fields[that.options.detailView && !that.options.cardView ? index - 1 : index], + column = that.columns[getFieldIndex(that.columns, field)], + value = getItemField(item, field); + + if ($td.find('.detail-icon').length) { + return; + } + + that.trigger(e.type === 'click' ? 'click-cell' : 'dbl-click-cell', field, value, item, $td); + that.trigger(e.type === 'click' ? 'click-row' : 'dbl-click-row', item, $tr); + // if click to select - then trigger the checkbox/radio click - if (that.options.clickToSelect) { - if (that.header.clickToSelects[$tr.children().index($(this))]) { - $tr.find(sprintf('[name="%s"]', - that.options.selectItemName))[0].click(); // #144: .trigger('click') bug + if (e.type === 'click' && that.options.clickToSelect && column.clickToSelect) { + var $selectItem = $tr.find(sprintf('[name="%s"]', that.options.selectItemName)); + if ($selectItem.length) { + $selectItem[0].click(); // #144: .trigger('click') bug } } }); - this.$body.find('> tr > td').off('dblclick').on('dblclick', function () { - var $td = $(this), - $tr = $td.parent(), - item = that.data[$tr.data('index')], - cellIndex = $td[0].cellIndex, - $headerCell = that.$header.find('th:eq(' + cellIndex + ')'), - field = $headerCell.data('field'), - value = item[field]; - that.trigger('dbl-click-cell', field, value, item, $td); - that.trigger('dbl-click-row', item, $tr); - }); - this.$body.find('> tr > td > .detail-icon').off('click').on('click', function () { + this.$body.find('> tr[data-index] > td > .detail-icon').off('click').on('click', function () { var $this = $(this), $tr = $this.parent().parent(), index = $tr.data('index'), - row = that.options.data[index]; + row = data[index]; // Fix #980 Detail view, when searching, returns wrong row // remove and update if ($tr.next().is('tr.detail-view')) { - $this.find('i').attr('class', 'glyphicon glyphicon-plus icon-plus'); + $this.find('i').attr('class', sprintf('%s %s', that.options.iconsPrefix, that.options.icons.detailOpen)); $tr.next().remove(); that.trigger('collapse-row', index, row); } else { - $this.find('i').attr('class', 'glyphicon glyphicon-minus icon-minus'); + $this.find('i').attr('class', sprintf('%s %s', that.options.iconsPrefix, that.options.icons.detailClose)); $tr.after(sprintf('<tr class="detail-view"><td colspan="%s">%s</td></tr>', $tr.find('td').length, calculateObjectValue(that.options, that.options.detailFormatter, [index, row], ''))); @@ -1452,8 +1602,15 @@ this.$selectItem.off('click').on('click', function (event) { event.stopImmediatePropagation(); - var checked = $(this).prop('checked'), - row = that.data[$(this).data('index')]; + var $this = $(this), + checked = $this.prop('checked'), + row = that.data[$this.data('index')]; + + if (that.options.maintainSelected && $(this).is(':radio')) { + $.each(that.options.data, function (i, row) { + row[that.header.stateField] = false; + }); + } row[that.header.stateField] = checked; @@ -1465,7 +1622,7 @@ } that.updateSelected(); - that.trigger(checked ? 'check' : 'uncheck', row); + that.trigger(checked ? 'check' : 'uncheck', row, $this); }); $.each(this.header.events, function (i, events) { @@ -1476,13 +1633,18 @@ if (typeof events === 'string') { events = calculateObjectValue(null, events); } - if (!that.options.cardView && that.options.detailView) { - i += 1; + + var field = that.header.fields[i], + fieldIndex = $.inArray(field, that.getVisibleFields()); + + if (that.options.detailView && !that.options.cardView) { + fieldIndex += 1; } + for (var key in events) { - that.$body.find('tr').each(function () { + that.$body.find('>tr').each(function () { var $tr = $(this), - $td = $tr.find(that.options.cardView ? '.card-view' : 'td').eq(i), + $td = $tr.find(that.options.cardView ? '.card-view' : 'td').eq(fieldIndex), index = key.indexOf(' '), name = key.substring(0, index), el = key.substring(index + 1), @@ -1491,7 +1653,7 @@ $td.find(el).off(name).on(name, function (e) { var index = $tr.data('index'), row = that.data[index], - value = row[that.header.fields[i]]; + value = row[field]; func.apply(this, [e, value, row, index]); }); @@ -1567,7 +1729,7 @@ that.trigger('load-success', res); }, error: function (res) { - that.trigger('load-error', res.status); + that.trigger('load-error', res.status, res); }, complete: function () { if (!silent) { @@ -1583,26 +1745,33 @@ } }; - BootstrapTable.prototype.getCaretHtml = function () { + BootstrapTable.prototype.initSearchText = function () { + if (this.options.search) { + if (this.options.searchText !== '') { + var $search = this.$toolbar.find('.search input'); + $search.val(this.options.searchText); + this.onSearch({currentTarget: $search}); + } + } + }; + + BootstrapTable.prototype.getCaret = function () { var that = this; $.each(this.$header.find('th'), function (i, th) { - if ($(th).data('field') === that.options.sortName) { - $(th).find('.sortable').css('background-image', 'url(' + (that.options.sortOrder === 'desc' ? arrowDesc : arrowAsc) + ')'); - } else { - $(th).find('.sortable').css('background-image', 'url(' + arrowBoth +')'); - } + $(th).find('.sortable').removeClass('desc asc').addClass($(th).data('field') === that.options.sortName ? that.options.sortOrder : 'both'); }); }; BootstrapTable.prototype.updateSelected = function () { - var checkAll = this.$selectItem.filter(':enabled').length === + var checkAll = this.$selectItem.filter(':enabled').length && + this.$selectItem.filter(':enabled').length === this.$selectItem.filter(':enabled').filter(':checked').length; this.$selectAll.add(this.$selectAll_).prop('checked', checkAll); this.$selectItem.each(function () { - $(this).parents('tr')[$(this).prop('checked') ? 'addClass' : 'removeClass']('selected'); + $(this).closest('tr')[$(this).prop('checked') ? 'addClass' : 'removeClass']('selected'); }); }; @@ -1620,7 +1789,9 @@ $.each(this.data, function (i, row) { that.$selectAll.prop('checked', false); that.$selectItem.prop('checked', false); - row[that.header.stateField] = false; + if (that.header.stateField) { + row[that.header.stateField] = false; + } }); }; @@ -1645,39 +1816,80 @@ BootstrapTable.prototype.fitHeader = function () { var that = this, fixedBody, - scrollWidth; + scrollWidth, + focused, + focusedTemp; if (that.$el.is(':hidden')) { - that.timeoutFooter_ = setTimeout($.proxy(that.fitHeader, that), 100); + that.timeoutId_ = setTimeout($.proxy(that.fitHeader, that), 100); return; } fixedBody = this.$tableBody.get(0); scrollWidth = fixedBody.scrollWidth > fixedBody.clientWidth && - fixedBody.scrollHeight > fixedBody.clientHeight + this.$header.height() ? + fixedBody.scrollHeight > fixedBody.clientHeight + this.$header.outerHeight() ? getScrollBarWidth() : 0; - this.$el.css('margin-top', -this.$header.height()); + this.$el.css('margin-top', -this.$header.outerHeight()); + + focused = $(':focus'); + if (focused.length > 0) { + var $th = focused.parents('th'); + if ($th.length > 0) { + var dataField = $th.attr('data-field'); + if (dataField !== undefined) { + var $headerTh = this.$header.find("[data-field='" + dataField + "']"); + if ($headerTh.length > 0) { + $headerTh.find(":input").addClass("focus-temp"); + } + } + } + } + this.$header_ = this.$header.clone(true, true); this.$selectAll_ = this.$header_.find('[name="btSelectAll"]'); this.$tableHeader.css({ 'margin-right': scrollWidth - }).find('table').css('width', this.$el.css('width')) + }).find('table').css('width', this.$el.outerWidth()) .html('').attr('class', this.$el.attr('class')) .append(this.$header_); + + focusedTemp = $('.focus-temp:visible:eq(0)'); + if (focusedTemp.length > 0) { + focusedTemp.focus(); + this.$header.find('.focus-temp').removeClass('focus-temp'); + } + // fix bug: $.data() is not working as expected after $.append() - this.$header.find('th').each(function (i) { - that.$header_.find('th').eq(i).data($(this).data()); + this.$header.find('th[data-field]').each(function (i) { + that.$header_.find(sprintf('th[data-field="%s"]', $(this).data('field'))).data($(this).data()); }); - this.$body.find('tr:first-child:not(.no-records-found) > *').each(function (i) { - that.$header_.find('div.fht-cell').eq(i).width($(this).innerWidth()); + var visibleFields = this.getVisibleFields(); + + this.$body.find('>tr:first-child:not(.no-records-found) > *').each(function (i) { + var $this = $(this), + index = i; + + if (that.options.detailView && !that.options.cardView) { + if (i === 0) { + that.$header_.find('th.detail').find('.fht-cell').width($this.innerWidth()); + } + index = i - 1; + } + + that.$header_.find(sprintf('th[data-field="%s"]', visibleFields[index])) + .find('.fht-cell').width($this.innerWidth()); }); // horizontal scroll event // TODO: it's probably better improving the layout than binding to scroll event this.$tableBody.off('scroll').on('scroll', function () { that.$tableHeader.scrollLeft($(this).scrollLeft()); + + if (that.options.showFooter && !that.options.cardView) { + that.$tableFooter.scrollLeft($(this).scrollLeft()); + } }); that.trigger('post-header'); }; @@ -1692,10 +1904,10 @@ } if (!this.options.cardView && this.options.detailView) { - html.push('<td></td>'); + html.push('<td><div class="th-inner"> </div><div class="fht-cell"></div></td>'); } - $.each(this.options.columns, function (i, column) { + $.each(this.columns, function (i, column) { var falign = '', // footer align style style = '', class_ = sprintf(' class="%s"', column['class']); @@ -1712,8 +1924,13 @@ style = sprintf('vertical-align: %s; ', column.valign); html.push('<td', class_, sprintf(' style="%s"', falign + style), '>'); + html.push('<div class="th-inner">'); html.push(calculateObjectValue(column, column.footerFormatter, [data], ' ') || ' '); + + html.push('</div>'); + html.push('<div class="fht-cell"></div>'); + html.push('</div>'); html.push('</td>'); }); @@ -1745,8 +1962,10 @@ $footerTd = this.$tableFooter.find('td'); - this.$tableBody.find('tbody tr:first-child:not(.no-records-found) > td').each(function (i) { - $footerTd.eq(i).outerWidth($(this).outerWidth()); + this.$body.find('>tr:first-child:not(.no-records-found) > *').each(function (i) { + var $this = $(this); + + $footerTd.eq(i).find('.fht-cell').width($this.innerWidth()); }); }; @@ -1754,7 +1973,7 @@ if (index === -1) { return; } - this.options.columns[index].visible = checked; + this.columns[index].visible = checked; this.initHeader(); this.initSearch(); this.initPagination(); @@ -1773,15 +1992,32 @@ } }; - BootstrapTable.prototype.toggleRow = function (index, isIdField, visible) { + BootstrapTable.prototype.toggleRow = function (index, uniqueId, visible) { if (index === -1) { return; } - $(this.$body[0]).children().filter(sprintf(isIdField ? '[data-uniqueid="%s"]' : '[data-index="%s"]', index)) + this.$body.find(typeof index !== 'undefined' ? + sprintf('tr[data-index="%s"]', index) : + sprintf('tr[data-uniqueid="%s"]', uniqueId)) [visible ? 'show' : 'hide'](); }; + BootstrapTable.prototype.getVisibleFields = function () { + var that = this, + visibleFields = []; + + $.each(this.header.fields, function (j, field) { + var column = that.columns[getFieldIndex(that.columns, field)]; + + if (!column.visible) { + return; + } + visibleFields.push(field); + }); + return visibleFields; + }; + // PUBLIC FUNCTION DEFINITION // ======================= @@ -1813,7 +2049,7 @@ if (this.options.showHeader && this.options.height) { this.$tableHeader.show(); this.resetHeader(); - padding += cellHeight; + padding += this.$header.outerHeight(); } else { this.$tableHeader.hide(); this.trigger('post-header'); @@ -1822,23 +2058,20 @@ if (this.options.showFooter) { this.resetFooter(); if (this.options.height) { - padding += cellHeight; + padding += this.$tableFooter.outerHeight() + 1; } } // Assign the correct sortable arrow - this.getCaretHtml(); + this.getCaret(); this.$tableContainer.css('padding-bottom', padding + 'px'); + this.trigger('reset-view'); }; BootstrapTable.prototype.getData = function (useCurrentPage) { - return (this.searchText - || !$.isEmptyObject(this.filterColumns) - || !$.isEmptyObject(this.filterColumnsPartial)) ? - (useCurrentPage ? this.data.slice(this.pageFrom -1, this.pageTo) - : this.data) : - (useCurrentPage ? this.options.data.slice(this.pageFrom - 1, this.pageTo) - : this.options.data); + return (this.searchText || !$.isEmptyObject(this.filterColumns) || !$.isEmptyObject(this.filterColumnsPartial)) ? + (useCurrentPage ? this.data.slice(this.pageFrom - 1, this.pageTo) : this.data) : + (useCurrentPage ? this.options.data.slice(this.pageFrom - 1, this.pageTo) : this.options.data); }; BootstrapTable.prototype.load = function (data) { @@ -1848,7 +2081,7 @@ if (this.options.sidePagination === 'server') { this.options.totalRows = data.total; fixedScroll = data.fixedScroll; - data = data.rows; + data = data[this.options.dataField]; } else if (!$.isArray(data)) { // support fixedScroll fixedScroll = data.fixedScroll; data = data.data; @@ -1911,9 +2144,10 @@ } }; - BootstrapTable.prototype.removeByUniqueId = function (id) { + BootstrapTable.prototype.getRowByUniqueId = function (id) { var uniqueId = this.options.uniqueId, len = this.options.data.length, + dataRow = null, i, row; for (i = len - 1; i >= 0; i--) { @@ -1934,10 +2168,22 @@ } if (row[uniqueId] === id) { - this.options.data.splice(i, 1); + dataRow = row; + break; } } + return dataRow; + }; + + BootstrapTable.prototype.removeByUniqueId = function (id) { + var len = this.options.data.length, + row = this.getRowByUniqueId(id); + + if (row) { + this.options.data.splice(this.options.data.indexOf(row), 1); + } + if (len === this.options.data.length) { return; } @@ -1968,19 +2214,17 @@ }; BootstrapTable.prototype.showRow = function (params) { - if (!params.hasOwnProperty('index')) { + if (!params.hasOwnProperty('index') || !params.hasOwnProperty('uniqueId')) { return; } - - this.toggleRow(params.index, params.isIdField === undefined ? false : true, true); + this.toggleRow(params.index, params.uniqueId, true); }; BootstrapTable.prototype.hideRow = function (params) { - if (!params.hasOwnProperty('index')) { + if (!params.hasOwnProperty('index') || !params.hasOwnProperty('uniqueId')) { return; } - - this.toggleRow(params.index, params.isIdField === undefined ? false : true, false); + this.toggleRow(params.index, params.uniqueId, false); }; BootstrapTable.prototype.getRowsHidden = function (show) { @@ -1996,17 +2240,18 @@ BootstrapTable.prototype.mergeCells = function (options) { var row = options.index, - col = $.inArray(options.field, this.header.fields), + col = $.inArray(options.field, this.getVisibleFields()), rowspan = options.rowspan || 1, colspan = options.colspan || 1, i, j, - $tr = this.$body.find('tr'), - $td = $tr.eq(row).find('td').eq(col); + $tr = this.$body.find('>tr'), + $td; - if (!this.options.cardView && this.options.detailView) { + if (this.options.detailView && !this.options.cardView) { col += 1; } - $td = $tr.eq(row).find('td').eq(col); + + $td = $tr.eq(row).find('>td').eq(col); if (row < 0 || col < 0 || row >= this.data.length) { return; @@ -2014,7 +2259,7 @@ for (i = row; i < row + rowspan; i++) { for (j = col; j < col + colspan; j++) { - $tr.eq(i).find('td').eq(j).hide(); + $tr.eq(i).find('>td').eq(j).hide(); } } @@ -2022,10 +2267,12 @@ }; BootstrapTable.prototype.updateCell = function (params) { - if (!params.hasOwnProperty('rowIndex') || !params.hasOwnProperty('fieldName') || !params.hasOwnProperty('fieldValue')) { + if (!params.hasOwnProperty('index') || + !params.hasOwnProperty('field') || + !params.hasOwnProperty('value')) { return; } - this.data[params.rowIndex][params.fieldName] = params.fieldValue; + this.data[params.index][params.field] = params.value; this.initSort(); this.initBody(true); }; @@ -2063,9 +2310,9 @@ if (!checked) { rows = this.getSelections(); } + this.$selectAll.add(this.$selectAll_).prop('checked', checked); this.$selectItem.filter(':enabled').prop('checked', checked); this.updateRows(); - this.updateSelected(); if (checked) { rows = this.getSelections(); } @@ -2107,7 +2354,8 @@ return false; } if ($.inArray(row[obj.field], obj.values) !== -1) { - that.$selectItem.filter(sprintf('[data-index="%s"]', index)).prop('checked', checked); + that.$selectItem.filter(':enabled') + .filter(sprintf('[data-index="%s"]', index)).prop('checked', checked); row[that.header.stateField] = checked; rows.push(row); that.trigger(checked ? 'check' : 'uncheck', row); @@ -2164,11 +2412,17 @@ }; BootstrapTable.prototype.showColumn = function (field) { - this.toggleColumn(getFieldIndex(this.options.columns, field), true, true); + this.toggleColumn(getFieldIndex(this.columns, field), true, true); }; BootstrapTable.prototype.hideColumn = function (field) { - this.toggleColumn(getFieldIndex(this.options.columns, field), false, true); + this.toggleColumn(getFieldIndex(this.columns, field), false, true); + }; + + BootstrapTable.prototype.getHiddenColumns = function () { + return $.grep(this.columns, function (column) { + return !column.visible; + }); }; BootstrapTable.prototype.filterBy = function (columns) { @@ -2192,7 +2446,7 @@ BootstrapTable.prototype.getScrollPosition = function () { return this.scrollTo(); - } + }; BootstrapTable.prototype.selectPage = function (page) { if (page > 0 && page <= this.options.totalPages) { @@ -2224,6 +2478,87 @@ this.trigger('toggle', this.options.cardView); }; + BootstrapTable.prototype.refreshOptions = function (options) { + //If the objects are equivalent then avoid the call of destroy / init methods + if (compareObjects(this.options, options, false)) { + return; + } + this.options = $.extend(this.options, options); + this.trigger('refresh-options', this.options); + this.destroy(); + this.init(); + }; + + BootstrapTable.prototype.resetSearch = function (text) { + var $search = this.$toolbar.find('.search input'); + $search.val(text || ''); + this.onSearch({currentTarget: $search}); + }; + + BootstrapTable.prototype.expandRow_ = function (expand, index) { + var $tr = this.$body.find(sprintf('> tr[data-index="%s"]', index)); + if ($tr.next().is('tr.detail-view') === (expand ? false : true)) { + $tr.find('> td > .detail-icon').click(); + } + }; + + BootstrapTable.prototype.expandRow = function (index) { + this.expandRow_(true, index); + }; + + BootstrapTable.prototype.collapseRow = function (index) { + this.expandRow_(false, index); + }; + + BootstrapTable.prototype.expandAllRows = function (isSubTable) { + if (isSubTable) { + var $tr = this.$body.find(sprintf('> tr[data-index="%s"]', 0)), + that = this, + detailIcon = null, + executeInterval = false, + idInterval = -1; + + if (!$tr.next().is('tr.detail-view')) { + $tr.find('> td > .detail-icon').click(); + executeInterval = true; + } else if (!$tr.next().next().is('tr.detail-view')) { + $tr.next().find(".detail-icon").click(); + executeInterval = true; + } + + if (executeInterval) { + try { + idInterval = setInterval(function () { + detailIcon = that.$body.find("tr.detail-view").last().find(".detail-icon"); + if (detailIcon.length > 0) { + detailIcon.click(); + } else { + clearInterval(idInterval); + } + }, 1); + } catch (ex) { + clearInterval(idInterval); + } + } + } else { + var trs = this.$body.children(); + for (var i = 0; i < trs.length; i++) { + this.expandRow_(true, $(trs[i]).data("index")); + } + } + }; + + BootstrapTable.prototype.collapseAllRows = function (isSubTable) { + if (isSubTable) { + this.expandRow_(false, 0); + } else { + var trs = this.$body.children(); + for (var i = 0; i < trs.length; i++) { + this.expandRow_(false, $(trs[i]).data("index")); + } + } + }; + // BOOTSTRAP TABLE PLUGIN DEFINITION // ======================= @@ -2232,7 +2567,7 @@ 'getSelections', 'getAllSelections', 'getData', 'load', 'append', 'prepend', 'remove', 'removeAll', 'insertRow', 'updateRow', 'updateCell', 'removeByUniqueId', - 'showRow', 'hideRow', 'getRowsHidden', + 'getRowByUniqueId', 'showRow', 'hideRow', 'getRowsHidden', 'mergeCells', 'checkAll', 'uncheckAll', 'check', 'uncheck', @@ -2242,13 +2577,16 @@ 'resetWidth', 'destroy', 'showLoading', 'hideLoading', - 'showColumn', 'hideColumn', + 'showColumn', 'hideColumn', 'getHiddenColumns', 'filterBy', 'scrollTo', 'getScrollPosition', 'selectPage', 'prevPage', 'nextPage', 'togglePagination', - 'toggleView' + 'toggleView', + 'refreshOptions', + 'resetSearch', + 'expandRow', 'collapseRow', 'expandAllRows', 'collapseAllRows' ]; $.fn.bootstrapTable = function (option) { @@ -2290,6 +2628,12 @@ $.fn.bootstrapTable.columnDefaults = BootstrapTable.COLUMN_DEFAULTS; $.fn.bootstrapTable.locales = BootstrapTable.LOCALES; $.fn.bootstrapTable.methods = allowedMethods; + $.fn.bootstrapTable.utils = { + sprintf: sprintf, + getFieldIndex: getFieldIndex, + compareObjects: compareObjects, + calculateObjectValue: calculateObjectValue + }; // BOOTSTRAP TABLE INIT // ======================= diff --git a/public/assets/js/extensions/accent-neutralise/README.md b/public/assets/js/extensions/accent-neutralise/README.md new file mode 100755 index 0000000000..c2f3d09500 --- /dev/null +++ b/public/assets/js/extensions/accent-neutralise/README.md @@ -0,0 +1,17 @@ +# Table Accent Neutralise + +Use Plugin: [bootstrap-table-accent-neutralise](https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/accent-neutralise) + +## Usage + +```html +<script src="extensions/multiple-search/bootstrap-table-accent-neutralise.js"></script> +``` + +## Options + +### searchAccentNeutralise + +* type: Boolean +* description: Set to true if you want to use accent neutralise feature. +* default: `false` diff --git a/public/assets/js/extensions/accent-neutralise/bootstrap-table-accent-neutralise.js b/public/assets/js/extensions/accent-neutralise/bootstrap-table-accent-neutralise.js new file mode 100755 index 0000000000..dc7b4f08fc --- /dev/null +++ b/public/assets/js/extensions/accent-neutralise/bootstrap-table-accent-neutralise.js @@ -0,0 +1,182 @@ +/** + * @author: Dennis Hernández + * @webSite: http://djhvscf.github.io/Blog + * @version: v1.0.0 + */ + +!function ($) { + + 'use strict'; + + var diacriticsMap = {}; + var defaultAccentsDiacritics = [ + {'base':'A', 'letters':'\u0041\u24B6\uFF21\u00C0\u00C1\u00C2\u1EA6\u1EA4\u1EAA\u1EA8\u00C3\u0100\u0102\u1EB0\u1EAE\u1EB4\u1EB2\u0226\u01E0\u00C4\u01DE\u1EA2\u00C5\u01FA\u01CD\u0200\u0202\u1EA0\u1EAC\u1EB6\u1E00\u0104\u023A\u2C6F'}, + {'base':'AA','letters':'\uA732'}, + {'base':'AE','letters':'\u00C6\u01FC\u01E2'}, + {'base':'AO','letters':'\uA734'}, + {'base':'AU','letters':'\uA736'}, + {'base':'AV','letters':'\uA738\uA73A'}, + {'base':'AY','letters':'\uA73C'}, + {'base':'B', 'letters':'\u0042\u24B7\uFF22\u1E02\u1E04\u1E06\u0243\u0182\u0181'}, + {'base':'C', 'letters':'\u0043\u24B8\uFF23\u0106\u0108\u010A\u010C\u00C7\u1E08\u0187\u023B\uA73E'}, + {'base':'D', 'letters':'\u0044\u24B9\uFF24\u1E0A\u010E\u1E0C\u1E10\u1E12\u1E0E\u0110\u018B\u018A\u0189\uA779'}, + {'base':'DZ','letters':'\u01F1\u01C4'}, + {'base':'Dz','letters':'\u01F2\u01C5'}, + {'base':'E', 'letters':'\u0045\u24BA\uFF25\u00C8\u00C9\u00CA\u1EC0\u1EBE\u1EC4\u1EC2\u1EBC\u0112\u1E14\u1E16\u0114\u0116\u00CB\u1EBA\u011A\u0204\u0206\u1EB8\u1EC6\u0228\u1E1C\u0118\u1E18\u1E1A\u0190\u018E'}, + {'base':'F', 'letters':'\u0046\u24BB\uFF26\u1E1E\u0191\uA77B'}, + {'base':'G', 'letters':'\u0047\u24BC\uFF27\u01F4\u011C\u1E20\u011E\u0120\u01E6\u0122\u01E4\u0193\uA7A0\uA77D\uA77E'}, + {'base':'H', 'letters':'\u0048\u24BD\uFF28\u0124\u1E22\u1E26\u021E\u1E24\u1E28\u1E2A\u0126\u2C67\u2C75\uA78D'}, + {'base':'I', 'letters':'\u0049\u24BE\uFF29\u00CC\u00CD\u00CE\u0128\u012A\u012C\u0130\u00CF\u1E2E\u1EC8\u01CF\u0208\u020A\u1ECA\u012E\u1E2C\u0197'}, + {'base':'J', 'letters':'\u004A\u24BF\uFF2A\u0134\u0248'}, + {'base':'K', 'letters':'\u004B\u24C0\uFF2B\u1E30\u01E8\u1E32\u0136\u1E34\u0198\u2C69\uA740\uA742\uA744\uA7A2'}, + {'base':'L', 'letters':'\u004C\u24C1\uFF2C\u013F\u0139\u013D\u1E36\u1E38\u013B\u1E3C\u1E3A\u0141\u023D\u2C62\u2C60\uA748\uA746\uA780'}, + {'base':'LJ','letters':'\u01C7'}, + {'base':'Lj','letters':'\u01C8'}, + {'base':'M', 'letters':'\u004D\u24C2\uFF2D\u1E3E\u1E40\u1E42\u2C6E\u019C'}, + {'base':'N', 'letters':'\u004E\u24C3\uFF2E\u01F8\u0143\u00D1\u1E44\u0147\u1E46\u0145\u1E4A\u1E48\u0220\u019D\uA790\uA7A4'}, + {'base':'NJ','letters':'\u01CA'}, + {'base':'Nj','letters':'\u01CB'}, + {'base':'O', 'letters':'\u004F\u24C4\uFF2F\u00D2\u00D3\u00D4\u1ED2\u1ED0\u1ED6\u1ED4\u00D5\u1E4C\u022C\u1E4E\u014C\u1E50\u1E52\u014E\u022E\u0230\u00D6\u022A\u1ECE\u0150\u01D1\u020C\u020E\u01A0\u1EDC\u1EDA\u1EE0\u1EDE\u1EE2\u1ECC\u1ED8\u01EA\u01EC\u00D8\u01FE\u0186\u019F\uA74A\uA74C'}, + {'base':'OI','letters':'\u01A2'}, + {'base':'OO','letters':'\uA74E'}, + {'base':'OU','letters':'\u0222'}, + {'base':'OE','letters':'\u008C\u0152'}, + {'base':'oe','letters':'\u009C\u0153'}, + {'base':'P', 'letters':'\u0050\u24C5\uFF30\u1E54\u1E56\u01A4\u2C63\uA750\uA752\uA754'}, + {'base':'Q', 'letters':'\u0051\u24C6\uFF31\uA756\uA758\u024A'}, + {'base':'R', 'letters':'\u0052\u24C7\uFF32\u0154\u1E58\u0158\u0210\u0212\u1E5A\u1E5C\u0156\u1E5E\u024C\u2C64\uA75A\uA7A6\uA782'}, + {'base':'S', 'letters':'\u0053\u24C8\uFF33\u1E9E\u015A\u1E64\u015C\u1E60\u0160\u1E66\u1E62\u1E68\u0218\u015E\u2C7E\uA7A8\uA784'}, + {'base':'T', 'letters':'\u0054\u24C9\uFF34\u1E6A\u0164\u1E6C\u021A\u0162\u1E70\u1E6E\u0166\u01AC\u01AE\u023E\uA786'}, + {'base':'TZ','letters':'\uA728'}, + {'base':'U', 'letters':'\u0055\u24CA\uFF35\u00D9\u00DA\u00DB\u0168\u1E78\u016A\u1E7A\u016C\u00DC\u01DB\u01D7\u01D5\u01D9\u1EE6\u016E\u0170\u01D3\u0214\u0216\u01AF\u1EEA\u1EE8\u1EEE\u1EEC\u1EF0\u1EE4\u1E72\u0172\u1E76\u1E74\u0244'}, + {'base':'V', 'letters':'\u0056\u24CB\uFF36\u1E7C\u1E7E\u01B2\uA75E\u0245'}, + {'base':'VY','letters':'\uA760'}, + {'base':'W', 'letters':'\u0057\u24CC\uFF37\u1E80\u1E82\u0174\u1E86\u1E84\u1E88\u2C72'}, + {'base':'X', 'letters':'\u0058\u24CD\uFF38\u1E8A\u1E8C'}, + {'base':'Y', 'letters':'\u0059\u24CE\uFF39\u1EF2\u00DD\u0176\u1EF8\u0232\u1E8E\u0178\u1EF6\u1EF4\u01B3\u024E\u1EFE'}, + {'base':'Z', 'letters':'\u005A\u24CF\uFF3A\u0179\u1E90\u017B\u017D\u1E92\u1E94\u01B5\u0224\u2C7F\u2C6B\uA762'}, + {'base':'a', 'letters':'\u0061\u24D0\uFF41\u1E9A\u00E0\u00E1\u00E2\u1EA7\u1EA5\u1EAB\u1EA9\u00E3\u0101\u0103\u1EB1\u1EAF\u1EB5\u1EB3\u0227\u01E1\u00E4\u01DF\u1EA3\u00E5\u01FB\u01CE\u0201\u0203\u1EA1\u1EAD\u1EB7\u1E01\u0105\u2C65\u0250'}, + {'base':'aa','letters':'\uA733'}, + {'base':'ae','letters':'\u00E6\u01FD\u01E3'}, + {'base':'ao','letters':'\uA735'}, + {'base':'au','letters':'\uA737'}, + {'base':'av','letters':'\uA739\uA73B'}, + {'base':'ay','letters':'\uA73D'}, + {'base':'b', 'letters':'\u0062\u24D1\uFF42\u1E03\u1E05\u1E07\u0180\u0183\u0253'}, + {'base':'c', 'letters':'\u0063\u24D2\uFF43\u0107\u0109\u010B\u010D\u00E7\u1E09\u0188\u023C\uA73F\u2184'}, + {'base':'d', 'letters':'\u0064\u24D3\uFF44\u1E0B\u010F\u1E0D\u1E11\u1E13\u1E0F\u0111\u018C\u0256\u0257\uA77A'}, + {'base':'dz','letters':'\u01F3\u01C6'}, + {'base':'e', 'letters':'\u0065\u24D4\uFF45\u00E8\u00E9\u00EA\u1EC1\u1EBF\u1EC5\u1EC3\u1EBD\u0113\u1E15\u1E17\u0115\u0117\u00EB\u1EBB\u011B\u0205\u0207\u1EB9\u1EC7\u0229\u1E1D\u0119\u1E19\u1E1B\u0247\u025B\u01DD'}, + {'base':'f', 'letters':'\u0066\u24D5\uFF46\u1E1F\u0192\uA77C'}, + {'base':'g', 'letters':'\u0067\u24D6\uFF47\u01F5\u011D\u1E21\u011F\u0121\u01E7\u0123\u01E5\u0260\uA7A1\u1D79\uA77F'}, + {'base':'h', 'letters':'\u0068\u24D7\uFF48\u0125\u1E23\u1E27\u021F\u1E25\u1E29\u1E2B\u1E96\u0127\u2C68\u2C76\u0265'}, + {'base':'hv','letters':'\u0195'}, + {'base':'i', 'letters':'\u0069\u24D8\uFF49\u00EC\u00ED\u00EE\u0129\u012B\u012D\u00EF\u1E2F\u1EC9\u01D0\u0209\u020B\u1ECB\u012F\u1E2D\u0268\u0131'}, + {'base':'j', 'letters':'\u006A\u24D9\uFF4A\u0135\u01F0\u0249'}, + {'base':'k', 'letters':'\u006B\u24DA\uFF4B\u1E31\u01E9\u1E33\u0137\u1E35\u0199\u2C6A\uA741\uA743\uA745\uA7A3'}, + {'base':'l', 'letters':'\u006C\u24DB\uFF4C\u0140\u013A\u013E\u1E37\u1E39\u013C\u1E3D\u1E3B\u017F\u0142\u019A\u026B\u2C61\uA749\uA781\uA747'}, + {'base':'lj','letters':'\u01C9'}, + {'base':'m', 'letters':'\u006D\u24DC\uFF4D\u1E3F\u1E41\u1E43\u0271\u026F'}, + {'base':'n', 'letters':'\u006E\u24DD\uFF4E\u01F9\u0144\u00F1\u1E45\u0148\u1E47\u0146\u1E4B\u1E49\u019E\u0272\u0149\uA791\uA7A5'}, + {'base':'nj','letters':'\u01CC'}, + {'base':'o', 'letters':'\u006F\u24DE\uFF4F\u00F2\u00F3\u00F4\u1ED3\u1ED1\u1ED7\u1ED5\u00F5\u1E4D\u022D\u1E4F\u014D\u1E51\u1E53\u014F\u022F\u0231\u00F6\u022B\u1ECF\u0151\u01D2\u020D\u020F\u01A1\u1EDD\u1EDB\u1EE1\u1EDF\u1EE3\u1ECD\u1ED9\u01EB\u01ED\u00F8\u01FF\u0254\uA74B\uA74D\u0275'}, + {'base':'oi','letters':'\u01A3'}, + {'base':'ou','letters':'\u0223'}, + {'base':'oo','letters':'\uA74F'}, + {'base':'p','letters':'\u0070\u24DF\uFF50\u1E55\u1E57\u01A5\u1D7D\uA751\uA753\uA755'}, + {'base':'q','letters':'\u0071\u24E0\uFF51\u024B\uA757\uA759'}, + {'base':'r','letters':'\u0072\u24E1\uFF52\u0155\u1E59\u0159\u0211\u0213\u1E5B\u1E5D\u0157\u1E5F\u024D\u027D\uA75B\uA7A7\uA783'}, + {'base':'s','letters':'\u0073\u24E2\uFF53\u00DF\u015B\u1E65\u015D\u1E61\u0161\u1E67\u1E63\u1E69\u0219\u015F\u023F\uA7A9\uA785\u1E9B'}, + {'base':'t','letters':'\u0074\u24E3\uFF54\u1E6B\u1E97\u0165\u1E6D\u021B\u0163\u1E71\u1E6F\u0167\u01AD\u0288\u2C66\uA787'}, + {'base':'tz','letters':'\uA729'}, + {'base':'u','letters': '\u0075\u24E4\uFF55\u00F9\u00FA\u00FB\u0169\u1E79\u016B\u1E7B\u016D\u00FC\u01DC\u01D8\u01D6\u01DA\u1EE7\u016F\u0171\u01D4\u0215\u0217\u01B0\u1EEB\u1EE9\u1EEF\u1EED\u1EF1\u1EE5\u1E73\u0173\u1E77\u1E75\u0289'}, + {'base':'v','letters':'\u0076\u24E5\uFF56\u1E7D\u1E7F\u028B\uA75F\u028C'}, + {'base':'vy','letters':'\uA761'}, + {'base':'w','letters':'\u0077\u24E6\uFF57\u1E81\u1E83\u0175\u1E87\u1E85\u1E98\u1E89\u2C73'}, + {'base':'x','letters':'\u0078\u24E7\uFF58\u1E8B\u1E8D'}, + {'base':'y','letters':'\u0079\u24E8\uFF59\u1EF3\u00FD\u0177\u1EF9\u0233\u1E8F\u00FF\u1EF7\u1E99\u1EF5\u01B4\u024F\u1EFF'}, + {'base':'z','letters':'\u007A\u24E9\uFF5A\u017A\u1E91\u017C\u017E\u1E93\u1E95\u01B6\u0225\u0240\u2C6C\uA763'} + ]; + + var initNeutraliser = function () { + for (var i=0; i < defaultAccentsDiacritics.length; i++){ + var letters = defaultAccentsDiacritics[i].letters; + for (var j=0; j < letters.length ; j++){ + diacriticsMap[letters[j]] = defaultAccentsDiacritics[i].base; + } + } + }; + + var removeDiacritics = function (str) { + return str.replace(/[^\u0000-\u007E]/g, function(a){ + return diacriticsMap[a] || a; + }); + }; + + $.extend($.fn.bootstrapTable.defaults, { + searchAccentNeutralise: false + }); + + var BootstrapTable = $.fn.bootstrapTable.Constructor, + _init = BootstrapTable.prototype.init, + _initSearch = BootstrapTable.prototype.initSearch; + + BootstrapTable.prototype.init = function () { + if (this.options.searchAccentNeutralise) { + initNeutraliser(); + } + _init.apply(this, Array.prototype.slice.apply(arguments)); + }; + + BootstrapTable.prototype.initSearch = function () { + var that = this; + + if (this.options.sidePagination !== 'server') { + var s = this.searchText && this.searchText.toLowerCase(); + var f = $.isEmptyObject(this.filterColumns) ? null : this.filterColumns; + + // Check filter + this.data = f ? $.grep(this.options.data, function (item, i) { + for (var key in f) { + if (item[key] !== f[key]) { + return false; + } + } + return true; + }) : this.options.data; + + this.data = s ? $.grep(this.data, function (item, i) { + for (var key in item) { + key = $.isNumeric(key) ? parseInt(key, 10) : key; + var value = item[key], + column = that.columns[$.fn.bootstrapTable.utils.getFieldIndex(that.columns, key)], + j = $.inArray(key, that.header.fields); + + if (column && column.searchFormatter) { + value = $.fn.bootstrapTable.utils.calculateObjectValue(column, + that.header.formatters[j], [value, item, i], value); + } + + var index = $.inArray(key, that.header.fields); + if (index !== -1 && that.header.searchables[index] && (typeof value === 'string' || typeof value === 'number')) { + if (that.options.searchAccentNeutralise) { + value = removeDiacritics(value); + s = removeDiacritics(s); + } + if (that.options.strictSearch) { + if ((value + '').toLowerCase() === s) { + return true; + } + } else { + if ((value + '').toLowerCase().indexOf(s) !== -1) { + return true; + } + } + } + } + return false; + }) : this.data; + } + }; + +}(jQuery); diff --git a/public/assets/js/extensions/angular/bootstrap-table-angular.js b/public/assets/js/extensions/angular/bootstrap-table-angular.js new file mode 100755 index 0000000000..84c4ed330a --- /dev/null +++ b/public/assets/js/extensions/angular/bootstrap-table-angular.js @@ -0,0 +1,105 @@ +// JavaScript source code +(function () { + if (typeof angular === 'undefined') { + return; + } + angular.module('bsTable', []).directive('bsTableControl', function () { + var CONTAINER_SELECTOR = '.bootstrap-table'; + var SCROLLABLE_SELECTOR = '.fixed-table-body'; + var SEARCH_SELECTOR = '.search input'; + var bsTables = {}; + function getBsTable (el) { + var result; + $.each(bsTables, function (id, bsTable) { + if (!bsTable.$el.closest(CONTAINER_SELECTOR).has(el).length) return; + result = bsTable; + return true; + }); + return result; + } + + $(window).resize(function () { + $.each(bsTables, function (id, bsTable) { + bsTable.$el.bootstrapTable('resetView'); + }); + }); + function onScroll () { + var bsTable = this; + var state = bsTable.$s.bsTableControl.state; + bsTable.$s.$applyAsync(function () { + state.scroll = bsTable.$el.bootstrapTable('getScrollPosition'); + }); + } + $(document) + .on('post-header.bs.table', CONTAINER_SELECTOR+' table', function (evt) { // bootstrap-table calls .off('scroll') in initHeader so reattach here + var bsTable = getBsTable(evt.target); + if (!bsTable) return; + bsTable.$el + .closest(CONTAINER_SELECTOR) + .find(SCROLLABLE_SELECTOR) + .on('scroll', onScroll.bind(bsTable)); + }) + .on('sort.bs.table', CONTAINER_SELECTOR+' table', function (evt, sortName, sortOrder) { + var bsTable = getBsTable(evt.target); + if (!bsTable) return; + var state = bsTable.$s.bsTableControl.state; + bsTable.$s.$applyAsync(function () { + state.sortName = sortName; + state.sortOrder = sortOrder; + }); + }) + .on('page-change.bs.table', CONTAINER_SELECTOR+' table', function (evt, pageNumber, pageSize) { + var bsTable = getBsTable(evt.target); + if (!bsTable) return; + var state = bsTable.$s.bsTableControl.state; + bsTable.$s.$applyAsync(function () { + state.pageNumber = pageNumber; + state.pageSize = pageSize; + }); + }) + .on('search.bs.table', CONTAINER_SELECTOR+' table', function (evt, searchText) { + var bsTable = getBsTable(evt.target); + if (!bsTable) return; + var state = bsTable.$s.bsTableControl.state; + bsTable.$s.$applyAsync(function () { + state.searchText = searchText; + }); + }) + .on('focus blur', CONTAINER_SELECTOR+' '+SEARCH_SELECTOR, function (evt) { + var bsTable = getBsTable(evt.target); + if (!bsTable) return; + var state = bsTable.$s.bsTableControl.state; + bsTable.$s.$applyAsync(function () { + state.searchHasFocus = $(evt.target).is(':focus'); + }); + }); + + return { + restrict: 'EA', + scope: {bsTableControl: '='}, + link: function ($s, $el) { + var bsTable = bsTables[$s.$id] = {$s: $s, $el: $el}; + $s.instantiated = false; + $s.$watch('bsTableControl.options', function (options) { + if (!options) options = $s.bsTableControl.options = {}; + var state = $s.bsTableControl.state || {}; + + if ($s.instantiated) $el.bootstrapTable('destroy'); + $el.bootstrapTable(angular.extend(angular.copy(options), state)); + $s.instantiated = true; + + // Update the UI for state that isn't settable via options + if ('scroll' in state) $el.bootstrapTable('scrollTo', state.scroll); + if ('searchHasFocus' in state) $el.closest(CONTAINER_SELECTOR).find(SEARCH_SELECTOR).focus(); // $el gets detached so have to recompute whole chain + }, true); + $s.$watch('bsTableControl.state', function (state) { + if (!state) state = $s.bsTableControl.state = {}; + $el.trigger('directive-updated.bs.table', [state]); + }, true); + $s.$on('$destroy', function () { + delete bsTables[$s.$id]; + }); + } + }; + }) +})(); diff --git a/public/assets/js/extensions/cookie/README.md b/public/assets/js/extensions/cookie/README.md new file mode 100755 index 0000000000..727affa0a6 --- /dev/null +++ b/public/assets/js/extensions/cookie/README.md @@ -0,0 +1,62 @@ +# Table Cookie + +Use Plugin: [bootstrap-table-cookie](https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/cookie) + +## Usage + +```html +<script src="extensions/cookie/bootstrap-table-cookie.js"></script> +``` + +## Options + +### cookie + +* type: Boolean +* description: Set true to save the state of a table (its paging position, ordering state, records per page). +* default: `false` + +### cookieExpire + +* type: String +* description: You must set this property if cookie option is enable to know when will expire the cookie created. Must use this format: 'number{letter}' like '2h', in the letter position + you can use: 's','mi','h','d','m','y', these means: 'seconds', 'minutes', 'hours', 'days', 'months', 'years'. +* default: `2h` + +### cookiePath + +* type: String +* description: you can tell the browser what path the cookie belongs to. By default, the cookie belongs to the current page. +* default: `null` + +### cookieDomain + +* type: String +* description: This is the website domain, with the www. prefix removed. +* default: `null` + +### cookieSecure + +* type: Boolean +* description: This property keeps cookie communication limited to encrypted transmission, directing browsers to use cookies only via secure/encrypted connections. +* default: `null` + +### cookieIdTable + +* type: String +* description: You must set this property if the cookie property is enabled to set an unique cookie with an identifier for each table in your page or project. You must set this property because we need create cookies with an identifier. +* default: `` + +### cookiesEnabled + +* type: Array +* description: Set this array with the table properties (sortOrder, sortName, pageNumber, pageList, columns, searchText, filterControl) that you want to save +* default: `['bs.table.sortOrder', 'bs.table.sortName', 'bs.table.pageNumber', 'bs.table.pageList', 'bs.table.columns', 'bs.table.searchText', 'bs.table.filterControl']` + +## This plugin saves + +* Sort order +* Page number +* Page number from the list +* Visible columns +* Search text \ No newline at end of file diff --git a/public/assets/js/extensions/cookie/bootstrap-table-cookie.js b/public/assets/js/extensions/cookie/bootstrap-table-cookie.js old mode 100644 new mode 100755 index c1dc348d30..e6f8d5cc4c --- a/public/assets/js/extensions/cookie/bootstrap-table-cookie.js +++ b/public/assets/js/extensions/cookie/bootstrap-table-cookie.js @@ -310,7 +310,7 @@ setCookie(this, cookieIds.columns, JSON.stringify(visibleColumns)); }; - + BootstrapTable.prototype.selectPage = function (page) { _selectPage.apply(this, Array.prototype.slice.apply(arguments)); setCookie(this, idsStateSaveList.pageNumber, page); diff --git a/public/assets/js/extensions/cookie/bootstrap-table-cookie.min.js b/public/assets/js/extensions/cookie/bootstrap-table-cookie.min.js deleted file mode 100644 index 92b7107e0a..0000000000 --- a/public/assets/js/extensions/cookie/bootstrap-table-cookie.min.js +++ /dev/null @@ -1,7 +0,0 @@ -/* -* bootstrap-table - v1.8.1 - 2015-05-29 -* https://github.com/wenzhixin/bootstrap-table -* Copyright (c) 2015 zhixin wen -* Licensed MIT License -*/ -!function(a){"use strict";var b={sortOrder:"bs.table.sortOrder",sortName:"bs.table.sortName",pageNumber:"bs.table.pageNumber",pageList:"bs.table.pageList",columns:"bs.table.columns",searchText:"bs.table.searchText"},c=function(){return navigator.cookieEnabled?!0:!1},d=function(a,b,d,e,f,g){if(a.options.stateSave&&c()&&""!==a.options.stateSaveIdTable){var i=a.options.stateSaveIdTable,j=a.options.stateSaveExpire;return b=i+"."+b,!b||/^(?:expires|max\-age|path|domain|secure)$/i.test(b)?!1:(document.cookie=encodeURIComponent(b)+"="+encodeURIComponent(d)+h(j)+(f?"; domain="+f:"")+(e?"; path="+e:"")+(g?"; secure":""),!0)}},e=function(a,b){return b=a+"."+b,b?decodeURIComponent(document.cookie.replace(new RegExp("(?:(?:^|.*;)\\s*"+encodeURIComponent(b).replace(/[\-\.\+\*]/g,"\\$&")+"\\s*\\=\\s*([^;]*).*$)|^.*$"),"$1"))||null:null},f=function(a){return a?new RegExp("(?:^|;\\s*)"+encodeURIComponent(a).replace(/[\-\.\+\*]/g,"\\$&")+"\\s*\\=").test(document.cookie):!1},g=function(a,b,c,d){return b=a+"."+b,f(b)?(document.cookie=encodeURIComponent(b)+"=; expires=Thu, 01 Jan 1970 00:00:00 GMT"+(d?"; domain="+d:"")+(c?"; path="+c:""),!0):!1},h=function(a){var b=a.replace(/[0-9]/,"");switch(a=a.replace(/[A-Za-z]/,""),b.toLowerCase()){case"s":a=+a;break;case"mi":a=60*a;break;case"h":a=60*a*60;break;case"d":a=24*a*60*60;break;case"m":a=30*a*24*60*60;break;case"y":a=365*a*30*24*60*60;break;default:a=void 0}return void 0===a?"":"; max-age="+a};a.extend(a.fn.bootstrapTable.defaults,{stateSave:!1,stateSaveExpire:"2h",stateSaveIdTable:""}),a.fn.bootstrapTable.methods.push("deleteCookie");var i=a.fn.bootstrapTable.Constructor,j=i.prototype.initTable,k=i.prototype.onSort,l=i.prototype.onPageNumber,m=i.prototype.onPageListChange,n=i.prototype.onPageFirst,o=i.prototype.onPagePre,p=i.prototype.onPageNext,q=i.prototype.onPageLast,r=i.prototype.toggleColumn,s=i.prototype.onSearch;i.prototype.initTable=function(){j.apply(this,Array.prototype.slice.apply(arguments)),this.initStateSave()},i.prototype.initStateSave=function(){if(this.options.stateSave&&c()&&""!==this.options.stateSaveIdTable){var d=e(this.options.stateSaveIdTable,b.sortOrder),f=e(this.options.stateSaveIdTable,b.sortName),g=e(this.options.stateSaveIdTable,b.pageNumber),h=e(this.options.stateSaveIdTable,b.pageList),i=JSON.parse(e(this.options.stateSaveIdTable,b.columns)),j=e(this.options.stateSaveIdTable,b.searchText);d&&(this.options.sortOrder=d,this.options.sortName=f),g&&(this.options.pageNumber=+g),h&&(this.options.pageSize=h===this.options.formatAllRows()?h:+h),i&&a.each(this.options.columns,function(a,b){b.visible=-1!==i.indexOf(a)}),j&&(this.options.searchText=j)}},i.prototype.onSort=function(){k.apply(this,Array.prototype.slice.apply(arguments)),d(this,b.sortOrder,this.options.sortOrder),d(this,b.sortName,this.options.sortName)},i.prototype.onPageNumber=function(){l.apply(this,Array.prototype.slice.apply(arguments)),d(this,b.pageNumber,this.options.pageNumber)},i.prototype.onPageListChange=function(){m.apply(this,Array.prototype.slice.apply(arguments)),d(this,b.pageList,this.options.pageSize)},i.prototype.onPageFirst=function(){n.apply(this,Array.prototype.slice.apply(arguments)),d(this,b.pageNumber,this.options.pageNumber)},i.prototype.onPagePre=function(){o.apply(this,Array.prototype.slice.apply(arguments)),d(this,b.pageNumber,this.options.pageNumber)},i.prototype.onPageNext=function(){p.apply(this,Array.prototype.slice.apply(arguments)),d(this,b.pageNumber,this.options.pageNumber)},i.prototype.onPageLast=function(){q.apply(this,Array.prototype.slice.apply(arguments)),d(this,b.pageNumber,this.options.pageNumber)},i.prototype.toggleColumn=function(){r.apply(this,Array.prototype.slice.apply(arguments));var c=[];a.each(this.options.columns,function(a){this.visible&&c.push(a)}),d(this,b.columns,JSON.stringify(c))},i.prototype.onSearch=function(){s.apply(this,Array.prototype.slice.apply(arguments)),d(this,b.searchText,this.searchText)},i.prototype.deleteCookie=function(a){""!==a&&c()&&g(b[a])}}(jQuery); \ No newline at end of file diff --git a/public/assets/js/extensions/editable/README.md b/public/assets/js/extensions/editable/README.md new file mode 100755 index 0000000000..041a14202e --- /dev/null +++ b/public/assets/js/extensions/editable/README.md @@ -0,0 +1,53 @@ +# Table Editable + +Use Plugin: [x-editable](https://github.com/vitalets/x-editable) + +## Usage + +```html +<script src="extensions/editable/bootstrap-table-editable.js"></script> +``` + +## Options + +### editable + +* type: Boolean +* description: Set false to disabled editable of all columns. +* default: `true` + +## Column options + +### editable + +* type: Object +* description: Configuration of x-editable. Full list of options: http://vitalets.github.io/x-editable/docs.html#editable +* default: `undefined` + +## Events + +### onEditableInit(editable-init.bs.table) + +Fired when all columns was initialized by `$().editable()` method. + +### onEditableSave(editable-save.bs.table) + +Fired when an editable cell is saved. + +parameters: field, row, oldValue, $el + +### onEditableShown(editable-shown.bs.table) + +Fired when an editable cell is opened for edits. + +parameters: field, row, $el, editable + +### onEditableHidden(editable-hidden.bs.table) + +Fired when an editable cell is hidden / closed. + +parameters: field, row, $el, reason + +## The existing problems + +* Editable extension does not support searchable in the select type. diff --git a/public/assets/js/extensions/editable/bootstrap-table-editable.js b/public/assets/js/extensions/editable/bootstrap-table-editable.js old mode 100644 new mode 100755 index cd37f42b19..0bb43a6c21 --- a/public/assets/js/extensions/editable/bootstrap-table-editable.js +++ b/public/assets/js/extensions/editable/bootstrap-table-editable.js @@ -14,12 +14,20 @@ }, onEditableSave: function (field, row, oldValue, $el) { return false; + }, + onEditableShown: function (field, row, $el, editable) { + return false; + }, + onEditableHidden: function (field, row, $el, reason) { + return false; } }); $.extend($.fn.bootstrapTable.Constructor.EVENTS, { 'editable-init.bs.table': 'onEditableInit', - 'editable-save.bs.table': 'onEditableSave' + 'editable-save.bs.table': 'onEditableSave', + 'editable-shown.bs.table': 'onEditableShown', + 'editable-hidden.bs.table': 'onEditableHidden' }); var BootstrapTable = $.fn.bootstrapTable.Constructor, @@ -34,7 +42,7 @@ return; } - $.each(this.options.columns, function (i, column) { + $.each(this.columns, function (i, column) { if (!column.editable) { return; } @@ -61,7 +69,7 @@ return; } - $.each(this.options.columns, function (i, column) { + $.each(this.columns, function (i, column) { if (!column.editable) { return; } @@ -76,6 +84,22 @@ row[column.field] = params.submitValue; that.trigger('editable-save', column.field, row, oldValue, $(this)); }); + that.$body.find('a[data-name="' + column.field + '"]').editable(column.editable) + .off('shown').on('shown', function (e, editable) { + var data = that.getData(), + index = $(this).parents('tr[data-index]').data('index'), + row = data[index]; + + that.trigger('editable-shown', column.field, row, $(this), editable); + }); + that.$body.find('a[data-name="' + column.field + '"]').editable(column.editable) + .off('hidden').on('hidden', function (e, reason) { + var data = that.getData(), + index = $(this).parents('tr[data-index]').data('index'), + row = data[index]; + + that.trigger('editable-hidden', column.field, row, $(this), reason); + }); }); this.trigger('editable-init'); }; diff --git a/public/assets/js/extensions/editable/bootstrap-table-editable.min.js b/public/assets/js/extensions/editable/bootstrap-table-editable.min.js deleted file mode 100644 index 80355398ce..0000000000 --- a/public/assets/js/extensions/editable/bootstrap-table-editable.min.js +++ /dev/null @@ -1,7 +0,0 @@ -/* -* bootstrap-table - v1.8.1 - 2015-05-29 -* https://github.com/wenzhixin/bootstrap-table -* Copyright (c) 2015 zhixin wen -* Licensed MIT License -*/ -!function(a){"use strict";a.extend(a.fn.bootstrapTable.defaults,{editable:!0,onEditableInit:function(){return!1},onEditableSave:function(){return!1}}),a.extend(a.fn.bootstrapTable.Constructor.EVENTS,{"editable-init.bs.table":"onEditableInit","editable-save.bs.table":"onEditableSave"});var b=a.fn.bootstrapTable.Constructor,c=b.prototype.initTable,d=b.prototype.initBody;b.prototype.initTable=function(){var b=this;c.apply(this,Array.prototype.slice.apply(arguments)),this.options.editable&&a.each(this.options.columns,function(a,c){if(c.editable){var d=c.formatter;c.formatter=function(a,e,f){var g=d?d(a,e,f):a;return['<a href="javascript:void(0)"',' data-name="'+c.field+'"',' data-pk="'+e[b.options.idField]+'"',' data-value="'+g+'"',"></a>"].join("")}}})},b.prototype.initBody=function(){var b=this;d.apply(this,Array.prototype.slice.apply(arguments)),this.options.editable&&(a.each(this.options.columns,function(c,d){d.editable&&b.$body.find('a[data-name="'+d.field+'"]').editable(d.editable).off("save").on("save",function(c,e){var f=b.getData(),g=a(this).parents("tr[data-index]").data("index"),h=f[g],i=h[d.field];h[d.field]=e.submitValue,b.trigger("editable-save",d.field,h,i,a(this))})}),this.trigger("editable-init"))}}(jQuery); \ No newline at end of file diff --git a/public/assets/js/extensions/export/README.md b/public/assets/js/extensions/export/README.md new file mode 100755 index 0000000000..d8666893bc --- /dev/null +++ b/public/assets/js/extensions/export/README.md @@ -0,0 +1,35 @@ +# Table Export + +Use Plugin: [tableExport.jquery.plugin](https://github.com/hhurz/tableExport.jquery.plugin) + +## Usage + +```html +<script src="extensions/export/bootstrap-table-export.js"></script> +``` + +## Options + +### showExport + +* type: Boolean +* description: set `true` to show export button. +* default: `false` + +### exportDataType + +* type: String +* description: export data type, support: 'basic', 'all', 'selected'. +* default: `basic` + +### exportTypes + +* type: Array +* description: export types, support types: 'json', 'xml', 'png', 'csv', 'txt', 'sql', 'doc', 'excel', 'powerpoint', 'pdf'. +* default: `['json', 'xml', 'csv', 'txt', 'sql', 'excel']` + +### exportOptions + +* type: Object +* description: export [options](https://github.com/hhurz/tableExport.jquery.plugin#options) of `tableExport.jquery.plugin` +* default: `{}` diff --git a/public/assets/js/extensions/export/bootstrap-table-export.js b/public/assets/js/extensions/export/bootstrap-table-export.js old mode 100644 new mode 100755 index 2e2f4c3326..5be5001d53 --- a/public/assets/js/extensions/export/bootstrap-table-export.js +++ b/public/assets/js/extensions/export/bootstrap-table-export.js @@ -21,6 +21,7 @@ $.extend($.fn.bootstrapTable.defaults, { showExport: false, + exportDataType: 'basic', // basic, all, selected // 'json', 'xml', 'png', 'csv', 'txt', 'sql', 'doc', 'excel', 'powerpoint', 'pdf' exportTypes: ['json', 'xml', 'csv', 'txt', 'sql', 'excel'], exportOptions: {} @@ -73,10 +74,31 @@ }); $menu.find('li').click(function () { - that.$el.tableExport($.extend({}, that.options.exportOptions, { - type: $(this).data('type'), - escape: false - })); + var type = $(this).data('type'), + doExport = function () { + that.$el.tableExport($.extend({}, that.options.exportOptions, { + type: type, + escape: false + })); + }; + + if (that.options.exportDataType === 'all' && that.options.pagination) { + that.togglePagination(); + that.$el.on('load-success.bs.table', function () { + doExport(); + that.$el.off('load-success.bs.table'); + that.togglePagination(); + }); + } else if (that.options.exportDataType === 'selected') { + var data = that.getData(), + selectedData = that.getAllSelections(); + + that.load(selectedData); + doExport(); + that.load(data); + } else { + doExport(); + } }); } } diff --git a/public/assets/js/extensions/export/bootstrap-table-export.min.js b/public/assets/js/extensions/export/bootstrap-table-export.min.js deleted file mode 100644 index 5df6e1c271..0000000000 --- a/public/assets/js/extensions/export/bootstrap-table-export.min.js +++ /dev/null @@ -1,7 +0,0 @@ -/* -* bootstrap-table - v1.8.1 - 2015-05-29 -* https://github.com/wenzhixin/bootstrap-table -* Copyright (c) 2015 zhixin wen -* Licensed MIT License -*/ -!function(a){"use strict";var b={json:"JSON",xml:"XML",png:"PNG",csv:"CSV",txt:"TXT",sql:"SQL",doc:"MS-Word",excel:"Ms-Excel",powerpoint:"Ms-Powerpoint",pdf:"PDF"};a.extend(a.fn.bootstrapTable.defaults,{showExport:!1,exportTypes:["json","xml","csv","txt","sql","excel"],exportOptions:{}});var c=a.fn.bootstrapTable.Constructor,d=c.prototype.initToolbar;c.prototype.initToolbar=function(){if(this.showToolbar=this.options.showExport,d.apply(this,Array.prototype.slice.apply(arguments)),this.options.showExport){var c=this,e=this.$toolbar.find(">.btn-group"),f=e.find("div.export");if(!f.length){f=a(['<div class="export btn-group">','<button class="btn btn-default dropdown-toggle" data-toggle="dropdown" type="button">','<i class="glyphicon glyphicon-export icon-share"></i> ','<span class="caret"></span>',"</button>",'<ul class="dropdown-menu" role="menu">',"</ul>","</div>"].join("")).appendTo(e);var g=f.find(".dropdown-menu"),h=this.options.exportTypes;if("string"==typeof this.options.exportTypes){var i=this.options.exportTypes.slice(1,-1).replace(/ /g,"").split(",");h=[],a.each(i,function(a,b){h.push(b.slice(1,-1))})}a.each(h,function(a,c){b.hasOwnProperty(c)&&g.append(['<li data-type="'+c+'">','<a href="javascript:void(0)">',b[c],"</a>","</li>"].join(""))}),g.find("li").click(function(){c.$el.tableExport(a.extend({},c.options.exportOptions,{type:a(this).data("type"),escape:!1}))})}}}}(jQuery); \ No newline at end of file diff --git a/public/assets/js/extensions/filter-control/README.md b/public/assets/js/extensions/filter-control/README.md new file mode 100755 index 0000000000..b223102773 --- /dev/null +++ b/public/assets/js/extensions/filter-control/README.md @@ -0,0 +1,49 @@ +# Table Filter Control + +Use Plugin: [bootstrap-table-filter-control](https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/filter-control) </br> +Dependence if you use the datepicker option: [bootstrap-datepicker](https://github.com/eternicode/bootstrap-datepicker) v1.4.0 + +## Usage + +```html +<script src="extensions/filter-control/bootstrap-table-filter-control.js"></script> +``` + +## Options + +### filterControl + +* type: Boolean +* description: Set true to add an `input` or `select` into the column. +* default: `false` + +### filterShowClear + +* type: Boolean +* description: Set true to add a button to clear all the controls added by this plugin +* default: `false` + + +## Column options + +### filterControl + +* type: String +* description: Set `input`: show an input control, `select`: show a select control, `datepicker`: show a datepicker control. +* default: `undefined` + +### filterDatepickerOptions +* type: Object +* description: If the datepicker option is set use this option to configure the datepicker with the native options. Use this way: `data-filter-datepicker-options='{"autoclose":true, "clearBtn": true, "todayHighlight": true}'`. +* default: `undefined` + +### filterStrictSearch +* type: Boolean +* description: Set to true if you want to use the strict search mode. +* default: `false` + +## Events + +### onColumnSearch(column-search.bs.table) + +* Fired when we are searching into the column data \ No newline at end of file diff --git a/public/assets/js/extensions/filter-control/bootstrap-table-filter-control.js b/public/assets/js/extensions/filter-control/bootstrap-table-filter-control.js old mode 100644 new mode 100755 index fc80c1cb41..fa696d3bb2 --- a/public/assets/js/extensions/filter-control/bootstrap-table-filter-control.js +++ b/public/assets/js/extensions/filter-control/bootstrap-table-filter-control.js @@ -8,94 +8,110 @@ 'use strict'; - var sprintf = function (str) { - var args = arguments, - flag = true, - i = 1; + var sprintf = $.fn.bootstrapTable.utils.sprintf; - str = str.replace(/%s/g, function () { - var arg = args[i++]; + var addOptionToSelectControl = function (selectControl, value, text) { + selectControl = $(selectControl.get(selectControl.length - 1)); + if (existsOptionInSelectControl(selectControl, value)) { + selectControl.append($("<option></option>") + .attr("value", value) + .text($('<div />').html(text).text())); - if (typeof arg === 'undefined') { - flag = false; - return ''; - } - return arg; - }); - return flag ? str : ''; + // Sort it. Not overly efficient to do this here + var $opts = selectControl.find('option:gt(0)'); + $opts.sort(function (a, b) { + a = $(a).text().toLowerCase(); + b = $(b).text().toLowerCase(); + if ($.isNumeric(a) && $.isNumeric(b)) { + // Convert numerical values from string to float. + a = parseFloat(a); + b = parseFloat(b); + } + return a > b ? 1 : a < b ? -1 : 0; + }); + + selectControl.find('option:gt(0)').remove(); + selectControl.append($opts); + } }; - var getFieldIndex = function (columns, field) { - var index = -1; - - $.each(columns, function (i, column) { - if (column.field === field) { - index = i; + var existsOptionInSelectControl = function (selectControl, value) { + var options = selectControl.get(selectControl.length - 1).options; + for (var i = 0; i < options.length; i++) { + if (options[i].value === value.toString()) { + //The value is nor valid to add return false; } - return true; - }); - return index; + } + + //If we get here, the value is valid to add + return true; }; - var calculateObjectValue = function (self, name, args, defaultValue) { - if (typeof name === 'string') { - // support obj.func1.func2 - var names = name.split('.'); + var fixHeaderCSS = function (that) { + that.$tableHeader.css('height', '77px'); + }; - if (names.length > 1) { - name = window; - $.each(names, function (i, f) { - name = name[f]; + var getCurrentHeader = function (that) { + var header = that.$header; + if (that.options.height) { + header = that.$tableHeader; + } + + return header; + }; + + var getCurrentSearchControls = function (that) { + var searchControls = 'select, input'; + if (that.options.height) { + searchControls = 'table select, table input'; + } + + return searchControls; + }; + + var copyValues = function (that) { + var header = getCurrentHeader(that), + searchControls = getCurrentSearchControls(that); + + that.options.values = []; + + header.find(searchControls).each(function () { + that.options.values.push( + { + field: $(this).parent().parent().parent().data('field'), + value: $(this).val() }); - } else { - name = window[name]; - } - } - if (typeof name === 'object') { - return name; - } - if (typeof name === 'function') { - return name.apply(self, args); - } - return defaultValue; + }); }; - $.extend($.fn.bootstrapTable.defaults, { - filterControl: false, - onColumnSearch: function (field, text) { - return false; - } - }); - - $.extend($.fn.bootstrapTable.COLUMN_DEFAULTS, { - filterControl: undefined, - filterData: undefined - }); - - $.extend($.fn.bootstrapTable.Constructor.EVENTS, { - 'column-search.bs.table': 'onColumnSearch' - }); - - var BootstrapTable = $.fn.bootstrapTable.Constructor, - _initHeader = BootstrapTable.prototype.initHeader, - _initBody = BootstrapTable.prototype.initBody, - _initSearch = BootstrapTable.prototype.initSearch; - - BootstrapTable.prototype.initHeader = function () { - _initHeader.apply(this, Array.prototype.slice.apply(arguments)); - - if (!this.options.filterControl) { - return; + var setValues = function(that) { + var field = null, + result = [], + header = getCurrentHeader(that), + searchControls = getCurrentSearchControls(that); + + if (that.options.values.length > 0) { + header.find(searchControls).each(function (index, ele) { + field = $(this).parent().parent().parent().data('field'); + result = $.grep(that.options.values, function (valueObj) { + return valueObj.field === field; + }); + + if (result.length > 0) { + $(this).val(result[0].value); + } + }); } + }; + var createControls = function (that, header) { var addedFilterControl = false, - that = this, isVisible, html, timeoutId = 0; - $.each(this.options.columns, function (i, column) { + $.each(that.columns, function (i, column) { isVisible = 'hidden'; html = []; @@ -120,17 +136,26 @@ html.push(sprintf('<select class="%s form-control" style="width: 100%; visibility: %s"></select>', column.field, isVisible)) break; + case 'datepicker': + html.push(sprintf('<input type="text" class="date-filter-control %s form-control" style="width: 100%; visibility: %s">', + column.field, isVisible)); + break; } } - that.$header.find(sprintf('.th-inner:eq("%s")', i)).next().append(html.join('')); + $.each(header.children().children(), function (i, tr) { + tr = $(tr); + if (tr.data('field') === column.field) { + tr.find('.fht-cell').append(html.join('')); + return false; + } + }); if (column.filterData !== undefined && column.filterData.toLowerCase() !== 'column') { var filterDataType = column.filterData.substring(0, 3); var filterDataSource = column.filterData.substring(4, column.filterData.length); var selectControl = $('.' + column.field); - selectControl.append($("<option></option>") - .attr("value", '') - .text('')); + addOptionToSelectControl(selectControl, '', ''); + switch (filterDataType) { case 'url': $.ajax({ @@ -138,9 +163,7 @@ dataType: 'json', success: function (data) { $.each(data, function (key, value) { - selectControl.append($("<option></option>") - .attr("value", key) - .text(value)); + addOptionToSelectControl(selectControl, key, value); }); } }); @@ -148,87 +171,185 @@ case 'var': var variableValues = window[filterDataSource]; for (var key in variableValues) { - selectControl.append($("<option></option>") - .attr("value", key) - .text(variableValues[key])); - }; + addOptionToSelectControl(selectControl, key, variableValues[key]); + } break; } } }); if (addedFilterControl) { - this.$header.off('keyup', 'input').on('keyup', 'input', function (event) { + header.off('keyup', 'input').on('keyup', 'input', function (event) { clearTimeout(timeoutId); timeoutId = setTimeout(function () { that.onColumnSearch(event); }, that.options.searchTimeOut); }); - this.$header.off('change', 'select').on('change', 'select', function (event) { + header.off('change', 'select').on('change', 'select', function (event) { clearTimeout(timeoutId); timeoutId = setTimeout(function () { that.onColumnSearch(event); }, that.options.searchTimeOut); }); + + header.off('mouseup', 'input').on('mouseup', 'input', function (event) { + var $input = $(this), + oldValue = $input.val(); + + if (oldValue === "") { + return; + } + + setTimeout(function(){ + var newValue = $input.val(); + + if (newValue === "") { + clearTimeout(timeoutId); + timeoutId = setTimeout(function () { + that.onColumnSearch(event); + }, that.options.searchTimeOut); + } + }, 1); + }); + + if (header.find('.date-filter-control').length > 0) { + $.each(that.columns, function (i, column) { + if (column.filterControl !== undefined && column.filterControl.toLowerCase() === 'datepicker') { + header.find('.date-filter-control.' + column.field).datepicker(column.filterDatepickerOptions) + .on('changeDate', function (e) { + //Fired the keyup event + $(e.currentTarget).keyup(); + }); + } + }); + } } else { - this.$header.find('.filterControl').hide(); + header.find('.filterControl').hide(); } }; + $.extend($.fn.bootstrapTable.defaults, { + filterControl: false, + onColumnSearch: function (field, text) { + return false; + }, + filterShowClear: false, + //internal variables + values: [] + }); + + $.extend($.fn.bootstrapTable.COLUMN_DEFAULTS, { + filterControl: undefined, + filterData: undefined, + filterDatepickerOptions: undefined, + filterStrictSearch: false + }); + + $.extend($.fn.bootstrapTable.Constructor.EVENTS, { + 'column-search.bs.table': 'onColumnSearch' + }); + + var BootstrapTable = $.fn.bootstrapTable.Constructor, + _init = BootstrapTable.prototype.init, + _initToolbar = BootstrapTable.prototype.initToolbar, + _initHeader = BootstrapTable.prototype.initHeader, + _initBody = BootstrapTable.prototype.initBody, + _initSearch = BootstrapTable.prototype.initSearch; + + BootstrapTable.prototype.init = function () { + //Make sure that the filtercontrol option is set + if (this.options.filterControl) { + var that = this; + //Make sure that the internal variables are set correctly + this.options.values = []; + + this.$el.on('reset-view.bs.table', function () { + //Create controls on $tableHeader if the height is set + if (!that.options.height) { + return; + } + + //Avoid recreate the controls + if (that.$tableHeader.find('select').length > 0 || that.$tableHeader.find('input').length > 0) { + return; + } + + createControls(that, that.$tableHeader); + }).on('post-header.bs.table', function () { + setValues(that); + }).on('post-body.bs.table', function () { + if (that.options.height) { + fixHeaderCSS(that); + } + }).on('column-switch.bs.table', function(field, checked) { + setValues(that); + }); + } + _init.apply(this, Array.prototype.slice.apply(arguments)); + }; + + BootstrapTable.prototype.initToolbar = function () { + if ((!this.showToolbar) && (this.options.filterControl)) { + this.showToolbar = this.options.filterControl; + } + + _initToolbar.apply(this, Array.prototype.slice.apply(arguments)); + + if (this.options.filterControl && this.options.filterShowClear) { + var $btnGroup = this.$toolbar.find('>.btn-group'), + $btnClear = $btnGroup.find('div.export'); + + if (!$btnClear.length) { + $btnClear = $([ + '<button class="btn btn-default " ' + + 'type="button">', + '<i class="glyphicon glyphicon-trash icon-share"></i> ', + '</button>', + '</ul>'].join('')).appendTo($btnGroup); + + $btnClear.off('click').on('click', $.proxy(this.clearFilterControl, this)); + } + } + }; + + BootstrapTable.prototype.initHeader = function () { + _initHeader.apply(this, Array.prototype.slice.apply(arguments)); + + if (!this.options.filterControl) { + return; + } + createControls(this, this.$header); + }; + BootstrapTable.prototype.initBody = function () { _initBody.apply(this, Array.prototype.slice.apply(arguments)); var that = this, - data = this.getData(); + data = this.options.data, + pageTo = this.pageTo < this.options.data.length ? this.options.data.length : this.pageTo; - for (var i = this.pageFrom - 1; i < this.pageTo; i++) { - var key, - item = data[i]; + for (var i = this.pageFrom - 1; i < pageTo; i++) { + var item = data[i]; $.each(this.header.fields, function (j, field) { var value = item[field], - column = that.options.columns[getFieldIndex(that.options.columns, field)]; + column = that.columns[$.fn.bootstrapTable.utils.getFieldIndex(that.columns, field)]; - value = calculateObjectValue(that.header, - that.header.formatters[j], [value, item, i], value); + value = $.fn.bootstrapTable.utils.calculateObjectValue(that.header, that.header.formatters[j], [value, item, i], value); if ((!column.checkbox) || (!column.radio)) { - if (column.filterControl !== undefined && column.filterControl.toLowerCase() === 'select' - && column.searchable) { - + if (column.filterControl !== undefined && column.filterControl.toLowerCase() === 'select' && column.searchable) { if (column.filterData === undefined || column.filterData.toLowerCase() === 'column') { - var selectControl = $('.' + column.field), - iOpt = 0, - exitsOpt = false, - options; - if (selectControl !== undefined) { - options = selectControl.get(0).options; - - if (options.length === 0) { - + var selectControl = $('.' + column.field); + if (selectControl !== undefined && selectControl.length > 0) { + if (selectControl.get(selectControl.length - 1).options.length === 0) { //Added the default option - selectControl.append($("<option></option>") - .attr("value", '') - .text('')); - - selectControl.append($("<option></option>") - .attr("value", value) - .text(value)); - } else { - for (; iOpt < options.length; iOpt++) { - if (options[iOpt].value === value) { - exitsOpt = true; - break; - } - } - - if (!exitsOpt) { - selectControl.append($("<option></option>") - .attr("value", value) - .text(value)); - } + addOptionToSelectControl(selectControl, '', ''); } + + //Added a new value + addOptionToSelectControl(selectControl, value, value); } } } @@ -246,23 +367,34 @@ //Check partial column filter this.data = fp ? $.grep(this.data, function (item, i) { for (var key in fp) { + var thisColumn = that.columns[$.fn.bootstrapTable.utils.getFieldIndex(that.columns, key)]; var fval = fp[key].toLowerCase(); var value = item[key]; - value = calculateObjectValue(that.header, + value = $.fn.bootstrapTable.utils.calculateObjectValue(that.header, that.header.formatters[$.inArray(key, that.header.fields)], [value, item, i], value); - if (!($.inArray(key, that.header.fields) !== -1 && - (typeof value === 'string' || typeof value === 'number') && - (value + '').toLowerCase().indexOf(fval) !== -1)) { - return false; + if(thisColumn.filterStrictSearch){ + if (!($.inArray(key, that.header.fields) !== -1 && + (typeof value === 'string' || typeof value === 'number') && + value.toString().toLowerCase() === fval.toString().toLowerCase())) { + return false; + } } + else{ + if (!($.inArray(key, that.header.fields) !== -1 && + (typeof value === 'string' || typeof value === 'number') && + (value + '').toLowerCase().indexOf(fval) !== -1)) { + return false; + } + }; } return true; }) : this.data; }; BootstrapTable.prototype.onColumnSearch = function (event) { + copyValues(this); var text = $.trim($(event.currentTarget).val()); var $field = $(event.currentTarget).parent().parent().parent().data('field') @@ -280,4 +412,25 @@ this.updatePagination(); this.trigger('column-search', $field, text); }; + + BootstrapTable.prototype.clearFilterControl = function () { + if (this.options.filterControl && this.options.filterShowClear) { + $.each(this.options.values, function (i, item) { + item.value = ''; + }); + + setValues(this); + + var controls = getCurrentHeader(this).find(getCurrentSearchControls(this)), + timeoutId = 0; + + if (controls.length > 0) { + this.filterColumnsPartial = {}; + clearTimeout(timeoutId); + timeoutId = setTimeout(function () { + $(controls[0]).trigger(controls[0].tagName === 'INPUT' ? 'keyup' : 'change'); + }, this.options.searchTimeOut); + } + } + }; }(jQuery); diff --git a/public/assets/js/extensions/filter-control/bootstrap-table-filter-control.min.js b/public/assets/js/extensions/filter-control/bootstrap-table-filter-control.min.js deleted file mode 100644 index 9a7457df02..0000000000 --- a/public/assets/js/extensions/filter-control/bootstrap-table-filter-control.min.js +++ /dev/null @@ -1,7 +0,0 @@ -/* -* bootstrap-table - v1.8.1 - 2015-05-29 -* https://github.com/wenzhixin/bootstrap-table -* Copyright (c) 2015 zhixin wen -* Licensed MIT License -*/ -!function(a){"use strict";var b=function(a){var b=arguments,c=!0,d=1;return a=a.replace(/%s/g,function(){var a=b[d++];return"undefined"==typeof a?(c=!1,""):a}),c?a:""},c=function(b,c){var d=-1;return a.each(b,function(a,b){return b.field===c?(d=a,!1):!0}),d},d=function(b,c,d,e){if("string"==typeof c){var f=c.split(".");f.length>1?(c=window,a.each(f,function(a,b){c=c[b]})):c=window[c]}return"object"==typeof c?c:"function"==typeof c?c.apply(b,d):e};a.extend(a.fn.bootstrapTable.defaults,{filterControl:!1,onColumnSearch:function(){return!1}}),a.extend(a.fn.bootstrapTable.COLUMN_DEFAULTS,{filterControl:void 0,filterData:void 0}),a.extend(a.fn.bootstrapTable.Constructor.EVENTS,{"column-search.bs.table":"onColumnSearch"});var e=a.fn.bootstrapTable.Constructor,f=e.prototype.initHeader,g=e.prototype.initBody,h=e.prototype.initSearch;e.prototype.initHeader=function(){if(f.apply(this,Array.prototype.slice.apply(arguments)),this.options.filterControl){var c,d,e=!1,g=this,h=0;a.each(this.options.columns,function(f,h){if(c="hidden",d=[],h.visible){if(h.filterControl)switch(d.push('<div style="margin: 0px 2px 2px 2px;" class="filterControl">'),h.filterControl&&h.searchable&&(e=!0,c="visible"),h.filterControl.toLowerCase()){case"input":d.push(b('<input type="text" class="form-control" style="width: 100%; visibility: %s">',c));break;case"select":d.push(b('<select class="%s form-control" style="width: 100%; visibility: %s"></select>',h.field,c))}else d.push('<div style="height: 34px;"></div>');if(g.$header.find(b('.th-inner:eq("%s")',f)).next().append(d.join("")),void 0!==h.filterData&&"column"!==h.filterData.toLowerCase()){var i=h.filterData.substring(0,3),j=h.filterData.substring(4,h.filterData.length),k=a("."+h.field);switch(k.append(a("<option></option>").attr("value","").text("")),i){case"url":a.ajax({url:j,dataType:"json",success:function(b){a.each(b,function(b,c){k.append(a("<option></option>").attr("value",b).text(c))})}});break;case"var":var l=window[j];for(var m in l)k.append(a("<option></option>").attr("value",m).text(l[m]))}}}}),e?(this.$header.off("keyup","input").on("keyup","input",function(a){clearTimeout(h),h=setTimeout(function(){g.onColumnSearch(a)},g.options.searchTimeOut)}),this.$header.off("change","select").on("change","select",function(a){clearTimeout(h),h=setTimeout(function(){g.onColumnSearch(a)},g.options.searchTimeOut)})):this.$header.find(".filterControl").hide()}},e.prototype.initBody=function(){g.apply(this,Array.prototype.slice.apply(arguments));for(var b=this,e=this.getData(),f=this.pageFrom-1;f<this.pageTo;f++){var h=e[f];a.each(this.header.fields,function(e,g){var i=h[g],j=b.options.columns[c(b.options.columns,g)];if(i=d(b.header,b.header.formatters[e],[i,h,f],i),!(j.checkbox&&j.radio||void 0===j.filterControl||"select"!==j.filterControl.toLowerCase()||!j.searchable||void 0!==j.filterData&&"column"!==j.filterData.toLowerCase())){var k,l=a("."+j.field),m=0,n=!1;if(void 0!==l)if(k=l.get(0).options,0===k.length)l.append(a("<option></option>").attr("value","").text("")),l.append(a("<option></option>").attr("value",i).text(i));else{for(;m<k.length;m++)if(k[m].value===i){n=!0;break}n||l.append(a("<option></option>").attr("value",i).text(i))}}})}},e.prototype.initSearch=function(){h.apply(this,Array.prototype.slice.apply(arguments));var b=this,c=a.isEmptyObject(this.filterColumnsPartial)?null:this.filterColumnsPartial;this.data=c?a.grep(this.data,function(e,f){for(var g in c){var h=c[g].toLowerCase(),i=e[g];if(i=d(b.header,b.header.formatters[a.inArray(g,b.header.fields)],[i,e,f],i),-1===a.inArray(g,b.header.fields)||"string"!=typeof i&&"number"!=typeof i||-1===(i+"").toLowerCase().indexOf(h))return!1}return!0}):this.data},e.prototype.onColumnSearch=function(b){var c=a.trim(a(b.currentTarget).val()),d=a(b.currentTarget).parent().parent().parent().data("field");a.isEmptyObject(this.filterColumnsPartial)&&(this.filterColumnsPartial={}),c?this.filterColumnsPartial[d]=c:delete this.filterColumnsPartial[d],this.options.pageNumber=1,this.onSearch(b),this.updatePagination(),this.trigger("column-search",d,c)}}(jQuery); \ No newline at end of file diff --git a/public/assets/js/extensions/filter/README.md b/public/assets/js/extensions/filter/README.md new file mode 100755 index 0000000000..15501f412f --- /dev/null +++ b/public/assets/js/extensions/filter/README.md @@ -0,0 +1,17 @@ +# Table Filter + +Use Plugin: [bootstrap table filters](https://github.com/lukaskral/bootstrap-table-filter) + +## Usage + +```html +<script src="extensions/filter/bootstrap-table-filter.js"></script> +``` + +## Options + +### showFilter + +* type: Boolean +* description: set true to show filter menu. +* default: `false` diff --git a/public/assets/js/extensions/filter/bootstrap-table-filter.js b/public/assets/js/extensions/filter/bootstrap-table-filter.js old mode 100644 new mode 100755 index 086566916f..14af13da06 --- a/public/assets/js/extensions/filter/bootstrap-table-filter.js +++ b/public/assets/js/extensions/filter/bootstrap-table-filter.js @@ -43,7 +43,7 @@ }; BootstrapTable.prototype.getColumns = function () { - return this.options.columns; + return this.columns; }; BootstrapTable.prototype.registerSearchCallback = function (callback) { diff --git a/public/assets/js/extensions/filter/bootstrap-table-filter.min.js b/public/assets/js/extensions/filter/bootstrap-table-filter.min.js deleted file mode 100644 index 125cdb7bfa..0000000000 --- a/public/assets/js/extensions/filter/bootstrap-table-filter.min.js +++ /dev/null @@ -1,7 +0,0 @@ -/* -* bootstrap-table - v1.8.1 - 2015-05-29 -* https://github.com/wenzhixin/bootstrap-table -* Copyright (c) 2015 zhixin wen -* Licensed MIT License -*/ -!function(a){"use strict";a.extend(a.fn.bootstrapTable.defaults,{showFilter:!1});var b=a.fn.bootstrapTable.Constructor,c=b.prototype.init,d=b.prototype.initSearch;b.prototype.init=function(){c.apply(this,Array.prototype.slice.apply(arguments));var b=this;this.$el.on("load-success.bs.table",function(){b.options.showFilter&&a(b.options.toolbar).bootstrapTableFilter({connectTo:b.$el})})},b.prototype.initSearch=function(){d.apply(this,Array.prototype.slice.apply(arguments)),"server"!==this.options.sidePagination&&"function"==typeof this.searchCallback&&(this.data=a.grep(this.options.data,this.searchCallback))},b.prototype.getData=function(){return this.searchText||this.searchCallback?this.data:this.options.data},b.prototype.getColumns=function(){return this.options.columns},b.prototype.registerSearchCallback=function(a){this.searchCallback=a},b.prototype.updateSearch=function(){this.options.pageNumber=1,this.initSearch(),this.updatePagination()},b.prototype.getServerUrl=function(){return"server"===this.options.sidePagination?this.options.url:!1},a.fn.bootstrapTable.methods.push("getColumns","registerSearchCallback","updateSearch","getServerUrl")}(jQuery); \ No newline at end of file diff --git a/public/assets/js/extensions/flat-json/README.md b/public/assets/js/extensions/flat-json/README.md new file mode 100755 index 0000000000..f1c5c46d82 --- /dev/null +++ b/public/assets/js/extensions/flat-json/README.md @@ -0,0 +1,23 @@ +# Table flat-json + +Use Plugin: [bootstrap-table-flat-json](https://github.com/djhvscf/bootstrap-table-flat-json) + +## Usage + +```html +<script src="extensions/flat-json/bootstrap-table-flat-json.js"></script> +``` + +## Options + +### flat + +* type: Boolean +* description: Set true to flat the JSON object. +* default: `false` + +### flatSeparator + +* type: String +* description: Set the default separator between object levels. +* default: `.` \ No newline at end of file diff --git a/public/assets/js/extensions/flat-json/bootstrap-table-flat-json.js b/public/assets/js/extensions/flat-json/bootstrap-table-flat-json.js old mode 100644 new mode 100755 index f5f3a35c35..4bbf3a2a9e --- a/public/assets/js/extensions/flat-json/bootstrap-table-flat-json.js +++ b/public/assets/js/extensions/flat-json/bootstrap-table-flat-json.js @@ -1,70 +1,62 @@ /** * @author: Dennis Hernández * @webSite: http://djhvscf.github.io/Blog - * @version: v1.2.0 + * @version: v1.3.0 */ - (function ($) { 'use strict'; + var flat = function (element, that) { + var result = {}; + + function recurse(cur, prop) { + if (Object(cur) !== cur) { + result[prop] = cur; + } else if ($.isArray(cur)) { + for (var i = 0, l = cur.length; i < l; i++) { + recurse(cur[i], prop ? prop + that.options.flatSeparator + i : "" + i); + if (l == 0) { + result[prop] = []; + } + } + } else { + var isEmpty = true; + for (var p in cur) { + isEmpty = false; + recurse(cur[p], prop ? prop + that.options.flatSeparator + p : p); + } + if (isEmpty) { + result[prop] = {}; + } + } + } + + recurse(element, ""); + return result; + }; + + var flatHelper = function (data, that) { + var flatArray = []; + + $.each(!$.isArray(data) ? [data] : data, function (i, element) { + flatArray.push(flat(element, that)); + }); + return flatArray; + }; + $.extend($.fn.bootstrapTable.defaults, { - flat: false + flat: false, + flatSeparator: '.' }); var BootstrapTable = $.fn.bootstrapTable.Constructor, _initData = BootstrapTable.prototype.initData; BootstrapTable.prototype.initData = function (data, type) { - if( this.options.flat ){ - data = data === undefined ? this.options.data : data; - data = sd.flatHelper(data); + if (this.options.flat) { + data = flatHelper(data ? data : this.options.data, this); } _initData.apply(this, [data, type]); }; - - //Main functions - var sd = { - flat: function (element) { - var result = {}; - - function recurse(cur, prop) { - if (Object(cur) !== cur) { - result[prop] = cur; - } else if ($.isArray(cur)) { - for (var i = 0, l = cur.length; i < l; i++) { - recurse(cur[i], prop ? prop + "." + i : "" + i); - if (l == 0) { - result[prop] = []; - } - } - } else { - var isEmpty = true; - for (var p in cur) { - isEmpty = false; - recurse(cur[p], prop ? prop + "." + p : p); - } - if (isEmpty) { - result[prop] = {}; - } - } - } - - recurse(element, ""); - return result; - }, - - flatHelper: function (data) { - var flatArray = [], - arrayHelper = []; - if (!$.isArray(data)) { - arrayHelper.push(data); - data = arrayHelper; - } - $.each(data, function (i, element) { - flatArray.push(sd.flat(element)); - }); - return flatArray; - } - }; })(jQuery); diff --git a/public/assets/js/extensions/flat-json/bootstrap-table-flat-json.min.js b/public/assets/js/extensions/flat-json/bootstrap-table-flat-json.min.js deleted file mode 100644 index d842a6cada..0000000000 --- a/public/assets/js/extensions/flat-json/bootstrap-table-flat-json.min.js +++ /dev/null @@ -1,7 +0,0 @@ -/* -* bootstrap-table - v1.8.1 - 2015-05-29 -* https://github.com/wenzhixin/bootstrap-table -* Copyright (c) 2015 zhixin wen -* Licensed MIT License -*/ -!function(a){"use strict";a.extend(a.fn.bootstrapTable.defaults,{flat:!1});var b=a.fn.bootstrapTable.Constructor,c=b.prototype.initData;b.prototype.initData=function(a,b){this.options.flat&&(a=void 0===a?this.options.data:a,a=d.flatHelper(a)),c.apply(this,[a,b])};var d={flat:function(b){function c(b,e){if(Object(b)!==b)d[e]=b;else if(a.isArray(b))for(var f=0,g=b.length;g>f;f++)c(b[f],e?e+"."+f:""+f),0==g&&(d[e]=[]);else{var h=!0;for(var i in b)h=!1,c(b[i],e?e+"."+i:i);h&&(d[e]={})}}var d={};return c(b,""),d},flatHelper:function(b){var c=[],e=[];return a.isArray(b)||(e.push(b),b=e),a.each(b,function(a,b){c.push(d.flat(b))}),c}}}(jQuery); \ No newline at end of file diff --git a/public/assets/js/extensions/group-by/README.md b/public/assets/js/extensions/group-by/README.md new file mode 100755 index 0000000000..95317dcfa0 --- /dev/null +++ b/public/assets/js/extensions/group-by/README.md @@ -0,0 +1,62 @@ +# Table group-by + +Use Plugin: [bootstrap-table-group-by](https://github.com/djhvscf/bootstrap-table-group-by) </br> +Dependence: [jquery-treetable](https://github.com/ludo/jquery-treetable/) v3.2.0 </br> +You must include the bootstrap-table-group-by.css file in order to get the appropriate style + +## Usage + +```html +<script src="extensions/group-by/bootstrap-table-group-by.js"></script> +``` + +## Options + +### groupBy + +* type: Boolean +* description: Set true to group the data by the field passed. +* default: `false` + +### groupByField + +* type: Array +* description: Set the array fields that you want to group the data. +* default: `[]` + +### groupBySumGroup + +* type: Boolean +* description: Set to True to include a sum per column. +* default: `false` + +### groupByInitExpanded + +* type: Boolean +* description: You can use the node number (parent row index) or you can use the `all` option in order to expand all nodes of the table. +* default: `undefined` + +## Methods + +### expandAll + +* Expand all the nodes in the table. + +### collapseAll + +* Collapse all the nodes in the table. + +## Column options + +### groupBySumGroup + +* type: Boolean +* description: Set to True to sum the column values. +* default: `false` + + +## Known issues + +### OnSort + +* When sort options are set to True the group by is not working properly, for now if these properties are set to True the group by extension will be disabled. \ No newline at end of file diff --git a/public/assets/js/extensions/group-by/bootstrap-table-group-by.css b/public/assets/js/extensions/group-by/bootstrap-table-group-by.css new file mode 100755 index 0000000000..fce5a9a7b1 --- /dev/null +++ b/public/assets/js/extensions/group-by/bootstrap-table-group-by.css @@ -0,0 +1,53 @@ +table.treetable tbody tr td { + cursor: default; +} + +table.treetable span { + background-position: center left; + background-repeat: no-repeat; + padding: .2em 0 .2em 1.5em; +} + +table.treetable tr.collapsed span.indenter a { + background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsTAAALEwEAmpwYAAAKT2lDQ1BQaG90b3Nob3AgSUNDIHByb2ZpbGUAAHjanVNnVFPpFj333vRCS4iAlEtvUhUIIFJCi4AUkSYqIQkQSoghodkVUcERRUUEG8igiAOOjoCMFVEsDIoK2AfkIaKOg6OIisr74Xuja9a89+bN/rXXPues852zzwfACAyWSDNRNYAMqUIeEeCDx8TG4eQuQIEKJHAAEAizZCFz/SMBAPh+PDwrIsAHvgABeNMLCADATZvAMByH/w/qQplcAYCEAcB0kThLCIAUAEB6jkKmAEBGAYCdmCZTAKAEAGDLY2LjAFAtAGAnf+bTAICd+Jl7AQBblCEVAaCRACATZYhEAGg7AKzPVopFAFgwABRmS8Q5ANgtADBJV2ZIALC3AMDOEAuyAAgMADBRiIUpAAR7AGDIIyN4AISZABRG8lc88SuuEOcqAAB4mbI8uSQ5RYFbCC1xB1dXLh4ozkkXKxQ2YQJhmkAuwnmZGTKBNA/g88wAAKCRFRHgg/P9eM4Ors7ONo62Dl8t6r8G/yJiYuP+5c+rcEAAAOF0ftH+LC+zGoA7BoBt/qIl7gRoXgugdfeLZrIPQLUAoOnaV/Nw+H48PEWhkLnZ2eXk5NhKxEJbYcpXff5nwl/AV/1s+X48/Pf14L7iJIEyXYFHBPjgwsz0TKUcz5IJhGLc5o9H/LcL//wd0yLESWK5WCoU41EScY5EmozzMqUiiUKSKcUl0v9k4t8s+wM+3zUAsGo+AXuRLahdYwP2SycQWHTA4vcAAPK7b8HUKAgDgGiD4c93/+8//UegJQCAZkmScQAAXkQkLlTKsz/HCAAARKCBKrBBG/TBGCzABhzBBdzBC/xgNoRCJMTCQhBCCmSAHHJgKayCQiiGzbAdKmAv1EAdNMBRaIaTcA4uwlW4Dj1wD/phCJ7BKLyBCQRByAgTYSHaiAFiilgjjggXmYX4IcFIBBKLJCDJiBRRIkuRNUgxUopUIFVIHfI9cgI5h1xGupE7yAAygvyGvEcxlIGyUT3UDLVDuag3GoRGogvQZHQxmo8WoJvQcrQaPYw2oefQq2gP2o8+Q8cwwOgYBzPEbDAuxsNCsTgsCZNjy7EirAyrxhqwVqwDu4n1Y8+xdwQSgUXACTYEd0IgYR5BSFhMWE7YSKggHCQ0EdoJNwkDhFHCJyKTqEu0JroR+cQYYjIxh1hILCPWEo8TLxB7iEPENyQSiUMyJ7mQAkmxpFTSEtJG0m5SI+ksqZs0SBojk8naZGuyBzmULCAryIXkneTD5DPkG+Qh8lsKnWJAcaT4U+IoUspqShnlEOU05QZlmDJBVaOaUt2ooVQRNY9aQq2htlKvUYeoEzR1mjnNgxZJS6WtopXTGmgXaPdpr+h0uhHdlR5Ol9BX0svpR+iX6AP0dwwNhhWDx4hnKBmbGAcYZxl3GK+YTKYZ04sZx1QwNzHrmOeZD5lvVVgqtip8FZHKCpVKlSaVGyovVKmqpqreqgtV81XLVI+pXlN9rkZVM1PjqQnUlqtVqp1Q61MbU2epO6iHqmeob1Q/pH5Z/YkGWcNMw09DpFGgsV/jvMYgC2MZs3gsIWsNq4Z1gTXEJrHN2Xx2KruY/R27iz2qqaE5QzNKM1ezUvOUZj8H45hx+Jx0TgnnKKeX836K3hTvKeIpG6Y0TLkxZVxrqpaXllirSKtRq0frvTau7aedpr1Fu1n7gQ5Bx0onXCdHZ4/OBZ3nU9lT3acKpxZNPTr1ri6qa6UbobtEd79up+6Ynr5egJ5Mb6feeb3n+hx9L/1U/W36p/VHDFgGswwkBtsMzhg8xTVxbzwdL8fb8VFDXcNAQ6VhlWGX4YSRudE8o9VGjUYPjGnGXOMk423GbcajJgYmISZLTepN7ppSTbmmKaY7TDtMx83MzaLN1pk1mz0x1zLnm+eb15vft2BaeFostqi2uGVJsuRaplnutrxuhVo5WaVYVVpds0atna0l1rutu6cRp7lOk06rntZnw7Dxtsm2qbcZsOXYBtuutm22fWFnYhdnt8Wuw+6TvZN9un2N/T0HDYfZDqsdWh1+c7RyFDpWOt6azpzuP33F9JbpL2dYzxDP2DPjthPLKcRpnVOb00dnF2e5c4PziIuJS4LLLpc+Lpsbxt3IveRKdPVxXeF60vWdm7Obwu2o26/uNu5p7ofcn8w0nymeWTNz0MPIQ+BR5dE/C5+VMGvfrH5PQ0+BZ7XnIy9jL5FXrdewt6V3qvdh7xc+9j5yn+M+4zw33jLeWV/MN8C3yLfLT8Nvnl+F30N/I/9k/3r/0QCngCUBZwOJgUGBWwL7+Hp8Ib+OPzrbZfay2e1BjKC5QRVBj4KtguXBrSFoyOyQrSH355jOkc5pDoVQfujW0Adh5mGLw34MJ4WHhVeGP45wiFga0TGXNXfR3ENz30T6RJZE3ptnMU85ry1KNSo+qi5qPNo3ujS6P8YuZlnM1VidWElsSxw5LiquNm5svt/87fOH4p3iC+N7F5gvyF1weaHOwvSFpxapLhIsOpZATIhOOJTwQRAqqBaMJfITdyWOCnnCHcJnIi/RNtGI2ENcKh5O8kgqTXqS7JG8NXkkxTOlLOW5hCepkLxMDUzdmzqeFpp2IG0yPTq9MYOSkZBxQqohTZO2Z+pn5mZ2y6xlhbL+xW6Lty8elQfJa7OQrAVZLQq2QqboVFoo1yoHsmdlV2a/zYnKOZarnivN7cyzytuQN5zvn//tEsIS4ZK2pYZLVy0dWOa9rGo5sjxxedsK4xUFK4ZWBqw8uIq2Km3VT6vtV5eufr0mek1rgV7ByoLBtQFr6wtVCuWFfevc1+1dT1gvWd+1YfqGnRs+FYmKrhTbF5cVf9go3HjlG4dvyr+Z3JS0qavEuWTPZtJm6ebeLZ5bDpaql+aXDm4N2dq0Dd9WtO319kXbL5fNKNu7g7ZDuaO/PLi8ZafJzs07P1SkVPRU+lQ27tLdtWHX+G7R7ht7vPY07NXbW7z3/T7JvttVAVVN1WbVZftJ+7P3P66Jqun4lvttXa1ObXHtxwPSA/0HIw6217nU1R3SPVRSj9Yr60cOxx++/p3vdy0NNg1VjZzG4iNwRHnk6fcJ3/ceDTradox7rOEH0x92HWcdL2pCmvKaRptTmvtbYlu6T8w+0dbq3nr8R9sfD5w0PFl5SvNUyWna6YLTk2fyz4ydlZ19fi753GDborZ752PO32oPb++6EHTh0kX/i+c7vDvOXPK4dPKy2+UTV7hXmq86X23qdOo8/pPTT8e7nLuarrlca7nuer21e2b36RueN87d9L158Rb/1tWeOT3dvfN6b/fF9/XfFt1+cif9zsu72Xcn7q28T7xf9EDtQdlD3YfVP1v+3Njv3H9qwHeg89HcR/cGhYPP/pH1jw9DBY+Zj8uGDYbrnjg+OTniP3L96fynQ89kzyaeF/6i/suuFxYvfvjV69fO0ZjRoZfyl5O/bXyl/erA6xmv28bCxh6+yXgzMV70VvvtwXfcdx3vo98PT+R8IH8o/2j5sfVT0Kf7kxmTk/8EA5jz/GMzLdsAAAAgY0hSTQAAeiUAAICDAAD5/wAAgOkAAHUwAADqYAAAOpgAABdvkl/FRgAAAHlJREFUeNrcU1sNgDAQ6wgmcAM2MICGGlg1gJnNzWQcvwQGy1j4oUl/7tH0mpwzM7SgQyO+EZAUWh2MkkzSWhJwuRAlHYsJwEwyvs1gABDuzqoJcTw5qxaIJN0bgQRgIjnlmn1heSO5PE6Y2YXe+5Cr5+h++gs12AcAS6FS+7YOsj4AAAAASUVORK5CYII=); + padding-right: 12px; +} + +table.treetable tr.expanded span.indenter a { + background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsTAAALEwEAmpwYAAAKT2lDQ1BQaG90b3Nob3AgSUNDIHByb2ZpbGUAAHjanVNnVFPpFj333vRCS4iAlEtvUhUIIFJCi4AUkSYqIQkQSoghodkVUcERRUUEG8igiAOOjoCMFVEsDIoK2AfkIaKOg6OIisr74Xuja9a89+bN/rXXPues852zzwfACAyWSDNRNYAMqUIeEeCDx8TG4eQuQIEKJHAAEAizZCFz/SMBAPh+PDwrIsAHvgABeNMLCADATZvAMByH/w/qQplcAYCEAcB0kThLCIAUAEB6jkKmAEBGAYCdmCZTAKAEAGDLY2LjAFAtAGAnf+bTAICd+Jl7AQBblCEVAaCRACATZYhEAGg7AKzPVopFAFgwABRmS8Q5ANgtADBJV2ZIALC3AMDOEAuyAAgMADBRiIUpAAR7AGDIIyN4AISZABRG8lc88SuuEOcqAAB4mbI8uSQ5RYFbCC1xB1dXLh4ozkkXKxQ2YQJhmkAuwnmZGTKBNA/g88wAAKCRFRHgg/P9eM4Ors7ONo62Dl8t6r8G/yJiYuP+5c+rcEAAAOF0ftH+LC+zGoA7BoBt/qIl7gRoXgugdfeLZrIPQLUAoOnaV/Nw+H48PEWhkLnZ2eXk5NhKxEJbYcpXff5nwl/AV/1s+X48/Pf14L7iJIEyXYFHBPjgwsz0TKUcz5IJhGLc5o9H/LcL//wd0yLESWK5WCoU41EScY5EmozzMqUiiUKSKcUl0v9k4t8s+wM+3zUAsGo+AXuRLahdYwP2SycQWHTA4vcAAPK7b8HUKAgDgGiD4c93/+8//UegJQCAZkmScQAAXkQkLlTKsz/HCAAARKCBKrBBG/TBGCzABhzBBdzBC/xgNoRCJMTCQhBCCmSAHHJgKayCQiiGzbAdKmAv1EAdNMBRaIaTcA4uwlW4Dj1wD/phCJ7BKLyBCQRByAgTYSHaiAFiilgjjggXmYX4IcFIBBKLJCDJiBRRIkuRNUgxUopUIFVIHfI9cgI5h1xGupE7yAAygvyGvEcxlIGyUT3UDLVDuag3GoRGogvQZHQxmo8WoJvQcrQaPYw2oefQq2gP2o8+Q8cwwOgYBzPEbDAuxsNCsTgsCZNjy7EirAyrxhqwVqwDu4n1Y8+xdwQSgUXACTYEd0IgYR5BSFhMWE7YSKggHCQ0EdoJNwkDhFHCJyKTqEu0JroR+cQYYjIxh1hILCPWEo8TLxB7iEPENyQSiUMyJ7mQAkmxpFTSEtJG0m5SI+ksqZs0SBojk8naZGuyBzmULCAryIXkneTD5DPkG+Qh8lsKnWJAcaT4U+IoUspqShnlEOU05QZlmDJBVaOaUt2ooVQRNY9aQq2htlKvUYeoEzR1mjnNgxZJS6WtopXTGmgXaPdpr+h0uhHdlR5Ol9BX0svpR+iX6AP0dwwNhhWDx4hnKBmbGAcYZxl3GK+YTKYZ04sZx1QwNzHrmOeZD5lvVVgqtip8FZHKCpVKlSaVGyovVKmqpqreqgtV81XLVI+pXlN9rkZVM1PjqQnUlqtVqp1Q61MbU2epO6iHqmeob1Q/pH5Z/YkGWcNMw09DpFGgsV/jvMYgC2MZs3gsIWsNq4Z1gTXEJrHN2Xx2KruY/R27iz2qqaE5QzNKM1ezUvOUZj8H45hx+Jx0TgnnKKeX836K3hTvKeIpG6Y0TLkxZVxrqpaXllirSKtRq0frvTau7aedpr1Fu1n7gQ5Bx0onXCdHZ4/OBZ3nU9lT3acKpxZNPTr1ri6qa6UbobtEd79up+6Ynr5egJ5Mb6feeb3n+hx9L/1U/W36p/VHDFgGswwkBtsMzhg8xTVxbzwdL8fb8VFDXcNAQ6VhlWGX4YSRudE8o9VGjUYPjGnGXOMk423GbcajJgYmISZLTepN7ppSTbmmKaY7TDtMx83MzaLN1pk1mz0x1zLnm+eb15vft2BaeFostqi2uGVJsuRaplnutrxuhVo5WaVYVVpds0atna0l1rutu6cRp7lOk06rntZnw7Dxtsm2qbcZsOXYBtuutm22fWFnYhdnt8Wuw+6TvZN9un2N/T0HDYfZDqsdWh1+c7RyFDpWOt6azpzuP33F9JbpL2dYzxDP2DPjthPLKcRpnVOb00dnF2e5c4PziIuJS4LLLpc+Lpsbxt3IveRKdPVxXeF60vWdm7Obwu2o26/uNu5p7ofcn8w0nymeWTNz0MPIQ+BR5dE/C5+VMGvfrH5PQ0+BZ7XnIy9jL5FXrdewt6V3qvdh7xc+9j5yn+M+4zw33jLeWV/MN8C3yLfLT8Nvnl+F30N/I/9k/3r/0QCngCUBZwOJgUGBWwL7+Hp8Ib+OPzrbZfay2e1BjKC5QRVBj4KtguXBrSFoyOyQrSH355jOkc5pDoVQfujW0Adh5mGLw34MJ4WHhVeGP45wiFga0TGXNXfR3ENz30T6RJZE3ptnMU85ry1KNSo+qi5qPNo3ujS6P8YuZlnM1VidWElsSxw5LiquNm5svt/87fOH4p3iC+N7F5gvyF1weaHOwvSFpxapLhIsOpZATIhOOJTwQRAqqBaMJfITdyWOCnnCHcJnIi/RNtGI2ENcKh5O8kgqTXqS7JG8NXkkxTOlLOW5hCepkLxMDUzdmzqeFpp2IG0yPTq9MYOSkZBxQqohTZO2Z+pn5mZ2y6xlhbL+xW6Lty8elQfJa7OQrAVZLQq2QqboVFoo1yoHsmdlV2a/zYnKOZarnivN7cyzytuQN5zvn//tEsIS4ZK2pYZLVy0dWOa9rGo5sjxxedsK4xUFK4ZWBqw8uIq2Km3VT6vtV5eufr0mek1rgV7ByoLBtQFr6wtVCuWFfevc1+1dT1gvWd+1YfqGnRs+FYmKrhTbF5cVf9go3HjlG4dvyr+Z3JS0qavEuWTPZtJm6ebeLZ5bDpaql+aXDm4N2dq0Dd9WtO319kXbL5fNKNu7g7ZDuaO/PLi8ZafJzs07P1SkVPRU+lQ27tLdtWHX+G7R7ht7vPY07NXbW7z3/T7JvttVAVVN1WbVZftJ+7P3P66Jqun4lvttXa1ObXHtxwPSA/0HIw6217nU1R3SPVRSj9Yr60cOxx++/p3vdy0NNg1VjZzG4iNwRHnk6fcJ3/ceDTradox7rOEH0x92HWcdL2pCmvKaRptTmvtbYlu6T8w+0dbq3nr8R9sfD5w0PFl5SvNUyWna6YLTk2fyz4ydlZ19fi753GDborZ752PO32oPb++6EHTh0kX/i+c7vDvOXPK4dPKy2+UTV7hXmq86X23qdOo8/pPTT8e7nLuarrlca7nuer21e2b36RueN87d9L158Rb/1tWeOT3dvfN6b/fF9/XfFt1+cif9zsu72Xcn7q28T7xf9EDtQdlD3YfVP1v+3Njv3H9qwHeg89HcR/cGhYPP/pH1jw9DBY+Zj8uGDYbrnjg+OTniP3L96fynQ89kzyaeF/6i/suuFxYvfvjV69fO0ZjRoZfyl5O/bXyl/erA6xmv28bCxh6+yXgzMV70VvvtwXfcdx3vo98PT+R8IH8o/2j5sfVT0Kf7kxmTk/8EA5jz/GMzLdsAAAAgY0hSTQAAeiUAAICDAAD5/wAAgOkAAHUwAADqYAAAOpgAABdvkl/FRgAAAHFJREFUeNpi/P//PwMlgImBQsA44C6gvhfa29v3MzAwOODRc6CystIRbxi0t7fjDJjKykpGYrwwi1hxnLHQ3t7+jIGBQRJJ6HllZaUUKYEYRYBPOB0gBShKwKGA////48VtbW3/8clTnBIH3gCKkzJgAGvBX0dDm0sCAAAAAElFTkSuQmCC); + padding-right: 12px; +} + +table.treetable tr.branch { + background-color: #f9f9f9; +} + +table.treetable tr.selected { + background-color: #3875d7; + color: #fff; +} + +table.treetable tr span.indenter a { + outline: none; /* Expander shows outline after upgrading to 3.0 (#141) */ +} + +table.treetable tr.collapsed.selected span.indenter a { + background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsTAAALEwEAmpwYAAAKT2lDQ1BQaG90b3Nob3AgSUNDIHByb2ZpbGUAAHjanVNnVFPpFj333vRCS4iAlEtvUhUIIFJCi4AUkSYqIQkQSoghodkVUcERRUUEG8igiAOOjoCMFVEsDIoK2AfkIaKOg6OIisr74Xuja9a89+bN/rXXPues852zzwfACAyWSDNRNYAMqUIeEeCDx8TG4eQuQIEKJHAAEAizZCFz/SMBAPh+PDwrIsAHvgABeNMLCADATZvAMByH/w/qQplcAYCEAcB0kThLCIAUAEB6jkKmAEBGAYCdmCZTAKAEAGDLY2LjAFAtAGAnf+bTAICd+Jl7AQBblCEVAaCRACATZYhEAGg7AKzPVopFAFgwABRmS8Q5ANgtADBJV2ZIALC3AMDOEAuyAAgMADBRiIUpAAR7AGDIIyN4AISZABRG8lc88SuuEOcqAAB4mbI8uSQ5RYFbCC1xB1dXLh4ozkkXKxQ2YQJhmkAuwnmZGTKBNA/g88wAAKCRFRHgg/P9eM4Ors7ONo62Dl8t6r8G/yJiYuP+5c+rcEAAAOF0ftH+LC+zGoA7BoBt/qIl7gRoXgugdfeLZrIPQLUAoOnaV/Nw+H48PEWhkLnZ2eXk5NhKxEJbYcpXff5nwl/AV/1s+X48/Pf14L7iJIEyXYFHBPjgwsz0TKUcz5IJhGLc5o9H/LcL//wd0yLESWK5WCoU41EScY5EmozzMqUiiUKSKcUl0v9k4t8s+wM+3zUAsGo+AXuRLahdYwP2SycQWHTA4vcAAPK7b8HUKAgDgGiD4c93/+8//UegJQCAZkmScQAAXkQkLlTKsz/HCAAARKCBKrBBG/TBGCzABhzBBdzBC/xgNoRCJMTCQhBCCmSAHHJgKayCQiiGzbAdKmAv1EAdNMBRaIaTcA4uwlW4Dj1wD/phCJ7BKLyBCQRByAgTYSHaiAFiilgjjggXmYX4IcFIBBKLJCDJiBRRIkuRNUgxUopUIFVIHfI9cgI5h1xGupE7yAAygvyGvEcxlIGyUT3UDLVDuag3GoRGogvQZHQxmo8WoJvQcrQaPYw2oefQq2gP2o8+Q8cwwOgYBzPEbDAuxsNCsTgsCZNjy7EirAyrxhqwVqwDu4n1Y8+xdwQSgUXACTYEd0IgYR5BSFhMWE7YSKggHCQ0EdoJNwkDhFHCJyKTqEu0JroR+cQYYjIxh1hILCPWEo8TLxB7iEPENyQSiUMyJ7mQAkmxpFTSEtJG0m5SI+ksqZs0SBojk8naZGuyBzmULCAryIXkneTD5DPkG+Qh8lsKnWJAcaT4U+IoUspqShnlEOU05QZlmDJBVaOaUt2ooVQRNY9aQq2htlKvUYeoEzR1mjnNgxZJS6WtopXTGmgXaPdpr+h0uhHdlR5Ol9BX0svpR+iX6AP0dwwNhhWDx4hnKBmbGAcYZxl3GK+YTKYZ04sZx1QwNzHrmOeZD5lvVVgqtip8FZHKCpVKlSaVGyovVKmqpqreqgtV81XLVI+pXlN9rkZVM1PjqQnUlqtVqp1Q61MbU2epO6iHqmeob1Q/pH5Z/YkGWcNMw09DpFGgsV/jvMYgC2MZs3gsIWsNq4Z1gTXEJrHN2Xx2KruY/R27iz2qqaE5QzNKM1ezUvOUZj8H45hx+Jx0TgnnKKeX836K3hTvKeIpG6Y0TLkxZVxrqpaXllirSKtRq0frvTau7aedpr1Fu1n7gQ5Bx0onXCdHZ4/OBZ3nU9lT3acKpxZNPTr1ri6qa6UbobtEd79up+6Ynr5egJ5Mb6feeb3n+hx9L/1U/W36p/VHDFgGswwkBtsMzhg8xTVxbzwdL8fb8VFDXcNAQ6VhlWGX4YSRudE8o9VGjUYPjGnGXOMk423GbcajJgYmISZLTepN7ppSTbmmKaY7TDtMx83MzaLN1pk1mz0x1zLnm+eb15vft2BaeFostqi2uGVJsuRaplnutrxuhVo5WaVYVVpds0atna0l1rutu6cRp7lOk06rntZnw7Dxtsm2qbcZsOXYBtuutm22fWFnYhdnt8Wuw+6TvZN9un2N/T0HDYfZDqsdWh1+c7RyFDpWOt6azpzuP33F9JbpL2dYzxDP2DPjthPLKcRpnVOb00dnF2e5c4PziIuJS4LLLpc+Lpsbxt3IveRKdPVxXeF60vWdm7Obwu2o26/uNu5p7ofcn8w0nymeWTNz0MPIQ+BR5dE/C5+VMGvfrH5PQ0+BZ7XnIy9jL5FXrdewt6V3qvdh7xc+9j5yn+M+4zw33jLeWV/MN8C3yLfLT8Nvnl+F30N/I/9k/3r/0QCngCUBZwOJgUGBWwL7+Hp8Ib+OPzrbZfay2e1BjKC5QRVBj4KtguXBrSFoyOyQrSH355jOkc5pDoVQfujW0Adh5mGLw34MJ4WHhVeGP45wiFga0TGXNXfR3ENz30T6RJZE3ptnMU85ry1KNSo+qi5qPNo3ujS6P8YuZlnM1VidWElsSxw5LiquNm5svt/87fOH4p3iC+N7F5gvyF1weaHOwvSFpxapLhIsOpZATIhOOJTwQRAqqBaMJfITdyWOCnnCHcJnIi/RNtGI2ENcKh5O8kgqTXqS7JG8NXkkxTOlLOW5hCepkLxMDUzdmzqeFpp2IG0yPTq9MYOSkZBxQqohTZO2Z+pn5mZ2y6xlhbL+xW6Lty8elQfJa7OQrAVZLQq2QqboVFoo1yoHsmdlV2a/zYnKOZarnivN7cyzytuQN5zvn//tEsIS4ZK2pYZLVy0dWOa9rGo5sjxxedsK4xUFK4ZWBqw8uIq2Km3VT6vtV5eufr0mek1rgV7ByoLBtQFr6wtVCuWFfevc1+1dT1gvWd+1YfqGnRs+FYmKrhTbF5cVf9go3HjlG4dvyr+Z3JS0qavEuWTPZtJm6ebeLZ5bDpaql+aXDm4N2dq0Dd9WtO319kXbL5fNKNu7g7ZDuaO/PLi8ZafJzs07P1SkVPRU+lQ27tLdtWHX+G7R7ht7vPY07NXbW7z3/T7JvttVAVVN1WbVZftJ+7P3P66Jqun4lvttXa1ObXHtxwPSA/0HIw6217nU1R3SPVRSj9Yr60cOxx++/p3vdy0NNg1VjZzG4iNwRHnk6fcJ3/ceDTradox7rOEH0x92HWcdL2pCmvKaRptTmvtbYlu6T8w+0dbq3nr8R9sfD5w0PFl5SvNUyWna6YLTk2fyz4ydlZ19fi753GDborZ752PO32oPb++6EHTh0kX/i+c7vDvOXPK4dPKy2+UTV7hXmq86X23qdOo8/pPTT8e7nLuarrlca7nuer21e2b36RueN87d9L158Rb/1tWeOT3dvfN6b/fF9/XfFt1+cif9zsu72Xcn7q28T7xf9EDtQdlD3YfVP1v+3Njv3H9qwHeg89HcR/cGhYPP/pH1jw9DBY+Zj8uGDYbrnjg+OTniP3L96fynQ89kzyaeF/6i/suuFxYvfvjV69fO0ZjRoZfyl5O/bXyl/erA6xmv28bCxh6+yXgzMV70VvvtwXfcdx3vo98PT+R8IH8o/2j5sfVT0Kf7kxmTk/8EA5jz/GMzLdsAAAAgY0hSTQAAeiUAAICDAAD5/wAAgOkAAHUwAADqYAAAOpgAABdvkl/FRgAAAFpJREFUeNpi/P//PwMlgHHADWD4//8/NtyAQxwD45KAAQdKDfj//////fgMIsYAZIMw1DKREFwODAwM/4kNRKq64AADA4MjFDOQ6gKyY4HodMA49PMCxQYABgAVYHsjyZ1x7QAAAABJRU5ErkJggg==); +} + +table.treetable tr.expanded.selected span.indenter a { + background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsTAAALEwEAmpwYAAAKT2lDQ1BQaG90b3Nob3AgSUNDIHByb2ZpbGUAAHjanVNnVFPpFj333vRCS4iAlEtvUhUIIFJCi4AUkSYqIQkQSoghodkVUcERRUUEG8igiAOOjoCMFVEsDIoK2AfkIaKOg6OIisr74Xuja9a89+bN/rXXPues852zzwfACAyWSDNRNYAMqUIeEeCDx8TG4eQuQIEKJHAAEAizZCFz/SMBAPh+PDwrIsAHvgABeNMLCADATZvAMByH/w/qQplcAYCEAcB0kThLCIAUAEB6jkKmAEBGAYCdmCZTAKAEAGDLY2LjAFAtAGAnf+bTAICd+Jl7AQBblCEVAaCRACATZYhEAGg7AKzPVopFAFgwABRmS8Q5ANgtADBJV2ZIALC3AMDOEAuyAAgMADBRiIUpAAR7AGDIIyN4AISZABRG8lc88SuuEOcqAAB4mbI8uSQ5RYFbCC1xB1dXLh4ozkkXKxQ2YQJhmkAuwnmZGTKBNA/g88wAAKCRFRHgg/P9eM4Ors7ONo62Dl8t6r8G/yJiYuP+5c+rcEAAAOF0ftH+LC+zGoA7BoBt/qIl7gRoXgugdfeLZrIPQLUAoOnaV/Nw+H48PEWhkLnZ2eXk5NhKxEJbYcpXff5nwl/AV/1s+X48/Pf14L7iJIEyXYFHBPjgwsz0TKUcz5IJhGLc5o9H/LcL//wd0yLESWK5WCoU41EScY5EmozzMqUiiUKSKcUl0v9k4t8s+wM+3zUAsGo+AXuRLahdYwP2SycQWHTA4vcAAPK7b8HUKAgDgGiD4c93/+8//UegJQCAZkmScQAAXkQkLlTKsz/HCAAARKCBKrBBG/TBGCzABhzBBdzBC/xgNoRCJMTCQhBCCmSAHHJgKayCQiiGzbAdKmAv1EAdNMBRaIaTcA4uwlW4Dj1wD/phCJ7BKLyBCQRByAgTYSHaiAFiilgjjggXmYX4IcFIBBKLJCDJiBRRIkuRNUgxUopUIFVIHfI9cgI5h1xGupE7yAAygvyGvEcxlIGyUT3UDLVDuag3GoRGogvQZHQxmo8WoJvQcrQaPYw2oefQq2gP2o8+Q8cwwOgYBzPEbDAuxsNCsTgsCZNjy7EirAyrxhqwVqwDu4n1Y8+xdwQSgUXACTYEd0IgYR5BSFhMWE7YSKggHCQ0EdoJNwkDhFHCJyKTqEu0JroR+cQYYjIxh1hILCPWEo8TLxB7iEPENyQSiUMyJ7mQAkmxpFTSEtJG0m5SI+ksqZs0SBojk8naZGuyBzmULCAryIXkneTD5DPkG+Qh8lsKnWJAcaT4U+IoUspqShnlEOU05QZlmDJBVaOaUt2ooVQRNY9aQq2htlKvUYeoEzR1mjnNgxZJS6WtopXTGmgXaPdpr+h0uhHdlR5Ol9BX0svpR+iX6AP0dwwNhhWDx4hnKBmbGAcYZxl3GK+YTKYZ04sZx1QwNzHrmOeZD5lvVVgqtip8FZHKCpVKlSaVGyovVKmqpqreqgtV81XLVI+pXlN9rkZVM1PjqQnUlqtVqp1Q61MbU2epO6iHqmeob1Q/pH5Z/YkGWcNMw09DpFGgsV/jvMYgC2MZs3gsIWsNq4Z1gTXEJrHN2Xx2KruY/R27iz2qqaE5QzNKM1ezUvOUZj8H45hx+Jx0TgnnKKeX836K3hTvKeIpG6Y0TLkxZVxrqpaXllirSKtRq0frvTau7aedpr1Fu1n7gQ5Bx0onXCdHZ4/OBZ3nU9lT3acKpxZNPTr1ri6qa6UbobtEd79up+6Ynr5egJ5Mb6feeb3n+hx9L/1U/W36p/VHDFgGswwkBtsMzhg8xTVxbzwdL8fb8VFDXcNAQ6VhlWGX4YSRudE8o9VGjUYPjGnGXOMk423GbcajJgYmISZLTepN7ppSTbmmKaY7TDtMx83MzaLN1pk1mz0x1zLnm+eb15vft2BaeFostqi2uGVJsuRaplnutrxuhVo5WaVYVVpds0atna0l1rutu6cRp7lOk06rntZnw7Dxtsm2qbcZsOXYBtuutm22fWFnYhdnt8Wuw+6TvZN9un2N/T0HDYfZDqsdWh1+c7RyFDpWOt6azpzuP33F9JbpL2dYzxDP2DPjthPLKcRpnVOb00dnF2e5c4PziIuJS4LLLpc+Lpsbxt3IveRKdPVxXeF60vWdm7Obwu2o26/uNu5p7ofcn8w0nymeWTNz0MPIQ+BR5dE/C5+VMGvfrH5PQ0+BZ7XnIy9jL5FXrdewt6V3qvdh7xc+9j5yn+M+4zw33jLeWV/MN8C3yLfLT8Nvnl+F30N/I/9k/3r/0QCngCUBZwOJgUGBWwL7+Hp8Ib+OPzrbZfay2e1BjKC5QRVBj4KtguXBrSFoyOyQrSH355jOkc5pDoVQfujW0Adh5mGLw34MJ4WHhVeGP45wiFga0TGXNXfR3ENz30T6RJZE3ptnMU85ry1KNSo+qi5qPNo3ujS6P8YuZlnM1VidWElsSxw5LiquNm5svt/87fOH4p3iC+N7F5gvyF1weaHOwvSFpxapLhIsOpZATIhOOJTwQRAqqBaMJfITdyWOCnnCHcJnIi/RNtGI2ENcKh5O8kgqTXqS7JG8NXkkxTOlLOW5hCepkLxMDUzdmzqeFpp2IG0yPTq9MYOSkZBxQqohTZO2Z+pn5mZ2y6xlhbL+xW6Lty8elQfJa7OQrAVZLQq2QqboVFoo1yoHsmdlV2a/zYnKOZarnivN7cyzytuQN5zvn//tEsIS4ZK2pYZLVy0dWOa9rGo5sjxxedsK4xUFK4ZWBqw8uIq2Km3VT6vtV5eufr0mek1rgV7ByoLBtQFr6wtVCuWFfevc1+1dT1gvWd+1YfqGnRs+FYmKrhTbF5cVf9go3HjlG4dvyr+Z3JS0qavEuWTPZtJm6ebeLZ5bDpaql+aXDm4N2dq0Dd9WtO319kXbL5fNKNu7g7ZDuaO/PLi8ZafJzs07P1SkVPRU+lQ27tLdtWHX+G7R7ht7vPY07NXbW7z3/T7JvttVAVVN1WbVZftJ+7P3P66Jqun4lvttXa1ObXHtxwPSA/0HIw6217nU1R3SPVRSj9Yr60cOxx++/p3vdy0NNg1VjZzG4iNwRHnk6fcJ3/ceDTradox7rOEH0x92HWcdL2pCmvKaRptTmvtbYlu6T8w+0dbq3nr8R9sfD5w0PFl5SvNUyWna6YLTk2fyz4ydlZ19fi753GDborZ752PO32oPb++6EHTh0kX/i+c7vDvOXPK4dPKy2+UTV7hXmq86X23qdOo8/pPTT8e7nLuarrlca7nuer21e2b36RueN87d9L158Rb/1tWeOT3dvfN6b/fF9/XfFt1+cif9zsu72Xcn7q28T7xf9EDtQdlD3YfVP1v+3Njv3H9qwHeg89HcR/cGhYPP/pH1jw9DBY+Zj8uGDYbrnjg+OTniP3L96fynQ89kzyaeF/6i/suuFxYvfvjV69fO0ZjRoZfyl5O/bXyl/erA6xmv28bCxh6+yXgzMV70VvvtwXfcdx3vo98PT+R8IH8o/2j5sfVT0Kf7kxmTk/8EA5jz/GMzLdsAAAAgY0hSTQAAeiUAAICDAAD5/wAAgOkAAHUwAADqYAAAOpgAABdvkl/FRgAAAFtJREFUeNpi/P//PwMlgImBQsA44C6giQENDAwM//HgBmLCAF/AMBLjBUeixf///48L7/+PCvZjU4fPAAc0AxywqcMXCwegGJ1NckL6jx5wpKYDxqGXEkkCgAEAmrqBIejdgngAAAAASUVORK5CYII=); +} + +table.treetable tr.accept { + background-color: #a3bce4; + color: #fff +} + +table.treetable tr.collapsed.accept td span.indenter a { + background-image: url(data:image/x-png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsTAAALEwEAmpwYAAAKT2lDQ1BQaG90b3Nob3AgSUNDIHByb2ZpbGUAAHjanVNnVFPpFj333vRCS4iAlEtvUhUIIFJCi4AUkSYqIQkQSoghodkVUcERRUUEG8igiAOOjoCMFVEsDIoK2AfkIaKOg6OIisr74Xuja9a89+bN/rXXPues852zzwfACAyWSDNRNYAMqUIeEeCDx8TG4eQuQIEKJHAAEAizZCFz/SMBAPh+PDwrIsAHvgABeNMLCADATZvAMByH/w/qQplcAYCEAcB0kThLCIAUAEB6jkKmAEBGAYCdmCZTAKAEAGDLY2LjAFAtAGAnf+bTAICd+Jl7AQBblCEVAaCRACATZYhEAGg7AKzPVopFAFgwABRmS8Q5ANgtADBJV2ZIALC3AMDOEAuyAAgMADBRiIUpAAR7AGDIIyN4AISZABRG8lc88SuuEOcqAAB4mbI8uSQ5RYFbCC1xB1dXLh4ozkkXKxQ2YQJhmkAuwnmZGTKBNA/g88wAAKCRFRHgg/P9eM4Ors7ONo62Dl8t6r8G/yJiYuP+5c+rcEAAAOF0ftH+LC+zGoA7BoBt/qIl7gRoXgugdfeLZrIPQLUAoOnaV/Nw+H48PEWhkLnZ2eXk5NhKxEJbYcpXff5nwl/AV/1s+X48/Pf14L7iJIEyXYFHBPjgwsz0TKUcz5IJhGLc5o9H/LcL//wd0yLESWK5WCoU41EScY5EmozzMqUiiUKSKcUl0v9k4t8s+wM+3zUAsGo+AXuRLahdYwP2SycQWHTA4vcAAPK7b8HUKAgDgGiD4c93/+8//UegJQCAZkmScQAAXkQkLlTKsz/HCAAARKCBKrBBG/TBGCzABhzBBdzBC/xgNoRCJMTCQhBCCmSAHHJgKayCQiiGzbAdKmAv1EAdNMBRaIaTcA4uwlW4Dj1wD/phCJ7BKLyBCQRByAgTYSHaiAFiilgjjggXmYX4IcFIBBKLJCDJiBRRIkuRNUgxUopUIFVIHfI9cgI5h1xGupE7yAAygvyGvEcxlIGyUT3UDLVDuag3GoRGogvQZHQxmo8WoJvQcrQaPYw2oefQq2gP2o8+Q8cwwOgYBzPEbDAuxsNCsTgsCZNjy7EirAyrxhqwVqwDu4n1Y8+xdwQSgUXACTYEd0IgYR5BSFhMWE7YSKggHCQ0EdoJNwkDhFHCJyKTqEu0JroR+cQYYjIxh1hILCPWEo8TLxB7iEPENyQSiUMyJ7mQAkmxpFTSEtJG0m5SI+ksqZs0SBojk8naZGuyBzmULCAryIXkneTD5DPkG+Qh8lsKnWJAcaT4U+IoUspqShnlEOU05QZlmDJBVaOaUt2ooVQRNY9aQq2htlKvUYeoEzR1mjnNgxZJS6WtopXTGmgXaPdpr+h0uhHdlR5Ol9BX0svpR+iX6AP0dwwNhhWDx4hnKBmbGAcYZxl3GK+YTKYZ04sZx1QwNzHrmOeZD5lvVVgqtip8FZHKCpVKlSaVGyovVKmqpqreqgtV81XLVI+pXlN9rkZVM1PjqQnUlqtVqp1Q61MbU2epO6iHqmeob1Q/pH5Z/YkGWcNMw09DpFGgsV/jvMYgC2MZs3gsIWsNq4Z1gTXEJrHN2Xx2KruY/R27iz2qqaE5QzNKM1ezUvOUZj8H45hx+Jx0TgnnKKeX836K3hTvKeIpG6Y0TLkxZVxrqpaXllirSKtRq0frvTau7aedpr1Fu1n7gQ5Bx0onXCdHZ4/OBZ3nU9lT3acKpxZNPTr1ri6qa6UbobtEd79up+6Ynr5egJ5Mb6feeb3n+hx9L/1U/W36p/VHDFgGswwkBtsMzhg8xTVxbzwdL8fb8VFDXcNAQ6VhlWGX4YSRudE8o9VGjUYPjGnGXOMk423GbcajJgYmISZLTepN7ppSTbmmKaY7TDtMx83MzaLN1pk1mz0x1zLnm+eb15vft2BaeFostqi2uGVJsuRaplnutrxuhVo5WaVYVVpds0atna0l1rutu6cRp7lOk06rntZnw7Dxtsm2qbcZsOXYBtuutm22fWFnYhdnt8Wuw+6TvZN9un2N/T0HDYfZDqsdWh1+c7RyFDpWOt6azpzuP33F9JbpL2dYzxDP2DPjthPLKcRpnVOb00dnF2e5c4PziIuJS4LLLpc+Lpsbxt3IveRKdPVxXeF60vWdm7Obwu2o26/uNu5p7ofcn8w0nymeWTNz0MPIQ+BR5dE/C5+VMGvfrH5PQ0+BZ7XnIy9jL5FXrdewt6V3qvdh7xc+9j5yn+M+4zw33jLeWV/MN8C3yLfLT8Nvnl+F30N/I/9k/3r/0QCngCUBZwOJgUGBWwL7+Hp8Ib+OPzrbZfay2e1BjKC5QRVBj4KtguXBrSFoyOyQrSH355jOkc5pDoVQfujW0Adh5mGLw34MJ4WHhVeGP45wiFga0TGXNXfR3ENz30T6RJZE3ptnMU85ry1KNSo+qi5qPNo3ujS6P8YuZlnM1VidWElsSxw5LiquNm5svt/87fOH4p3iC+N7F5gvyF1weaHOwvSFpxapLhIsOpZATIhOOJTwQRAqqBaMJfITdyWOCnnCHcJnIi/RNtGI2ENcKh5O8kgqTXqS7JG8NXkkxTOlLOW5hCepkLxMDUzdmzqeFpp2IG0yPTq9MYOSkZBxQqohTZO2Z+pn5mZ2y6xlhbL+xW6Lty8elQfJa7OQrAVZLQq2QqboVFoo1yoHsmdlV2a/zYnKOZarnivN7cyzytuQN5zvn//tEsIS4ZK2pYZLVy0dWOa9rGo5sjxxedsK4xUFK4ZWBqw8uIq2Km3VT6vtV5eufr0mek1rgV7ByoLBtQFr6wtVCuWFfevc1+1dT1gvWd+1YfqGnRs+FYmKrhTbF5cVf9go3HjlG4dvyr+Z3JS0qavEuWTPZtJm6ebeLZ5bDpaql+aXDm4N2dq0Dd9WtO319kXbL5fNKNu7g7ZDuaO/PLi8ZafJzs07P1SkVPRU+lQ27tLdtWHX+G7R7ht7vPY07NXbW7z3/T7JvttVAVVN1WbVZftJ+7P3P66Jqun4lvttXa1ObXHtxwPSA/0HIw6217nU1R3SPVRSj9Yr60cOxx++/p3vdy0NNg1VjZzG4iNwRHnk6fcJ3/ceDTradox7rOEH0x92HWcdL2pCmvKaRptTmvtbYlu6T8w+0dbq3nr8R9sfD5w0PFl5SvNUyWna6YLTk2fyz4ydlZ19fi753GDborZ752PO32oPb++6EHTh0kX/i+c7vDvOXPK4dPKy2+UTV7hXmq86X23qdOo8/pPTT8e7nLuarrlca7nuer21e2b36RueN87d9L158Rb/1tWeOT3dvfN6b/fF9/XfFt1+cif9zsu72Xcn7q28T7xf9EDtQdlD3YfVP1v+3Njv3H9qwHeg89HcR/cGhYPP/pH1jw9DBY+Zj8uGDYbrnjg+OTniP3L96fynQ89kzyaeF/6i/suuFxYvfvjV69fO0ZjRoZfyl5O/bXyl/erA6xmv28bCxh6+yXgzMV70VvvtwXfcdx3vo98PT+R8IH8o/2j5sfVT0Kf7kxmTk/8EA5jz/GMzLdsAAAAgY0hSTQAAeiUAAICDAAD5/wAAgOkAAHUwAADqYAAAOpgAABdvkl/FRgAAAFpJREFUeNpi/P//PwMlgHHADWD4//8/NtyAQxwD45KAAQdKDfj//////fgMIsYAZIMw1DKREFwODAwM/4kNRKq64AADA4MjFDOQ6gKyY4HodMA49PMCxQYABgAVYHsjyZ1x7QAAAABJRU5ErkJggg==); +} + +table.treetable tr.expanded.accept td span.indenter a { + background-image: url(data:image/x-png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsTAAALEwEAmpwYAAAKT2lDQ1BQaG90b3Nob3AgSUNDIHByb2ZpbGUAAHjanVNnVFPpFj333vRCS4iAlEtvUhUIIFJCi4AUkSYqIQkQSoghodkVUcERRUUEG8igiAOOjoCMFVEsDIoK2AfkIaKOg6OIisr74Xuja9a89+bN/rXXPues852zzwfACAyWSDNRNYAMqUIeEeCDx8TG4eQuQIEKJHAAEAizZCFz/SMBAPh+PDwrIsAHvgABeNMLCADATZvAMByH/w/qQplcAYCEAcB0kThLCIAUAEB6jkKmAEBGAYCdmCZTAKAEAGDLY2LjAFAtAGAnf+bTAICd+Jl7AQBblCEVAaCRACATZYhEAGg7AKzPVopFAFgwABRmS8Q5ANgtADBJV2ZIALC3AMDOEAuyAAgMADBRiIUpAAR7AGDIIyN4AISZABRG8lc88SuuEOcqAAB4mbI8uSQ5RYFbCC1xB1dXLh4ozkkXKxQ2YQJhmkAuwnmZGTKBNA/g88wAAKCRFRHgg/P9eM4Ors7ONo62Dl8t6r8G/yJiYuP+5c+rcEAAAOF0ftH+LC+zGoA7BoBt/qIl7gRoXgugdfeLZrIPQLUAoOnaV/Nw+H48PEWhkLnZ2eXk5NhKxEJbYcpXff5nwl/AV/1s+X48/Pf14L7iJIEyXYFHBPjgwsz0TKUcz5IJhGLc5o9H/LcL//wd0yLESWK5WCoU41EScY5EmozzMqUiiUKSKcUl0v9k4t8s+wM+3zUAsGo+AXuRLahdYwP2SycQWHTA4vcAAPK7b8HUKAgDgGiD4c93/+8//UegJQCAZkmScQAAXkQkLlTKsz/HCAAARKCBKrBBG/TBGCzABhzBBdzBC/xgNoRCJMTCQhBCCmSAHHJgKayCQiiGzbAdKmAv1EAdNMBRaIaTcA4uwlW4Dj1wD/phCJ7BKLyBCQRByAgTYSHaiAFiilgjjggXmYX4IcFIBBKLJCDJiBRRIkuRNUgxUopUIFVIHfI9cgI5h1xGupE7yAAygvyGvEcxlIGyUT3UDLVDuag3GoRGogvQZHQxmo8WoJvQcrQaPYw2oefQq2gP2o8+Q8cwwOgYBzPEbDAuxsNCsTgsCZNjy7EirAyrxhqwVqwDu4n1Y8+xdwQSgUXACTYEd0IgYR5BSFhMWE7YSKggHCQ0EdoJNwkDhFHCJyKTqEu0JroR+cQYYjIxh1hILCPWEo8TLxB7iEPENyQSiUMyJ7mQAkmxpFTSEtJG0m5SI+ksqZs0SBojk8naZGuyBzmULCAryIXkneTD5DPkG+Qh8lsKnWJAcaT4U+IoUspqShnlEOU05QZlmDJBVaOaUt2ooVQRNY9aQq2htlKvUYeoEzR1mjnNgxZJS6WtopXTGmgXaPdpr+h0uhHdlR5Ol9BX0svpR+iX6AP0dwwNhhWDx4hnKBmbGAcYZxl3GK+YTKYZ04sZx1QwNzHrmOeZD5lvVVgqtip8FZHKCpVKlSaVGyovVKmqpqreqgtV81XLVI+pXlN9rkZVM1PjqQnUlqtVqp1Q61MbU2epO6iHqmeob1Q/pH5Z/YkGWcNMw09DpFGgsV/jvMYgC2MZs3gsIWsNq4Z1gTXEJrHN2Xx2KruY/R27iz2qqaE5QzNKM1ezUvOUZj8H45hx+Jx0TgnnKKeX836K3hTvKeIpG6Y0TLkxZVxrqpaXllirSKtRq0frvTau7aedpr1Fu1n7gQ5Bx0onXCdHZ4/OBZ3nU9lT3acKpxZNPTr1ri6qa6UbobtEd79up+6Ynr5egJ5Mb6feeb3n+hx9L/1U/W36p/VHDFgGswwkBtsMzhg8xTVxbzwdL8fb8VFDXcNAQ6VhlWGX4YSRudE8o9VGjUYPjGnGXOMk423GbcajJgYmISZLTepN7ppSTbmmKaY7TDtMx83MzaLN1pk1mz0x1zLnm+eb15vft2BaeFostqi2uGVJsuRaplnutrxuhVo5WaVYVVpds0atna0l1rutu6cRp7lOk06rntZnw7Dxtsm2qbcZsOXYBtuutm22fWFnYhdnt8Wuw+6TvZN9un2N/T0HDYfZDqsdWh1+c7RyFDpWOt6azpzuP33F9JbpL2dYzxDP2DPjthPLKcRpnVOb00dnF2e5c4PziIuJS4LLLpc+Lpsbxt3IveRKdPVxXeF60vWdm7Obwu2o26/uNu5p7ofcn8w0nymeWTNz0MPIQ+BR5dE/C5+VMGvfrH5PQ0+BZ7XnIy9jL5FXrdewt6V3qvdh7xc+9j5yn+M+4zw33jLeWV/MN8C3yLfLT8Nvnl+F30N/I/9k/3r/0QCngCUBZwOJgUGBWwL7+Hp8Ib+OPzrbZfay2e1BjKC5QRVBj4KtguXBrSFoyOyQrSH355jOkc5pDoVQfujW0Adh5mGLw34MJ4WHhVeGP45wiFga0TGXNXfR3ENz30T6RJZE3ptnMU85ry1KNSo+qi5qPNo3ujS6P8YuZlnM1VidWElsSxw5LiquNm5svt/87fOH4p3iC+N7F5gvyF1weaHOwvSFpxapLhIsOpZATIhOOJTwQRAqqBaMJfITdyWOCnnCHcJnIi/RNtGI2ENcKh5O8kgqTXqS7JG8NXkkxTOlLOW5hCepkLxMDUzdmzqeFpp2IG0yPTq9MYOSkZBxQqohTZO2Z+pn5mZ2y6xlhbL+xW6Lty8elQfJa7OQrAVZLQq2QqboVFoo1yoHsmdlV2a/zYnKOZarnivN7cyzytuQN5zvn//tEsIS4ZK2pYZLVy0dWOa9rGo5sjxxedsK4xUFK4ZWBqw8uIq2Km3VT6vtV5eufr0mek1rgV7ByoLBtQFr6wtVCuWFfevc1+1dT1gvWd+1YfqGnRs+FYmKrhTbF5cVf9go3HjlG4dvyr+Z3JS0qavEuWTPZtJm6ebeLZ5bDpaql+aXDm4N2dq0Dd9WtO319kXbL5fNKNu7g7ZDuaO/PLi8ZafJzs07P1SkVPRU+lQ27tLdtWHX+G7R7ht7vPY07NXbW7z3/T7JvttVAVVN1WbVZftJ+7P3P66Jqun4lvttXa1ObXHtxwPSA/0HIw6217nU1R3SPVRSj9Yr60cOxx++/p3vdy0NNg1VjZzG4iNwRHnk6fcJ3/ceDTradox7rOEH0x92HWcdL2pCmvKaRptTmvtbYlu6T8w+0dbq3nr8R9sfD5w0PFl5SvNUyWna6YLTk2fyz4ydlZ19fi753GDborZ752PO32oPb++6EHTh0kX/i+c7vDvOXPK4dPKy2+UTV7hXmq86X23qdOo8/pPTT8e7nLuarrlca7nuer21e2b36RueN87d9L158Rb/1tWeOT3dvfN6b/fF9/XfFt1+cif9zsu72Xcn7q28T7xf9EDtQdlD3YfVP1v+3Njv3H9qwHeg89HcR/cGhYPP/pH1jw9DBY+Zj8uGDYbrnjg+OTniP3L96fynQ89kzyaeF/6i/suuFxYvfvjV69fO0ZjRoZfyl5O/bXyl/erA6xmv28bCxh6+yXgzMV70VvvtwXfcdx3vo98PT+R8IH8o/2j5sfVT0Kf7kxmTk/8EA5jz/GMzLdsAAAAgY0hSTQAAeiUAAICDAAD5/wAAgOkAAHUwAADqYAAAOpgAABdvkl/FRgAAAFtJREFUeNpi/P//PwMlgImBQsA44C6giQENDAwM//HgBmLCAF/AMBLjBUeixf///48L7/+PCvZjU4fPAAc0AxywqcMXCwegGJ1NckL6jx5wpKYDxqGXEkkCgAEAmrqBIejdgngAAAAASUVORK5CYII=); +} \ No newline at end of file diff --git a/public/assets/js/extensions/group-by/bootstrap-table-group-by.js b/public/assets/js/extensions/group-by/bootstrap-table-group-by.js new file mode 100755 index 0000000000..6f95e61bdd --- /dev/null +++ b/public/assets/js/extensions/group-by/bootstrap-table-group-by.js @@ -0,0 +1,243 @@ +/** + * @author: Dennis Hernández + * @webSite: http://djhvscf.github.io/Blog + * @version: v1.1.0 + */ + +!function ($) { + + 'use strict'; + + var originalRowAttr, + dataTTId = 'data-tt-id', + dataTTParentId = 'data-tt-parent-id', + obj = {}, + parentId = undefined; + + var getParentRowId = function (that, id) { + var parentRows = that.$body.find('tr').not('[' + 'data-tt-parent-id]'); + + for (var i = 0; i < parentRows.length; i++) { + if (i === id) { + return $(parentRows[i]).attr('data-tt-id'); + } + } + + return undefined; + }; + + var sumData = function (that, data) { + var sumRow = {}; + $.each(data, function (i, row) { + if (!row.IsParent) { + for (var prop in row) { + if (!isNaN(parseFloat(row[prop]))) { + if (that.columns[$.fn.bootstrapTable.utils.getFieldIndex(that.columns, prop)].groupBySumGroup) { + if (sumRow[prop] === undefined) { + sumRow[prop] = 0; + } + sumRow[prop] += +row[prop]; + } + } + } + } + }); + return sumRow; + }; + + var rowAttr = function (row, index) { + //Call the User Defined Function + originalRowAttr.apply([row, index]); + + obj[dataTTId.toString()] = index; + + if (!row.IsParent) { + obj[dataTTParentId.toString()] = parentId === undefined ? index : parentId; + } else { + parentId = index; + delete obj[dataTTParentId.toString()]; + } + + return obj; + }; + + var setObjectKeys = function () { + // From https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys + Object.keys = function (o) { + if (o !== Object(o)) { + throw new TypeError('Object.keys called on a non-object'); + } + var k = [], + p; + for (p in o) { + if (Object.prototype.hasOwnProperty.call(o, p)) { + k.push(p); + } + } + return k; + } + }; + + var getDataArrayFromItem = function (that, item) { + var itemDataArray = []; + for (var i = 0; i < that.options.groupByField.length; i++) { + itemDataArray.push(item[that.options.groupByField[i]]); + } + + return itemDataArray; + }; + + var getNewRow = function (that, result, index) { + var newRow = {}; + for (var i = 0; i < that.options.groupByField.length; i++) { + newRow[that.options.groupByField[i].toString()] = result[index][0][that.options.groupByField[i]]; + } + + newRow.IsParent = true; + + return newRow; + }; + + var groupBy = function (array, f) { + var groups = {}; + $.each(array, function (i, o) { + var group = JSON.stringify(f(o)); + groups[group] = groups[group] || []; + groups[group].push(o); + }); + return Object.keys(groups).map(function (group) { + return groups[group]; + }); + }; + + var makeGrouped = function (that, data) { + var newData = [], + sumRow = {}; + + var result = groupBy(data, function (item) { + return getDataArrayFromItem(that, item); + }); + + for (var i = 0; i < result.length; i++) { + result[i].unshift(getNewRow(that, result, i)); + if (that.options.groupBySumGroup) { + sumRow = sumData(that, result[i]); + if (!$.isEmptyObject(sumRow)) { + result[i].push(sumRow); + } + } + } + + newData = newData.concat.apply(newData, result); + + if (!that.options.loaded && newData.length > 0) { + that.options.loaded = true; + that.options.originalData = that.options.data; + that.options.data = newData; + } + + return newData; + }; + + $.extend($.fn.bootstrapTable.defaults, { + groupBy: false, + groupByField: [], + groupBySumGroup: false, + groupByInitExpanded: undefined, //node, 'all' + //internal variables + loaded: false, + originalData: undefined + }); + + $.fn.bootstrapTable.methods.push('collapseAll', 'expandAll', 'refreshGroupByField'); + + $.extend($.fn.bootstrapTable.COLUMN_DEFAULTS, { + groupBySumGroup: false + }); + + var BootstrapTable = $.fn.bootstrapTable.Constructor, + _init = BootstrapTable.prototype.init, + _initData = BootstrapTable.prototype.initData; + + BootstrapTable.prototype.init = function () { + //Temporal validation + if (!this.options.sortName) { + if ((this.options.groupBy) && (this.options.groupByField.length > 0)) { + var that = this; + + // Compatibility: IE < 9 and old browsers + if (!Object.keys) { + setObjectKeys(); + } + + //Make sure that the internal variables are set correctly + this.options.loaded = false; + this.options.originalData = undefined; + + originalRowAttr = this.options.rowAttributes; + this.options.rowAttributes = rowAttr; + this.$el.on('post-body.bs.table', function () { + that.$el.treetable({ + expandable: true, + onNodeExpand: function () { + if (that.options.height) { + that.resetHeader(); + } + }, + onNodeCollapse: function () { + if (that.options.height) { + that.resetHeader(); + } + } + }, true); + + if (that.options.groupByInitExpanded !== undefined) { + if (typeof that.options.groupByInitExpanded === 'number') { + that.expandNode(that.options.groupByInitExpanded); + } else if (that.options.groupByInitExpanded.toLowerCase() === 'all') { + that.expandAll(); + } + } + }); + } + } + _init.apply(this, Array.prototype.slice.apply(arguments)); + }; + + BootstrapTable.prototype.initData = function (data, type) { + //Temporal validation + if (!this.options.sortName) { + if ((this.options.groupBy) && (this.options.groupByField.length > 0)) { + + this.options.groupByField = typeof this.options.groupByField === 'string' ? + this.options.groupByField.replace('[', '').replace(']', '') + .replace(/ /g, '').toLowerCase().split(',') : this.options.groupByField; + + data = makeGrouped(this, data ? data : this.options.data); + } + } + _initData.apply(this, [data, type]); + }; + + BootstrapTable.prototype.expandAll = function () { + this.$el.treetable('expandAll'); + }; + + BootstrapTable.prototype.collapseAll = function () { + this.$el.treetable('collapseAll'); + }; + + BootstrapTable.prototype.expandNode = function (id) { + id = getParentRowId(this, id); + if (id !== undefined) { + this.$el.treetable('expandNode', id); + } + }; + + BootstrapTable.prototype.refreshGroupByField = function (groupByFields) { + if (!$.fn.bootstrapTable.utils.compareObjects(this.options.groupByField, groupByFields)) { + this.options.groupByField = groupByFields; + this.load(this.options.originalData); + } + }; +}(jQuery); diff --git a/public/assets/js/extensions/key-events/README.md b/public/assets/js/extensions/key-events/README.md new file mode 100755 index 0000000000..efe21923bb --- /dev/null +++ b/public/assets/js/extensions/key-events/README.md @@ -0,0 +1,24 @@ +# Table Key Events + +Use Plugin: [bootstrap-table-key-events](https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/key-events) + +## Usage + +```html +<script src="extensions/key-events/bootstrap-table-key-events.js"></script> +``` + +## Options + +### keyEvents + +* type: Boolean +* description: +True to enable the key events. The key event list is: + * s: It will be focused the search textbox if it is enabled. + * r: It will refresh the table if the showRefresh option is enabled. + * t: It will toggle the table view if the showToggle option is enabled. + * p: It will fires the pagination switch if the showPaginationSwitch is enabled. + * left: It will go to prev page if the pagination is true. + * right: It will go to next page if the pagination is true. +* default: `false` diff --git a/public/assets/js/extensions/key-events/bootstrap-table-key-events.js b/public/assets/js/extensions/key-events/bootstrap-table-key-events.js old mode 100644 new mode 100755 index ee33565189..887f803562 --- a/public/assets/js/extensions/key-events/bootstrap-table-key-events.js +++ b/public/assets/js/extensions/key-events/bootstrap-table-key-events.js @@ -19,7 +19,6 @@ BootstrapTable.prototype.init = function () { _init.apply(this, Array.prototype.slice.apply(arguments)); - this.initKeyEvents(); }; diff --git a/public/assets/js/extensions/key-events/bootstrap-table-key-events.min.js b/public/assets/js/extensions/key-events/bootstrap-table-key-events.min.js deleted file mode 100644 index e82ad41730..0000000000 --- a/public/assets/js/extensions/key-events/bootstrap-table-key-events.min.js +++ /dev/null @@ -1,7 +0,0 @@ -/* -* bootstrap-table - v1.8.1 - 2015-05-29 -* https://github.com/wenzhixin/bootstrap-table -* Copyright (c) 2015 zhixin wen -* Licensed MIT License -*/ -!function(a){"use strict";a.extend(a.fn.bootstrapTable.defaults,{keyEvents:!1});var b=a.fn.bootstrapTable.Constructor,c=b.prototype.init;b.prototype.init=function(){c.apply(this,Array.prototype.slice.apply(arguments)),this.initKeyEvents()},b.prototype.initKeyEvents=function(){if(this.options.keyEvents){var b=this;a(document).off("keydown").on("keydown",function(a){var c=b.$toolbar.find(".search input"),d=b.$toolbar.find('button[name="refresh"]'),e=b.$toolbar.find('button[name="toggle"]'),f=b.$toolbar.find('button[name="paginationSwitch"]');if(document.activeElement===c.get(0))return!0;switch(a.keyCode){case 83:if(!b.options.search)return;return c.focus(),!1;case 82:if(!b.options.showRefresh)return;return d.click(),!1;case 84:if(!b.options.showToggle)return;return e.click(),!1;case 80:if(!b.options.showPaginationSwitch)return;return f.click(),!1;case 37:if(!b.options.pagination)return;return b.prevPage(),!1;case 39:if(!b.options.pagination)return;return void b.nextPage()}})}}}(jQuery); \ No newline at end of file diff --git a/public/assets/js/extensions/mobile/README.md b/public/assets/js/extensions/mobile/README.md new file mode 100755 index 0000000000..d526d782f3 --- /dev/null +++ b/public/assets/js/extensions/mobile/README.md @@ -0,0 +1,41 @@ +# Table Mobile + +Use Plugin: [bootstrap-table-mobile](https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/mobile) + +## Usage + +```html +<script src="extensions/mobile/bootstrap-table-mobile.js"></script> +``` + +## Options + +### mobileResponsive + +* type: Boolean +* description: Set true to change the view between card and table view depending on width and height given. +* default: `false` + +### checkOnInit + +* type: Boolean +* description: Set true to check the window size on init. +* default: `true` + +### minWidth + +* type: Integer +* description: Set the minimum width when the table will change the view. +* default: `562` + +### minHeight + +* type: Integer +* description: Set the minimum height when the table will change the view. +* default: `undefined` + +### columnsHidden + +* type: String +* description: Set the columns fields in this array in order to hide those columns in the cardView mode. Use this way in `data-*` configuration: ` data-columns-hidden="['name', 'description']"` or this way in javascript configuration: `columnsHidden = ['name', 'description']`. +* default: `undefined` diff --git a/public/assets/js/extensions/mobile/bootstrap-table-mobile.js b/public/assets/js/extensions/mobile/bootstrap-table-mobile.js old mode 100644 new mode 100755 index 0917821d49..2a373a55b9 --- a/public/assets/js/extensions/mobile/bootstrap-table-mobile.js +++ b/public/assets/js/extensions/mobile/bootstrap-table-mobile.js @@ -8,23 +8,35 @@ 'use strict'; + var showHideColumns = function (that, checked) { + if (that.options.columnsHidden.length > 0 ) { + $.each(that.columns, function (i, column) { + if (that.options.columnsHidden.indexOf(column.field) !== -1) { + if (column.visible !== checked) { + that.toggleColumn($.fn.bootstrapTable.utils.getFieldIndex(that.columns, column.field), checked, true); + } + } + }); + } + }; + var resetView = function (that) { if (that.options.height || that.options.showFooter) { - setTimeout(that.resetView(), 1); + setTimeout(that.resetView, 1); } }; var changeView = function (that, width, height) { if (that.options.minHeight) { - if (checkValuesLessEqual(width, that.options.minWidth) && checkValuesLessEqual(height, that.options.minHeight)) { + if ((width <= that.options.minWidth) && (height <= that.options.minHeight)) { conditionCardView(that); - } else if (checkValuesGreater(width, that.options.minWidth) && checkValuesGreater(height, that.options.minHeight)) { + } else if ((width > that.options.minWidth) && (height > that.options.minHeight)) { conditionFullView(that); } } else { - if (checkValuesLessEqual(width, that.options.minWidth)) { + if (width <= that.options.minWidth) { conditionCardView(that); - } else if (checkValuesGreater(width, that.options.minWidth)) { + } else if (width > that.options.minWidth) { conditionFullView(that); } } @@ -32,20 +44,14 @@ resetView(that); }; - var checkValuesLessEqual = function (currentValue, targetValue) { - return currentValue <= targetValue; - }; - - var checkValuesGreater = function (currentValue, targetValue) { - return currentValue > targetValue; - }; - var conditionCardView = function (that) { changeTableView(that, false); + showHideColumns(that, false); }; var conditionFullView = function (that) { changeTableView(that, true); + showHideColumns(that, true); }; var changeTableView = function (that, cardViewState) { @@ -53,12 +59,27 @@ that.toggleView(); }; + var debounce = function(func,wait) { + var timeout; + return function() { + var context = this, + args = arguments; + var later = function() { + timeout = null; + func.apply(context,args); + }; + clearTimeout(timeout); + timeout = setTimeout(later, wait); + }; + }; + $.extend($.fn.bootstrapTable.defaults, { mobileResponsive: false, minWidth: 562, minHeight: undefined, + heightThreshold: 100, // just slightly larger than mobile chrome's auto-hiding toolbar checkOnInit: true, - toggled: false + columnsHidden: [] }); var BootstrapTable = $.fn.bootstrapTable.Constructor, @@ -75,13 +96,34 @@ return; } - var that = this; - $(window).resize(function () { - changeView(that, $(this).width(), $(this).height()) - }); + var that = this, + old = { + width: $(window).width(), + height: $(window).height() + }; + + $(window).on('resize orientationchange',debounce(function (evt) { + // reset view if height has only changed by at least the threshold. + var height = $(this).height(), + width = $(this).width(); + + if (Math.abs(old.height - height) > that.options.heightThreshold || old.width != width) { + changeView(that, width, height); + old = { + width: width, + height: height + }; + } + },200)); if (this.options.checkOnInit) { - changeView(this, $(window).width(), $(window).height()); + var height = $(window).height(), + width = $(window).width(); + changeView(this, width, height); + old = { + width: width, + height: height + }; } }; }(jQuery); diff --git a/public/assets/js/extensions/mobile/bootstrap-table-mobile.min.js b/public/assets/js/extensions/mobile/bootstrap-table-mobile.min.js deleted file mode 100644 index 843975add6..0000000000 --- a/public/assets/js/extensions/mobile/bootstrap-table-mobile.min.js +++ /dev/null @@ -1,7 +0,0 @@ -/* -* bootstrap-table - v1.8.1 - 2015-05-29 -* https://github.com/wenzhixin/bootstrap-table -* Copyright (c) 2015 zhixin wen -* Licensed MIT License -*/ -!function(a){"use strict";var b=function(a){(a.options.height||a.options.showFooter)&&setTimeout(a.resetView(),1)},c=function(a,c,h){a.options.minHeight?d(c,a.options.minWidth)&&d(h,a.options.minHeight)?f(a):e(c,a.options.minWidth)&&e(h,a.options.minHeight)&&g(a):d(c,a.options.minWidth)?f(a):e(c,a.options.minWidth)&&g(a),b(a)},d=function(a,b){return b>=a},e=function(a,b){return a>b},f=function(a){h(a,!1)},g=function(a){h(a,!0)},h=function(a,b){a.options.cardView=b,a.toggleView()};a.extend(a.fn.bootstrapTable.defaults,{mobileResponsive:!1,minWidth:562,minHeight:void 0,checkOnInit:!0,toggled:!1});var i=a.fn.bootstrapTable.Constructor,j=i.prototype.init;i.prototype.init=function(){if(j.apply(this,Array.prototype.slice.apply(arguments)),this.options.mobileResponsive&&this.options.minWidth){var b=this;a(window).resize(function(){c(b,a(this).width(),a(this).height())}),this.options.checkOnInit&&c(this,a(window).width(),a(window).height())}}}(jQuery); \ No newline at end of file diff --git a/public/assets/js/extensions/multiple-search/README.md b/public/assets/js/extensions/multiple-search/README.md new file mode 100755 index 0000000000..c12cf0ddf1 --- /dev/null +++ b/public/assets/js/extensions/multiple-search/README.md @@ -0,0 +1,17 @@ +# Table Multiple Search + +Use Plugin: [bootstrap-table-multiple-search](https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/multiple-search) + +## Usage + +```html +<script src="extensions/multiple-search/bootstrap-table-multiple-search.js"></script> +``` + +## Options + +### multipleSearch + +* type: Boolean +* description: Set to true if you want to search by multiple columns. For example: if the user puts: "526 table" we are going to `split` that string and then we are going to search in all columns in the boostrap table. +* default: `false` diff --git a/public/assets/js/extensions/multiple-search/bootstrap-table-multiple-search.js b/public/assets/js/extensions/multiple-search/bootstrap-table-multiple-search.js new file mode 100755 index 0000000000..22df2ae933 --- /dev/null +++ b/public/assets/js/extensions/multiple-search/bootstrap-table-multiple-search.js @@ -0,0 +1,67 @@ +/** + * @author: Dennis Hernández + * @webSite: http://djhvscf.github.io/Blog + * @version: v1.0.0 + */ + +!function ($) { + + 'use strict'; + + $.extend($.fn.bootstrapTable.defaults, { + multipleSearch: false + }); + + var BootstrapTable = $.fn.bootstrapTable.Constructor, + _initSearch = BootstrapTable.prototype.initSearch; + + BootstrapTable.prototype.initSearch = function () { + if (this.options.multipleSearch) { + var strArray = this.searchText.split(" "), + that = this, + f = $.isEmptyObject(this.filterColumns) ? null : this.filterColumns, + dataFiltered = []; + + if (strArray.length === 1) { + _initSearch.apply(this, Array.prototype.slice.apply(arguments)); + } else { + for (var i = 0; i < strArray.length; i++) { + var str = strArray[i].trim(); + dataFiltered = str ? $.grep(dataFiltered.length === 0 ? this.options.data : dataFiltered, function (item, i) { + for (var key in item) { + key = $.isNumeric(key) ? parseInt(key, 10) : key; + var value = item[key], + column = that.columns[$.fn.bootstrapTable.utils.getFieldIndex(that.columns, key)], + j = $.inArray(key, that.header.fields); + + // Fix #142: search use formated data + if (column && column.searchFormatter) { + value = $.fn.bootstrapTable.utils.calculateObjectValue(column, + that.header.formatters[j], [value, item, i], value); + } + + var index = $.inArray(key, that.header.fields); + if (index !== -1 && that.header.searchables[index] && (typeof value === 'string' || typeof value === 'number')) { + if (that.options.strictSearch) { + if ((value + '').toLowerCase() === str) { + return true; + } + } else { + if ((value + '').toLowerCase().indexOf(str) !== -1) { + return true; + } + } + } + } + return false; + }) : this.data; + } + + this.data = dataFiltered; + } + } else { + _initSearch.apply(this, Array.prototype.slice.apply(arguments)); + } + }; + +}(jQuery); diff --git a/public/assets/js/extensions/multiple-sort/README.md b/public/assets/js/extensions/multiple-sort/README.md new file mode 100755 index 0000000000..fc51b21d7d --- /dev/null +++ b/public/assets/js/extensions/multiple-sort/README.md @@ -0,0 +1,91 @@ +# Table Multiple Sort + +Use Plugin: [bootstrap-table-multiple-sort](https://github.com/dimbslmh/bootstrap-table/tree/master/src/extensions/multiple-sort) + +## Usage + +```html +<script src="extensions/multiple-sort/bootstrap-table-multiple-sort.js"></script> +``` + +## Options + +### showMultiSort + +* type: Boolean +* description: Set true to allow the multiple sort. +* default: `false` + +### sortPriority + +* type: Object +* description: Set one or multiple sort priority. Example: '[{"sortName": "forks_count","sortOrder":"desc"},{"sortName":"stargazers_count","sortOrder":"desc"}]' +* default: null + +### Icons +* sort: `glyphicon-sort` +* plus: `glyphicon-plus` +* minus: `glyphicon-minus` + +## Locales + +### formatMultipleSort + +* description: Title of the advanced search modal +* default: `Multiple Sort` + +### formatAddLevel + +* description: Text of the add level button +* default: `Add Level` + +### formatDeleteLevel + +* description: Text of the delete level button +* default: `Delete Level` + +### formatColumn + +* description: Text of Column header +* default: `Column` + +### formatOrder + +* description: Text of the delete level button +* default: `Order` + +### formatSortBy + +* description: Text of the delete level button +* default: `Sort by` + +### formatThenBy + +* description: Text of the delete level button +* default: `Then by` + +### formatSort + +* description: Text of the delete level button +* default: `Sort` + +### formatCancel + +* description: Text of the delete level button +* default: `Cancel` + +### formatDuplicateAlertTitle + +* description: Title of the duplicate alert +* default: `Duplicate(s) detected!` + +### formatDuplicateAlertDescription + +* description: Text of the duplicate alert +* default: `Please remove or change any duplicate column.` + +## Events + +### onMultipleSort(multiple-sort.bs.table) + +* Fires when sorting with one or multiple Sort Priority. diff --git a/public/assets/js/extensions/multiple-sort/bootstrap-table-multiple-sort.js b/public/assets/js/extensions/multiple-sort/bootstrap-table-multiple-sort.js old mode 100644 new mode 100755 index fc8bb1c4e7..68f6a52f19 --- a/public/assets/js/extensions/multiple-sort/bootstrap-table-multiple-sort.js +++ b/public/assets/js/extensions/multiple-sort/bootstrap-table-multiple-sort.js @@ -10,25 +10,21 @@ var isSingleSort = false; var sort_order = { - asc: 'Ascending', - desc: 'Descending' - }, - arrowAsc = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAATCAYAAAByUDbMAAAAZ' + - '0lEQVQ4y2NgGLKgquEuFxBPAGI2ahhWCsS/gDibUoO0gPgxEP8H4ttArEyuQYxAPBd' + - 'qEAxPBImTY5gjEL9DM+wTENuQahAvEO9DMwiGdwAxOymGJQLxTyD+jgWDxCMZRsEoGAVo' + - 'AADeemwtPcZI2wAAAABJRU5ErkJggg==', - arrowDesc = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAATCAYAAAByUDbMAAAAZUlEQVQ4y2NgGAWj' + - 'YBSggaqGu5FA/BOIv2PBIPFEUgxjB+IdQPwfC94HxLykus4GiD+hGfQOiB3J8SojEE9EM2wuSJ' + - 'zcsFMG4ttQgx4DsRalkZENxL+AuJQaMcsGxBOAmGvopk8AVz1sLZgg0bsAAAAASUVORK5CYII= '; + asc: 'Ascending', + desc: 'Descending' + }; var showSortModal = function(that) { - if (!$("#sortModal").hasClass("modal")) { - var sModal = ' <div class="modal fade" id="sortModal" tabindex="-1" role="dialog" aria-labelledby="sortModalLabel" aria-hidden="true">'; + var _selector = that.$sortModal.selector, + _id = _selector.substr(1); + + if (!$(_id).hasClass("modal")) { + var sModal = ' <div class="modal fade" id="' + _id + '" tabindex="-1" role="dialog" aria-labelledby="' + _id + 'Label" aria-hidden="true">'; sModal += ' <div class="modal-dialog">'; sModal += ' <div class="modal-content">'; sModal += ' <div class="modal-header">'; sModal += ' <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>'; - sModal += ' <h4 class="modal-title" id="sortModalLabel">' + that.options.formatMultipleSort() + '</h4>'; + sModal += ' <h4 class="modal-title" id="' + _id + 'Label">' + that.options.formatMultipleSort() + '</h4>'; sModal += ' </div>'; sModal += ' <div class="modal-body">'; sModal += ' <div class="bootstrap-table">'; @@ -64,12 +60,12 @@ $("body").append($(sModal)); - var $sortModal = $('#sortModal'), - $rows = $sortModal.find("tbody > tr"); + that.$sortModal = $(_selector); + var $rows = that.$sortModal.find("tbody > tr"); - $sortModal.off('click', '#add').on('click', '#add', function() { - var total = $sortModal.find('.multi-sort-name:first option').length, - current = $sortModal.find('tbody tr').length; + that.$sortModal.off('click', '#add').on('click', '#add', function() { + var total = that.$sortModal.find('.multi-sort-name:first option').length, + current = that.$sortModal.find('tbody tr').length; if (current < total) { current++; @@ -78,20 +74,20 @@ } }); - $sortModal.off('click', '#delete').on('click', '#delete', function() { - var total = $sortModal.find('.multi-sort-name:first option').length, - current = $sortModal.find('tbody tr').length; + that.$sortModal.off('click', '#delete').on('click', '#delete', function() { + var total = that.$sortModal.find('.multi-sort-name:first option').length, + current = that.$sortModal.find('tbody tr').length; if (current > 1 && current <= total) { current--; - $sortModal.find('tbody tr:last').remove(); + that.$sortModal.find('tbody tr:last').remove(); that.setButtonStates(); } }); - $sortModal.off('click', '.btn-primary').on('click', '.btn-primary', function() { - var $rows = $sortModal.find("tbody > tr"), - $alert = $sortModal.find('div.alert'), + that.$sortModal.off('click', '.btn-primary').on('click', '.btn-primary', function() { + var $rows = that.$sortModal.find("tbody > tr"), + $alert = that.$sortModal.find('div.alert'), fields = [], results = []; @@ -120,7 +116,7 @@ if (results.length > 0) { if ($alert.length === 0) { $alert = '<div class="alert alert-danger" role="alert"><strong>' + that.options.formatDuplicateAlertTitle() + '</strong> ' + that.options.formatDuplicateAlertDescription() + '</div>'; - $($alert).insertBefore($sortModal.find('.bars')); + $($alert).insertBefore(that.$sortModal.find('.bars')); } } else { if ($alert.length === 1) { @@ -129,11 +125,11 @@ that.options.sortName = ""; that.onMultipleSort(); - $sortModal.modal('hide'); + that.$sortModal.modal('hide'); } }); - if (that.options.sortPriority === null) { + if (that.options.sortPriority === null || that.options.sortPriority.length === 0) { if (that.options.sortName) { that.options.sortPriority = [{ sortName: that.options.sortName, @@ -141,8 +137,8 @@ }]; } } - - if (that.options.sortPriority !== null) { + + if (that.options.sortPriority !== null && that.options.sortPriority.length > 0) { if ($rows.length < that.options.sortPriority.length && typeof that.options.sortPriority === 'object') { for (var i = 0; i < that.options.sortPriority.length; i++) { that.addLevel(i, that.options.sortPriority[i]); @@ -217,16 +213,18 @@ BootstrapTable.prototype.initToolbar = function() { this.showToolbar = true; - var that = this; + var that = this, + sortModalId = '#sortModal_' + this.$el.attr('id'); + this.$sortModal = $(sortModalId); _initToolbar.apply(this, Array.prototype.slice.apply(arguments)); if (this.options.showMultiSort) { - var $btnGroup = this.$toolbar.find('>.btn-group'), - $multiSortBtn = $btnGroup.find('div.multi-sort'); + var $btnGroup = this.$toolbar.find('>.btn-group').first(), + $multiSortBtn = this.$toolbar.find('div.multi-sort'); if (!$multiSortBtn.length) { - $multiSortBtn = ' <button class="multi-sort btn btn-default' + (this.options.iconSize === undefined ? '' : ' btn-' + this.options.iconSize) + '" type="button" data-toggle="modal" data-target="#sortModal" title="' + this.options.formatMultipleSort() + '">'; + $multiSortBtn = ' <button class="multi-sort btn btn-default' + (this.options.iconSize === undefined ? '' : ' btn-' + this.options.iconSize) + '" type="button" data-toggle="modal" data-target="' + sortModalId + '" title="' + this.options.formatMultipleSort() + '">'; $multiSortBtn += ' <i class="' + this.options.iconsPrefix + ' ' + this.options.icons.sort + '"></i>'; $multiSortBtn += '</button>'; @@ -235,7 +233,7 @@ showSortModal(that); } - this.$el.one('sort.bs.table', function() { + this.$el.on('sort.bs.table', function() { isSingleSort = true; }); @@ -249,17 +247,29 @@ } }); - this.$el.on('column-switch.bs.table', function() { - that.options.sortPriority = null; - $('#sortModal').remove(); + this.$el.on('column-switch.bs.table', function(field, checked) { + for (var i = 0; i < that.options.sortPriority.length; i++) { + if (that.options.sortPriority[i].sortName === checked) { + that.options.sortPriority.splice(i, 1); + } + } + + that.assignSortableArrows(); + that.$sortModal.remove(); showSortModal(that); }); + + this.$el.on('reset-view.bs.table', function() { + if (!isSingleSort && that.options.sortPriority !== null && typeof that.options.sortPriority === 'object') { + that.assignSortableArrows(); + } + }); } }; BootstrapTable.prototype.onMultipleSort = function() { var that = this; - + var cmp = function(x, y) { return x > y ? 1 : x < y ? -1 : 0; }; @@ -306,20 +316,19 @@ }; BootstrapTable.prototype.addLevel = function(index, sortPriority) { - var $sortModal = $("#sortModal"), - text = index === 0 ? this.options.formatSortBy() : this.options.formatThenBy(); + var text = index === 0 ? this.options.formatSortBy() : this.options.formatThenBy(); - $sortModal.find('tbody') + this.$sortModal.find('tbody') .append($('<tr>') .append($('<td>').text(text)) .append($('<td>').append($('<select class="form-control multi-sort-name">'))) .append($('<td>').append($('<select class="form-control multi-sort-order">'))) - ); + ); - var $multiSortName = $sortModal.find('.multi-sort-name').last(), - $multiSortOrder = $sortModal.find('.multi-sort-order').last(); + var $multiSortName = this.$sortModal.find('.multi-sort-name').last(), + $multiSortOrder = this.$sortModal.find('.multi-sort-order').last(); - this.options.columns.forEach(function(column) { + $.each(this.columns, function (i, column) { if (column.sortable === false || column.visible === false) { return true; } @@ -343,28 +352,27 @@ for (var i = 0; i < headers.length; i++) { for (var c = 0; c < that.options.sortPriority.length; c++) { if ($(headers[i]).data('field') === that.options.sortPriority[c].sortName) { - $(headers[i]).find('.sortable').css('background-image', 'url(' + (that.options.sortPriority[c].sortOrder === 'desc' ? arrowDesc : arrowAsc) + ')'); + $(headers[i]).find('.sortable').removeClass('desc asc').addClass(that.options.sortPriority[c].sortOrder); } } } }; BootstrapTable.prototype.setButtonStates = function() { - var $sortModal = $('#sortModal'), - total = $sortModal.find('.multi-sort-name:first option').length, - current = $sortModal.find('tbody tr').length; + var total = this.$sortModal.find('.multi-sort-name:first option').length, + current = this.$sortModal.find('tbody tr').length; if (current == total) { - $sortModal.find('#add').attr('disabled', 'disabled'); + this.$sortModal.find('#add').attr('disabled', 'disabled'); } if (current > 1) { - $sortModal.find('#delete').removeAttr('disabled'); + this.$sortModal.find('#delete').removeAttr('disabled'); } if (current < total) { - $sortModal.find('#add').removeAttr('disabled'); + this.$sortModal.find('#add').removeAttr('disabled'); } if (current == 1) { - $sortModal.find('#delete').attr('disabled', 'disabled'); + this.$sortModal.find('#delete').attr('disabled', 'disabled'); } }; })(jQuery); diff --git a/public/assets/js/extensions/multiple-sort/bootstrap-table-multiple-sort.min.js b/public/assets/js/extensions/multiple-sort/bootstrap-table-multiple-sort.min.js deleted file mode 100644 index dbcf11a11f..0000000000 --- a/public/assets/js/extensions/multiple-sort/bootstrap-table-multiple-sort.min.js +++ /dev/null @@ -1,7 +0,0 @@ -/* -* bootstrap-table - v1.8.1 - 2015-05-29 -* https://github.com/wenzhixin/bootstrap-table -* Copyright (c) 2015 zhixin wen -* Licensed MIT License -*/ -!function(a){"use strict";var b=!1,c={asc:"Ascending",desc:"Descending"},d="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAATCAYAAAByUDbMAAAAZ0lEQVQ4y2NgGLKgquEuFxBPAGI2ahhWCsS/gDibUoO0gPgxEP8H4ttArEyuQYxAPBdqEAxPBImTY5gjEL9DM+wTENuQahAvEO9DMwiGdwAxOymGJQLxTyD+jgWDxCMZRsEoGAVoAADeemwtPcZI2wAAAABJRU5ErkJggg==",e="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAATCAYAAAByUDbMAAAAZUlEQVQ4y2NgGAWjYBSggaqGu5FA/BOIv2PBIPFEUgxjB+IdQPwfC94HxLykus4GiD+hGfQOiB3J8SojEE9EM2wuSJzcsFMG4ttQgx4DsRalkZENxL+AuJQaMcsGxBOAmGvopk8AVz1sLZgg0bsAAAAASUVORK5CYII= ",f=function(b){if(!a("#sortModal").hasClass("modal")){var c=' <div class="modal fade" id="sortModal" tabindex="-1" role="dialog" aria-labelledby="sortModalLabel" aria-hidden="true">';c+=' <div class="modal-dialog">',c+=' <div class="modal-content">',c+=' <div class="modal-header">',c+=' <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>',c+=' <h4 class="modal-title" id="sortModalLabel">'+b.options.formatMultipleSort()+"</h4>",c+=" </div>",c+=' <div class="modal-body">',c+=' <div class="bootstrap-table">',c+=' <div class="fixed-table-toolbar">',c+=' <div class="bars">',c+=' <div id="toolbar">',c+=' <button id="add" type="button" class="btn btn-default"><i class="'+b.options.iconsPrefix+" "+b.options.icons.plus+'"></i> '+b.options.formatAddLevel()+"</button>",c+=' <button id="delete" type="button" class="btn btn-default" disabled><i class="'+b.options.iconsPrefix+" "+b.options.icons.minus+'"></i> '+b.options.formatDeleteLevel()+"</button>",c+=" </div>",c+=" </div>",c+=" </div>",c+=' <div class="fixed-table-container">',c+=' <table id="multi-sort" class="table">',c+=" <thead>",c+=" <tr>",c+=" <th></th>",c+=' <th><div class="th-inner">'+b.options.formatColumn()+"</div></th>",c+=' <th><div class="th-inner">'+b.options.formatOrder()+"</div></th>",c+=" </tr>",c+=" </thead>",c+=" <tbody></tbody>",c+=" </table>",c+=" </div>",c+=" </div>",c+=" </div>",c+=' <div class="modal-footer">',c+=' <button type="button" class="btn btn-default" data-dismiss="modal">'+b.options.formatCancel()+"</button>",c+=' <button type="button" class="btn btn-primary">'+b.options.formatSort()+"</button>",c+=" </div>",c+=" </div>",c+=" </div>",c+=" </div>",a("body").append(a(c));var d=a("#sortModal"),e=d.find("tbody > tr");if(d.off("click","#add").on("click","#add",function(){var a=d.find(".multi-sort-name:first option").length,c=d.find("tbody tr").length;a>c&&(c++,b.addLevel(),b.setButtonStates())}),d.off("click","#delete").on("click","#delete",function(){var a=d.find(".multi-sort-name:first option").length,c=d.find("tbody tr").length;c>1&&a>=c&&(c--,d.find("tbody tr:last").remove(),b.setButtonStates())}),d.off("click",".btn-primary").on("click",".btn-primary",function(){var c=d.find("tbody > tr"),e=d.find("div.alert"),f=[],g=[];b.options.sortPriority=a.map(c,function(b){var c=a(b),d=c.find(".multi-sort-name").val(),e=c.find(".multi-sort-order").val();return f.push(d),{sortName:d,sortOrder:e}});for(var h=f.sort(),i=0;i<f.length-1;i++)h[i+1]==h[i]&&g.push(h[i]);g.length>0?0===e.length&&(e='<div class="alert alert-danger" role="alert"><strong>'+b.options.formatDuplicateAlertTitle()+"</strong> "+b.options.formatDuplicateAlertDescription()+"</div>",a(e).insertBefore(d.find(".bars"))):(1===e.length&&a(e).remove(),b.options.sortName="",b.onMultipleSort(),d.modal("hide"))}),null===b.options.sortPriority&&b.options.sortName&&(b.options.sortPriority=[{sortName:b.options.sortName,sortOrder:b.options.sortOrder}]),null!==b.options.sortPriority){if(e.length<b.options.sortPriority.length&&"object"==typeof b.options.sortPriority)for(var f=0;f<b.options.sortPriority.length;f++)b.addLevel(f,b.options.sortPriority[f])}else b.addLevel(0);b.setButtonStates()}};a.extend(a.fn.bootstrapTable.defaults,{showMultiSort:!1,sortPriority:null,onMultipleSort:function(){return!1}}),a.extend(a.fn.bootstrapTable.defaults.icons,{sort:"glyphicon-sort",plus:"glyphicon-plus",minus:"glyphicon-minus"}),a.extend(a.fn.bootstrapTable.Constructor.EVENTS,{"multiple-sort.bs.table":"onMultipleSort"}),a.extend(a.fn.bootstrapTable.locales,{formatMultipleSort:function(){return"Multiple Sort"},formatAddLevel:function(){return"Add Level"},formatDeleteLevel:function(){return"Delete Level"},formatColumn:function(){return"Column"},formatOrder:function(){return"Order"},formatSortBy:function(){return"Sort by"},formatThenBy:function(){return"Then by"},formatSort:function(){return"Sort"},formatCancel:function(){return"Cancel"},formatDuplicateAlertTitle:function(){return"Duplicate(s) detected!"},formatDuplicateAlertDescription:function(){return"Please remove or change any duplicate column."}}),a.extend(a.fn.bootstrapTable.defaults,a.fn.bootstrapTable.locales);var g=a.fn.bootstrapTable.Constructor,h=g.prototype.initToolbar;g.prototype.initToolbar=function(){this.showToolbar=!0;var c=this;if(h.apply(this,Array.prototype.slice.apply(arguments)),this.options.showMultiSort){var d=this.$toolbar.find(">.btn-group"),e=d.find("div.multi-sort");e.length||(e=' <button class="multi-sort btn btn-default'+(void 0===this.options.iconSize?"":" btn-"+this.options.iconSize)+'" type="button" data-toggle="modal" data-target="#sortModal" title="'+this.options.formatMultipleSort()+'">',e+=' <i class="'+this.options.iconsPrefix+" "+this.options.icons.sort+'"></i>',e+="</button>",d.append(e),f(c)),this.$el.one("sort.bs.table",function(){b=!0}),this.$el.on("multiple-sort.bs.table",function(){b=!1}),this.$el.on("load-success.bs.table",function(){b||null===c.options.sortPriority||"object"!=typeof c.options.sortPriority||c.onMultipleSort()}),this.$el.on("column-switch.bs.table",function(){c.options.sortPriority=null,a("#sortModal").remove(),f(c)})}},g.prototype.onMultipleSort=function(){var b=this,c=function(a,b){return a>b?1:b>a?-1:0},d=function(d,e){for(var f=[],g=[],h=0;h<b.options.sortPriority.length;h++){var i="desc"===b.options.sortPriority[h].sortOrder?-1:1,j=d[b.options.sortPriority[h].sortName],k=e[b.options.sortPriority[h].sortName];(void 0===j||null===j)&&(j=""),(void 0===k||null===k)&&(k=""),a.isNumeric(j)&&a.isNumeric(k)&&(j=parseFloat(j),k=parseFloat(k)),"string"!=typeof j&&(j=j.toString()),f.push(i*c(j,k)),g.push(i*c(k,j))}return c(f,g)};this.data.sort(function(a,b){return d(a,b)}),this.initBody(),this.assignSortableArrows(),this.trigger("multiple-sort")},g.prototype.addLevel=function(b,d){var e=a("#sortModal"),f=0===b?this.options.formatSortBy():this.options.formatThenBy();e.find("tbody").append(a("<tr>").append(a("<td>").text(f)).append(a("<td>").append(a('<select class="form-control multi-sort-name">'))).append(a("<td>").append(a('<select class="form-control multi-sort-order">'))));var g=e.find(".multi-sort-name").last(),h=e.find(".multi-sort-order").last();this.options.columns.forEach(function(a){return a.sortable===!1||a.visible===!1?!0:void g.append('<option value="'+a.field+'">'+a.title+"</option>")}),a.each(c,function(a,b){h.append('<option value="'+a+'">'+b+"</option>")}),void 0!==d&&(g.find('option[value="'+d.sortName+'"]').attr("selected",!0),h.find('option[value="'+d.sortOrder+'"]').attr("selected",!0))},g.prototype.assignSortableArrows=function(){for(var b=this,c=b.$header.find("th"),f=0;f<c.length;f++)for(var g=0;g<b.options.sortPriority.length;g++)a(c[f]).data("field")===b.options.sortPriority[g].sortName&&a(c[f]).find(".sortable").css("background-image","url("+("desc"===b.options.sortPriority[g].sortOrder?e:d)+")")},g.prototype.setButtonStates=function(){var b=a("#sortModal"),c=b.find(".multi-sort-name:first option").length,d=b.find("tbody tr").length;d==c&&b.find("#add").attr("disabled","disabled"),d>1&&b.find("#delete").removeAttr("disabled"),c>d&&b.find("#add").removeAttr("disabled"),1==d&&b.find("#delete").attr("disabled","disabled")}}(jQuery); \ No newline at end of file diff --git a/public/assets/js/extensions/natural-sorting/README.md b/public/assets/js/extensions/natural-sorting/README.md new file mode 100755 index 0000000000..fbc01782a9 --- /dev/null +++ b/public/assets/js/extensions/natural-sorting/README.md @@ -0,0 +1,13 @@ +# Table Natural Sorting + +Use Plugin: [bootstrap-table-natural-sorting](https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/natural-sorting) + +## Usage + +```html +<script src="extensions/natural-sorting/bootstrap-table-natural-sorting.js"></script> +``` + +### Options + +* Just add data-sorter="alphanum" to any th \ No newline at end of file diff --git a/public/assets/js/extensions/natural-sorting/bootstrap-table-natural-sorting.js b/public/assets/js/extensions/natural-sorting/bootstrap-table-natural-sorting.js old mode 100644 new mode 100755 diff --git a/public/assets/js/extensions/natural-sorting/bootstrap-table-natural-sorting.min.js b/public/assets/js/extensions/natural-sorting/bootstrap-table-natural-sorting.min.js deleted file mode 100644 index 3d1130f722..0000000000 --- a/public/assets/js/extensions/natural-sorting/bootstrap-table-natural-sorting.min.js +++ /dev/null @@ -1,7 +0,0 @@ -/* -* bootstrap-table - v1.8.1 - 2015-05-29 -* https://github.com/wenzhixin/bootstrap-table -* Copyright (c) 2015 zhixin wen -* Licensed MIT License -*/ -function alphanum(a,b){function c(a){for(var b,c,d=[],e=0,f=-1,g=0;b=(c=a.charAt(e++)).charCodeAt(0);){var h=46===b||b>=48&&57>=b;h!==g&&(d[++f]="",g=h),d[f]+=c}return d}var d=c(a),e=c(b);for(x=0;d[x]&&e[x];x++)if(d[x]!==e[x]){var f=Number(d[x]),g=Number(e[x]);return f==d[x]&&g==e[x]?f-g:d[x]>e[x]?1:-1}return d.length-e.length} \ No newline at end of file diff --git a/public/assets/js/extensions/reorder-columns/README.md b/public/assets/js/extensions/reorder-columns/README.md new file mode 100755 index 0000000000..3a7868db6f --- /dev/null +++ b/public/assets/js/extensions/reorder-columns/README.md @@ -0,0 +1,41 @@ +# Table Reorder Columns + +Use Plugin: [bootstrap-table-reorder-columns](https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/reorder-columns) </br> +Dependence: [dragTable](https://github.com/akottr/dragtable/) v2.0.14 (must include the css file), </br> +[jquery-ui](https://code.jquery.com/ui/) v1.11 + + +## Usage + +```html +<link rel="stylesheet" href=".../dragtable.css"> +<script src=".../jquery-ui.js"></script> +<script src=".../jquery.dragtable.js"></script> +<script src="extensions/reorder-columns/bootstrap-table-reorder-columns.js"></script> +``` + +## Options + +### reorderableColumns + +* type: Boolean +* description: Set true to allow the reorder feature. +* default: `false` + +### maxMovingRows + +* type: Integer +* description: Moving only the header. Recommended for very large tables (cells > 1000) +* default: `10` + +### dragaccept + +* type: String +* description: Allow to drag only the rows that have the css class as attribute. +* default: `null` + +## Events + +### onReorderColumn(reorder-column.bs.table) + +Fired when the column was dropped, receive as parameter the new header fields order \ No newline at end of file diff --git a/public/assets/js/extensions/reorder-columns/bootstrap-table-reorder-columns.js b/public/assets/js/extensions/reorder-columns/bootstrap-table-reorder-columns.js old mode 100644 new mode 100755 index 7ae94b3414..0c8b8b3f7e --- a/public/assets/js/extensions/reorder-columns/bootstrap-table-reorder-columns.js +++ b/public/assets/js/extensions/reorder-columns/bootstrap-table-reorder-columns.js @@ -8,25 +8,13 @@ 'use strict'; - var getFieldIndex = function (columns, field) { - var index = -1; - - $.each(columns, function (i, column) { - if (column.field === field) { - index = i; - return false; - } - return true; - }); - return index; - }; - $.extend($.fn.bootstrapTable.defaults, { reorderableColumns: false, maxMovingRows: 10, onReorderColumn: function (headerFields) { return false; - } + }, + dragaccept: null }); $.extend($.fn.bootstrapTable.Constructor.EVENTS, { @@ -84,35 +72,50 @@ }; BootstrapTable.prototype.makeRowsReorderable = function () { - var that = this; try { $(this.$el).dragtable('destroy'); } catch (e) {} $(this.$el).dragtable({ maxMovingRows: that.options.maxMovingRows, + dragaccept: that.options.dragaccept, clickDelay:200, beforeStop: function() { var ths = [], + formatters = [], columns = [], + columnsHidden = [], columnIndex = -1; that.$header.find('th').each(function (i) { ths.push($(this).data('field')); + formatters.push($(this).data('formatter')); }); - for (var i = 0; i < ths.length; i++ ) { - columnIndex = getFieldIndex(that.options.columns, ths[i]); - if (columnIndex !== -1) { - columns.push(that.options.columns[columnIndex]); - that.options.columns.splice(columnIndex, 1); + //Exist columns not shown + if (ths.length < that.columns.length) { + columnsHidden = $.grep(that.columns, function (column) { + return !column.visible; + }); + for (var i = 0; i < columnsHidden.length; i++) { + ths.push(columnsHidden[i].field); + formatters.push(columnsHidden[i].formatter); } } - that.options.columns = that.options.columns.concat(columns); + for (var i = 0; i < ths.length; i++ ) { + columnIndex = $.fn.bootstrapTable.utils.getFieldIndex(that.columns, ths[i]); + if (columnIndex !== -1) { + columns.push(that.columns[columnIndex]); + that.columns.splice(columnIndex, 1); + } + } + + that.columns = that.columns.concat(columns); that.header.fields = ths; + that.header.formatters = formatters; that.resetView(); that.trigger('reorder-column', ths); } }); }; -}(jQuery); \ No newline at end of file +}(jQuery); diff --git a/public/assets/js/extensions/reorder-columns/bootstrap-table-reorder-columns.min.js b/public/assets/js/extensions/reorder-columns/bootstrap-table-reorder-columns.min.js deleted file mode 100644 index 466c379311..0000000000 --- a/public/assets/js/extensions/reorder-columns/bootstrap-table-reorder-columns.min.js +++ /dev/null @@ -1,7 +0,0 @@ -/* -* bootstrap-table - v1.8.1 - 2015-05-29 -* https://github.com/wenzhixin/bootstrap-table -* Copyright (c) 2015 zhixin wen -* Licensed MIT License -*/ -!function(a){"use strict";var b=function(b,c){var d=-1;return a.each(b,function(a,b){return b.field===c?(d=a,!1):!0}),d};a.extend(a.fn.bootstrapTable.defaults,{reorderableColumns:!1,maxMovingRows:10,onReorderColumn:function(){return!1}}),a.extend(a.fn.bootstrapTable.Constructor.EVENTS,{"reorder-column.bs.table":"onReorderColumn"});var c=a.fn.bootstrapTable.Constructor,d=c.prototype.initHeader,e=c.prototype.toggleColumn,f=c.prototype.toggleView,g=c.prototype.resetView;c.prototype.initHeader=function(){d.apply(this,Array.prototype.slice.apply(arguments)),this.options.reorderableColumns&&this.makeRowsReorderable()},c.prototype.toggleColumn=function(){e.apply(this,Array.prototype.slice.apply(arguments)),this.options.reorderableColumns&&this.makeRowsReorderable()},c.prototype.toggleView=function(){f.apply(this,Array.prototype.slice.apply(arguments)),this.options.reorderableColumns&&(this.options.cardView||this.makeRowsReorderable())},c.prototype.resetView=function(){g.apply(this,Array.prototype.slice.apply(arguments)),this.options.reorderableColumns&&this.makeRowsReorderable()},c.prototype.makeRowsReorderable=function(){var c=this;try{a(this.$el).dragtable("destroy")}catch(d){}a(this.$el).dragtable({maxMovingRows:c.options.maxMovingRows,clickDelay:200,beforeStop:function(){var d=[],e=[],f=-1;c.$header.find("th").each(function(){d.push(a(this).data("field"))});for(var g=0;g<d.length;g++)f=b(c.options.columns,d[g]),-1!==f&&(e.push(c.options.columns[f]),c.options.columns.splice(f,1));c.options.columns=c.options.columns.concat(e),c.header.fields=d,c.resetView(),c.trigger("reorder-column",d)}})}}(jQuery); \ No newline at end of file diff --git a/public/assets/js/extensions/reorder-rows/README.md b/public/assets/js/extensions/reorder-rows/README.md new file mode 100755 index 0000000000..07d83ea89a --- /dev/null +++ b/public/assets/js/extensions/reorder-rows/README.md @@ -0,0 +1,74 @@ +# Table Reorder Rows + +Use Plugin: [bootstrap-table-reorder-rows](https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/reorder-rows) </br> +Dependence: [tablednd](https://github.com/isocra/TableDnD) v0.9, </br> +if you want you can include the bootstrap-table-reorder-rows.css file to use the default dragClass + + +## Usage + +```html +<link rel="stylesheet" href=".../bootstrap-table-reorder-rows.css"> +<script src=".../jquery.tablednd.js"></script> +<script src="extensions/reorder-rows/bootstrap-table-reorder-rows.js"></script> +``` + +## Options + +### reorderableRows + +* type: Boolean +* description: Set true to allow the reorder feature. +* default: `false` + +### onDragStyle + +* type: String +* description: This is the style that is assigned to the row during drag. There are limitations to the styles that can be associated with a row (such as you can't assign a border�well you can, but it won't be displayed). +* default: `null` + +### onDropStyle + +* type: String +* description: This is the style that is assigned to the row when it is dropped. As for onDragStyle, there are limitations to what you can do. Also this replaces the original style, so again consider using onDragClass which is simply added and then removed on drop. +* default: `null` + +### onDragClass + +* type: String +* description: This class is added for the duration of the drag and then removed when the row is dropped. It is more flexible than using onDragStyle since it can be inherited by the row cells and other content. +* default: `reorder_rows_onDragClass` + +### dragHandle + +* type: String +* description: This is the cursor to use +* default: `null` + +### useRowAttrFunc + +* type: Boolean +* description: This function must be use if your `tr` elements won't have the `id` attribute. If your `tr` elements don't have the `id` attribute this plugin don't fire the onDrop event. +* default: `false` + +### onReorderRowsDrag + +* type: Function +* description: Pass a function that will be called when the user starts dragging. The function takes 2 parameters: the table and the row which the user has started to drag. +* default: `empty function` + +### onReorderRowsDrop + +* type: Function +* description: Pass a function that will be called when the row is dropped. The function takes 2 parameters: the table and the row that was dropped. +* default: `empty function` + +## Events + +### onReorderRow(reorder-row.bs.table) + +Fired when the row was dropped, receive as parameter the new data order + +## The existing problems + +* After search if the user reorder the rows the data is not shown properly after that. \ No newline at end of file diff --git a/public/assets/js/extensions/reorder-rows/bootstrap-table-reorder-rows.css b/public/assets/js/extensions/reorder-rows/bootstrap-table-reorder-rows.css old mode 100644 new mode 100755 diff --git a/public/assets/js/extensions/reorder-rows/bootstrap-table-reorder-rows.js b/public/assets/js/extensions/reorder-rows/bootstrap-table-reorder-rows.js old mode 100644 new mode 100755 index c65d6f666e..c733717695 --- a/public/assets/js/extensions/reorder-rows/bootstrap-table-reorder-rows.js +++ b/public/assets/js/extensions/reorder-rows/bootstrap-table-reorder-rows.js @@ -44,8 +44,6 @@ BootstrapTable.prototype.init = function () { - _init.apply(this, Array.prototype.slice.apply(arguments)); - if (!this.options.reorderableRows) { return; } @@ -62,6 +60,8 @@ onPostBody.apply(); }, 1); }; + + _init.apply(this, Array.prototype.slice.apply(arguments)); }; BootstrapTable.prototype.initSearch = function () { @@ -91,7 +91,7 @@ }); }; - BootstrapTable.prototype.onDrop = function (table, row) { + BootstrapTable.prototype.onDrop = function (table, droppedRow) { var tableBs = $(table), tableBsData = tableBs.data('bootstrap.table'), tableBsOptions = tableBs.data('bootstrap.table').options, @@ -107,7 +107,7 @@ tableBsOptions.data = newData; //Call the user defined function - tableBsOptions.onReorderRowsDrop.apply(table, row); + tableBsOptions.onReorderRowsDrop.apply(table, [table, droppedRow]); //Call the event reorder-row tableBsData.trigger('reorder-row', newData); diff --git a/public/assets/js/extensions/reorder-rows/bootstrap-table-reorder-rows.min.js b/public/assets/js/extensions/reorder-rows/bootstrap-table-reorder-rows.min.js deleted file mode 100644 index 785f15a121..0000000000 --- a/public/assets/js/extensions/reorder-rows/bootstrap-table-reorder-rows.min.js +++ /dev/null @@ -1,7 +0,0 @@ -/* -* bootstrap-table - v1.8.1 - 2015-05-29 -* https://github.com/wenzhixin/bootstrap-table -* Copyright (c) 2015 zhixin wen -* Licensed MIT License -*/ -!function(a){"use strict";var b=function(a,b){return{id:"customId_"+b}};a.extend(a.fn.bootstrapTable.defaults,{reorderableRows:!1,onDragStyle:null,onDropStyle:null,onDragClass:"reorder_rows_onDragClass",dragHandle:null,useRowAttrFunc:!1,onReorderRowsDrag:function(){return!1},onReorderRowsDrop:function(){return!1},onReorderRow:function(){return!1}}),a.extend(a.fn.bootstrapTable.Constructor.EVENTS,{"reorder-row.bs.table":"onReorderRow"});var c=a.fn.bootstrapTable.Constructor,d=c.prototype.init,e=c.prototype.initSearch;c.prototype.init=function(){if(d.apply(this,Array.prototype.slice.apply(arguments)),this.options.reorderableRows){var a=this;this.options.useRowAttrFunc&&(this.options.rowAttributes=b);var c=this.options.onPostBody;this.options.onPostBody=function(){setTimeout(function(){a.makeRowsReorderable(),c.apply()},1)}}},c.prototype.initSearch=function(){e.apply(this,Array.prototype.slice.apply(arguments)),!this.options.reorderableRows},c.prototype.makeRowsReorderable=function(){if(!this.options.cardView){var a=this;this.$el.tableDnD({onDragStyle:a.options.onDragStyle,onDropStyle:a.options.onDropStyle,onDragClass:a.options.onDragClass,onDrop:a.onDrop,onDragStart:a.options.onReorderRowsDrag,dragHandle:a.options.dragHandle})}},c.prototype.onDrop=function(b,c){for(var d=a(b),e=d.data("bootstrap.table"),f=d.data("bootstrap.table").options,c=null,g=[],h=0;h<b.tBodies[0].rows.length;h++)c=a(b.tBodies[0].rows[h]),g.push(f.data[c.data("index")]),c.data("index",h).attr("data-index",h);f.data=g,f.onReorderRowsDrop.apply(b,c),e.trigger("reorder-row",g)}}(jQuery); \ No newline at end of file diff --git a/public/assets/js/extensions/resizable/README.md b/public/assets/js/extensions/resizable/README.md new file mode 100755 index 0000000000..46e414ab13 --- /dev/null +++ b/public/assets/js/extensions/resizable/README.md @@ -0,0 +1,66 @@ +# Table Resizable + +Use Plugin: [bootstrap-table-resizable](https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/resizable) </br> +Dependence: [colResizable](https://github.com/alvaro-prieto/colResizable) v1.5 + +## Usage + +```html +<script src="extensions/cookie/bootstrap-table-resizable.js"></script> +``` + +## Options + +### resizable + +* type: Boolean +* description: Set true to allow the resize in each column. +* default: `false` + +### liveDrag + +* type: Boolean +* description: When set to true the table layout is updated while dragging column anchors. liveDrag enabled is more CPU consuming so it is not recommended for slow computers, specially when dealing with huge or extremely complicated tables. +* default: `false` + +### fixed + +* type: Boolean +* description: It is used to set how the resize method works. In fixed mode resizing a column does not alter total table width, which means that when a column is expanded the next one shrinks. If fixed is set to false then table can change its width and each column can shrink or expand independently. +* default: `true` + +### headerOnly + +* type: Boolean +* description: This attribute can be used to prevent vertical expansion of the column anchors to fit the table height. If it is set to true, column handler's size will be bounded to the first row's vertical size. +* default: `false` + +### minWidth + +* type: Integer +* description: This value specifies the minimum width (measured in pixels) that is allowed for the columns. +* default: `15` + +### hoverCursor + +* type: String +* description: This attribute can be used to customize the cursor that will be displayed when the user is positioned on the column anchors. +* default: `e-resize` + +### dragCursor + +* type: String +* description: Defines the cursor that will be used while the user is resizing a column. +* default: `e-resize` + +### onResizableResize + +* type: Function +* description: If a callback function is supplied it will be fired when the user has ended dragging a column anchor altering the previous table layout. The callback function can obtain a reference to the updated table through the currentTarget attribute of the event retrieved by parameters. +* default: `empty function` + +### onResizableDrag + +* type: Function +* description: This event is fired while dragging a column anchor if liveDrag is enabled. It can be useful if the table is being used as a multiple range slider. The callback function can obtain a reference to the updated table through the currentTarget attribute of the event retrieved by parameters +* default: `empty function` \ No newline at end of file diff --git a/public/assets/js/extensions/resizable/bootstrap-table-resizable.js b/public/assets/js/extensions/resizable/bootstrap-table-resizable.js old mode 100644 new mode 100755 diff --git a/public/assets/js/extensions/resizable/bootstrap-table-resizable.min.js b/public/assets/js/extensions/resizable/bootstrap-table-resizable.min.js deleted file mode 100644 index 3be404fd6c..0000000000 --- a/public/assets/js/extensions/resizable/bootstrap-table-resizable.min.js +++ /dev/null @@ -1,7 +0,0 @@ -/* -* bootstrap-table - v1.8.1 - 2015-05-29 -* https://github.com/wenzhixin/bootstrap-table -* Copyright (c) 2015 zhixin wen -* Licensed MIT License -*/ -!function(a){"use strict";var b=function(a){a.$el.colResizable({disable:!0}),a.$el.colResizable({liveDrag:a.options.liveDrag,fixed:a.options.fixed,headerOnly:a.options.headerOnly,minWidth:a.options.minWidth,hoverCursor:a.options.hoverCursor,dragCursor:a.options.dragCursor,onResize:a.onResize,onDrag:a.options.onResizableDrag})};a.extend(a.fn.bootstrapTable.defaults,{resizable:!1,liveDrag:!1,fixed:!0,headerOnly:!1,minWidth:15,hoverCursor:"e-resize",dragCursor:"e-resize",onResizableResize:function(){return!1},onResizableDrag:function(){return!1}});var c=a.fn.bootstrapTable.Constructor,d=c.prototype.toggleView,e=c.prototype.resetView;c.prototype.toggleView=function(){d.apply(this,Array.prototype.slice.apply(arguments)),this.options.resizable&&this.options.cardView&&a(this.$el).colResizable({disable:!0})},c.prototype.resetView=function(){var a=this;e.apply(this,Array.prototype.slice.apply(arguments)),this.options.resizable&&setTimeout(function(){b(a)},100)},c.prototype.onResize=function(b){var c=a(b.currentTarget);c.bootstrapTable("resetView"),c.data("bootstrap.table").options.onResizableResize.apply(b)}}(jQuery); \ No newline at end of file diff --git a/public/assets/js/extensions/toolbar/README.md b/public/assets/js/extensions/toolbar/README.md new file mode 100755 index 0000000000..b4a8a40abb --- /dev/null +++ b/public/assets/js/extensions/toolbar/README.md @@ -0,0 +1,53 @@ +# Table Toolbar + +Use Plugin: [bootstrap-table-toolbar](https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/toolbar) + +## Usage + +```html +<script src="extensions/toolbar/bootstrap-table-toolbar.js"></script> +``` + +## Options + +### advancedSearch + +* type: Boolean +* description: Set true to allow the advanced search. +* default: `false` + +### idForm + +* type: String +* description: Must be set to know the idform. +* default: `advancedSearch` + +### actionForm + +* type: String +* description: Set the action of the form (pop-up). +* default: `` + +### idTable + +* type: String +* description: Set the id of the table to create the pop-up form. Required. +* default: `` + +## Locales + +### formatAdvancedSearch + +* description: Title of the advanced search modal +* default: `Advanced search` + +### formatAdvancedCloseButton + +* description: Text of the close button +* default: `Close` + +## Events + +### onColumnAdvancedSearch(column-advanced-search.bs.table) + +* Fired when we are searching into the advanced search form \ No newline at end of file diff --git a/public/assets/js/extensions/toolbar/bootstrap-table-toolbar.js b/public/assets/js/extensions/toolbar/bootstrap-table-toolbar.js old mode 100644 new mode 100755 index 0e7f4dbb29..fd4e585933 --- a/public/assets/js/extensions/toolbar/bootstrap-table-toolbar.js +++ b/public/assets/js/extensions/toolbar/bootstrap-table-toolbar.js @@ -10,49 +10,11 @@ var firstLoad = false; - var sprintf = function(str) { - var args = arguments, - flag = true, - i = 1; - - str = str.replace(/%s/g, function() { - var arg = args[i++]; - - if (typeof arg === 'undefined') { - flag = false; - return ''; - } - return arg; - }); - return flag ? str : ''; - }; - - var calculateObjectValue = function (self, name, args, defaultValue) { - if (typeof name === 'string') { - // support obj.func1.func2 - var names = name.split('.'); - - if (names.length > 1) { - name = window; - $.each(names, function (i, f) { - name = name[f]; - }); - } else { - name = window[name]; - } - } - if (typeof name === 'object') { - return name; - } - if (typeof name === 'function') { - return name.apply(self, args); - } - return defaultValue; - }; + var sprintf = $.fn.bootstrapTable.utils.sprintf; var showAvdSearch = function(pColumns, searchTitle, searchText, that) { - if (!$("#avdSearchModal").hasClass("modal")) { - var vModal = "<div id=\"avdSearchModal\" class=\"modal fade\" tabindex=\"-1\" role=\"dialog\" aria-labelledby=\"mySmallModalLabel\" aria-hidden=\"true\">"; + if (!$("#avdSearchModal" + "_" + that.options.idTable).hasClass("modal")) { + var vModal = sprintf("<div id=\"avdSearchModal%s\" class=\"modal fade\" tabindex=\"-1\" role=\"dialog\" aria-labelledby=\"mySmallModalLabel\" aria-hidden=\"true\">", "_" + that.options.idTable); vModal += "<div class=\"modal-dialog modal-xs\">"; vModal += " <div class=\"modal-content\">"; vModal += " <div class=\"modal-header\">"; @@ -60,7 +22,7 @@ vModal += sprintf(" <h4 class=\"modal-title\">%s</h4>", searchTitle); vModal += " </div>"; vModal += " <div class=\"modal-body modal-body-custom\">"; - vModal += " <div class=\"container-fluid\" id=\"avdSearchModalContent\" style=\"padding-right: 0px;padding-left: 0px;\" >"; + vModal += sprintf(" <div class=\"container-fluid\" id=\"avdSearchModalContent%s\" style=\"padding-right: 0px;padding-left: 0px;\" >", "_" + that.options.idTable); vModal += " </div>"; vModal += " </div>"; vModal += " </div>"; @@ -72,7 +34,7 @@ var vFormAvd = createFormAvd(pColumns, searchText, that), timeoutId = 0;; - $('#avdSearchModalContent').append(vFormAvd.join('')); + $('#avdSearchModalContent' + "_" + that.options.idTable).append(vFormAvd.join('')); $('#' + that.options.idForm).off('keyup blur', 'input').on('keyup blur', 'input', function (event) { clearTimeout(timeoutId); @@ -81,13 +43,13 @@ }, that.options.searchTimeOut); }); - $("#btnCloseAvd").click(function() { - $("#avdSearchModal").modal('hide'); + $("#btnCloseAvd" + "_" + that.options.idTable).click(function() { + $("#avdSearchModal" + "_" + that.options.idTable).modal('hide'); }); - $("#avdSearchModal").modal(); + $("#avdSearchModal" + "_" + that.options.idTable).modal(); } else { - $("#avdSearchModal").modal(); + $("#avdSearchModal" + "_" + that.options.idTable).modal(); } }; @@ -108,7 +70,7 @@ htmlForm.push('<div class="form-group">'); htmlForm.push('<div class="col-sm-offset-9 col-sm-3">'); - htmlForm.push(sprintf('<button type="button" id="btnCloseAvd" class="btn btn-default" >%s</button>', searchText)); + htmlForm.push(sprintf('<button type="button" id="btnCloseAvd%s" class="btn btn-default" >%s</button>', "_" + that.options.idTable, searchText)); htmlForm.push('</div>'); htmlForm.push('</div>'); htmlForm.push('</form>'); @@ -161,6 +123,10 @@ return; } + if (!this.options.idTable) { + return; + } + var that = this, html = []; @@ -173,13 +139,17 @@ that.$toolbar.find('button[name="advancedSearch"]') .off('click').on('click', function() { - showAvdSearch(that.options.columns, that.options.formatAdvancedSearch(), that.options.formatAdvancedCloseButton(), that); + showAvdSearch(that.columns, that.options.formatAdvancedSearch(), that.options.formatAdvancedCloseButton(), that); }); }; BootstrapTable.prototype.load = function(data) { _load.apply(this, Array.prototype.slice.apply(arguments)); + if (!this.options.advancedSearch) { + return; + } + if (typeof this.options.idTable === 'undefined') { return; } else { @@ -195,6 +165,10 @@ BootstrapTable.prototype.initSearch = function () { _initSearch.apply(this, Array.prototype.slice.apply(arguments)); + if (!this.options.advancedSearch) { + return; + } + var that = this; var fp = $.isEmptyObject(this.filterColumnsPartial) ? null : this.filterColumnsPartial; @@ -202,7 +176,7 @@ for (var key in fp) { var fval = fp[key].toLowerCase(); var value = item[key]; - value = calculateObjectValue(that.header, + value = $.fn.bootstrapTable.utils.calculateObjectValue(that.header, that.header.formatters[$.inArray(key, that.header.fields)], [value, item, i], value); diff --git a/public/assets/js/extensions/toolbar/bootstrap-table-toolbar.min.js b/public/assets/js/extensions/toolbar/bootstrap-table-toolbar.min.js deleted file mode 100644 index 0f26ac6e2c..0000000000 --- a/public/assets/js/extensions/toolbar/bootstrap-table-toolbar.min.js +++ /dev/null @@ -1,7 +0,0 @@ -/* -* bootstrap-table - v1.8.1 - 2015-05-29 -* https://github.com/wenzhixin/bootstrap-table -* Copyright (c) 2015 zhixin wen -* Licensed MIT License -*/ -!function(a){"use strict";var b=!1,c=function(a){var b=arguments,c=!0,d=1;return a=a.replace(/%s/g,function(){var a=b[d++];return"undefined"==typeof a?(c=!1,""):a}),c?a:""},d=function(b,c,d,e){if("string"==typeof c){var f=c.split(".");f.length>1?(c=window,a.each(f,function(a,b){c=c[b]})):c=window[c]}return"object"==typeof c?c:"function"==typeof c?c.apply(b,d):e},e=function(b,d,e,g){if(a("#avdSearchModal").hasClass("modal"))a("#avdSearchModal").modal();else{var h='<div id="avdSearchModal" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="mySmallModalLabel" aria-hidden="true">';h+='<div class="modal-dialog modal-xs">',h+=' <div class="modal-content">',h+=' <div class="modal-header">',h+=' <button type="button" class="close" data-dismiss="modal" aria-hidden="true" >×</button>',h+=c(' <h4 class="modal-title">%s</h4>',d),h+=" </div>",h+=' <div class="modal-body modal-body-custom">',h+=' <div class="container-fluid" id="avdSearchModalContent" style="padding-right: 0px;padding-left: 0px;" >',h+=" </div>",h+=" </div>",h+=" </div>",h+=" </div>",h+="</div>",a("body").append(a(h));var i=f(b,e,g),j=0;a("#avdSearchModalContent").append(i.join("")),a("#"+g.options.idForm).off("keyup blur","input").on("keyup blur","input",function(a){clearTimeout(j),j=setTimeout(function(){g.onColumnAdvancedSearch(a)},g.options.searchTimeOut)}),a("#btnCloseAvd").click(function(){a("#avdSearchModal").modal("hide")}),a("#avdSearchModal").modal()}},f=function(a,b,d){var e=[];e.push(c('<form class="form-horizontal" id="%s" action="%s" >',d.options.idForm,d.options.actionForm));for(var f in a){var g=a[f];!g.checkbox&&g.visible&&g.searchable&&(e.push('<div class="form-group">'),e.push(c('<label class="col-sm-4 control-label">%s</label>',g.title)),e.push('<div class="col-sm-6">'),e.push(c('<input type="text" class="form-control input-md" name="%s" placeholder="%s" id="%s">',g.field,g.title,g.field)),e.push("</div>"),e.push("</div>"))}return e.push('<div class="form-group">'),e.push('<div class="col-sm-offset-9 col-sm-3">'),e.push(c('<button type="button" id="btnCloseAvd" class="btn btn-default" >%s</button>',b)),e.push("</div>"),e.push("</div>"),e.push("</form>"),e};a.extend(a.fn.bootstrapTable.defaults,{advancedSearch:!1,idForm:"advancedSearch",actionForm:"",idTable:void 0,onColumnAdvancedSearch:function(){return!1}}),a.extend(a.fn.bootstrapTable.defaults.icons,{advancedSearchIcon:"glyphicon-chevron-down"}),a.extend(a.fn.bootstrapTable.Constructor.EVENTS,{"column-advanced-search.bs.table":"onColumnAdvancedSearch"}),a.extend(a.fn.bootstrapTable.locales,{formatAdvancedSearch:function(){return"Advanced search"},formatAdvancedCloseButton:function(){return"Close"}}),a.extend(a.fn.bootstrapTable.defaults,a.fn.bootstrapTable.locales);var g=a.fn.bootstrapTable.Constructor,h=g.prototype.initToolbar,i=g.prototype.load,j=g.prototype.initSearch;g.prototype.initToolbar=function(){if(h.apply(this,Array.prototype.slice.apply(arguments)),this.options.search&&this.options.advancedSearch){var a=this,b=[];b.push(c('<div class="columns columns-%s btn-group pull-%s" role="group">',this.options.buttonsAlign,this.options.buttonsAlign)),b.push(c('<button class="btn btn-default%s" type="button" name="advancedSearch" title="%s">',void 0===a.options.iconSize?"":" btn-"+a.options.iconSize,a.options.formatAdvancedSearch())),b.push(c('<i class="%s %s"></i>',a.options.iconsPrefix,a.options.icons.advancedSearchIcon)),b.push("</button></div>"),a.$toolbar.prepend(b.join("")),a.$toolbar.find('button[name="advancedSearch"]').off("click").on("click",function(){e(a.options.columns,a.options.formatAdvancedSearch(),a.options.formatAdvancedCloseButton(),a)})}},g.prototype.load=function(){if(i.apply(this,Array.prototype.slice.apply(arguments)),"undefined"!=typeof this.options.idTable&&!b){var c=parseInt(a(".bootstrap-table").height());c+=10,a("#"+this.options.idTable).bootstrapTable("resetView",{height:c}),b=!0}},g.prototype.initSearch=function(){j.apply(this,Array.prototype.slice.apply(arguments));var b=this,c=a.isEmptyObject(this.filterColumnsPartial)?null:this.filterColumnsPartial;this.data=c?a.grep(this.data,function(e,f){for(var g in c){var h=c[g].toLowerCase(),i=e[g];if(i=d(b.header,b.header.formatters[a.inArray(g,b.header.fields)],[i,e,f],i),-1===a.inArray(g,b.header.fields)||"string"!=typeof i&&"number"!=typeof i||-1===(i+"").toLowerCase().indexOf(h))return!1}return!0}):this.data},g.prototype.onColumnAdvancedSearch=function(b){var c=a.trim(a(b.currentTarget).val()),d=a(b.currentTarget)[0].id;a.isEmptyObject(this.filterColumnsPartial)&&(this.filterColumnsPartial={}),c?this.filterColumnsPartial[d]=c:delete this.filterColumnsPartial[d],this.options.pageNumber=1,this.onSearch(b),this.updatePagination(),this.trigger("column-advanced-search",d,c)}}(jQuery); \ No newline at end of file From 36a3d655ad5046d21587ed156c05b65492a77bdf Mon Sep 17 00:00:00 2001 From: snipe <snipe@snipe.net> Date: Wed, 21 Oct 2015 15:15:04 -0700 Subject: [PATCH 080/120] Added cookie name to make column cookies work --- app/config/version.php | 4 ++-- app/views/backend/accessories/index.blade.php | 20 ++++++++++++------ app/views/backend/consumables/index.blade.php | 20 +++++++++++------- app/views/backend/hardware/index.blade.php | 21 ++++++++++++------- app/views/backend/licenses/index.blade.php | 21 ++++++++++++------- app/views/backend/users/index.blade.php | 3 +++ .../export/bootstrap-table-export.js | 2 +- 7 files changed, 61 insertions(+), 30 deletions(-) diff --git a/app/config/version.php b/app/config/version.php index 49cd88aa75..064f7f6ef6 100644 --- a/app/config/version.php +++ b/app/config/version.php @@ -1,5 +1,5 @@ <?php return array ( - 'app_version' => 'v2.0-261', - 'hash_version' => 'v2.0-261-gb25b332', + 'app_version' => 'v2.0-262', + 'hash_version' => 'v2.0-262-gcab5dba', ); \ No newline at end of file diff --git a/app/views/backend/accessories/index.blade.php b/app/views/backend/accessories/index.blade.php index 8b45b07f0c..bb63435f0e 100755 --- a/app/views/backend/accessories/index.blade.php +++ b/app/views/backend/accessories/index.blade.php @@ -19,7 +19,13 @@ <div class="user-profile"> <div class="row profile"> <div class="col-md-9 bio"> - <table name="accessories" id="table" data-url="{{route('api.accessories.list')}}"> + <table + name="accessories" + id="table" + data-url="{{route('api.accessories.list')}}" + data-cookie="true" + data-click-to-select="true" + data-cookie-id-table="accessoriesTable"> <thead> <tr> <th data-sortable="true" data-field="name">{{Lang::get('admin/accessories/table.title')}}</th> @@ -45,11 +51,11 @@ @section('moar_scripts') <script src="{{ asset('assets/js/bootstrap-table.js') }}"></script> +<script src="{{ asset('assets/js/extensions/cookie/bootstrap-table-cookie.js') }}"></script> <script src="{{ asset('assets/js/extensions/mobile/bootstrap-table-mobile.js') }}"></script> -<script src="{{ asset('assets/js/extensions/export/bootstrap-table-export.js?v=1') }}"></script> -<script src="{{ asset('assets/js/extensions/cookie/bootstrap-table-cookie.js?v=1') }}"></script> -<script src="//rawgit.com/kayalshri/tableExport.jquery.plugin/master/tableExport.js?v=1') }}"></script> -<script src="//rawgit.com/kayalshri/tableExport.jquery.plugin/master/jquery.base64.js?v=1') }}"></script> +<script src="{{ asset('assets/js/extensions/export/bootstrap-table-export.js') }}"></script> +<script src="//rawgit.com/kayalshri/tableExport.jquery.plugin/master/tableExport.js"></script> +<script src="//rawgit.com/kayalshri/tableExport.jquery.plugin/master/jquery.base64.js"></script> <script type="text/javascript"> $('#table').bootstrapTable({ classes: 'table table-responsive table-no-bordered', @@ -63,8 +69,10 @@ sortable: true, cookie: true, mobileResponsive: true, - columnsHidden: ['name'], showExport: true, + showColumns: true, + exportDataType: 'all', + exportTypes: ['csv', 'txt','json', 'xml'], maintainSelected: true, paginationFirstText: "@lang('general.first')", paginationLastText: "@lang('general.last')", diff --git a/app/views/backend/consumables/index.blade.php b/app/views/backend/consumables/index.blade.php index c20897243b..0e66dffe8f 100644 --- a/app/views/backend/consumables/index.blade.php +++ b/app/views/backend/consumables/index.blade.php @@ -19,7 +19,13 @@ <div class="user-profile"> <div class="row profile"> <div class="col-md-9 bio"> - <table name="consumables" id="table" data-url="{{route('api.consumables.list')}}"> + <table + name="consumables" + id="table" + data-url="{{route('api.consumables.list')}}" + data-cookie="true" + data-click-to-select="true" + data-cookie-id-table="consumablesTable"> <thead> <tr> <th data-sortable="true" data-field="name">{{Lang::get('admin/consumables/table.title')}}</th> @@ -43,11 +49,11 @@ @section('moar_scripts') <script src="{{ asset('assets/js/bootstrap-table.js') }}"></script> +<script src="{{ asset('assets/js/extensions/cookie/bootstrap-table-cookie.js') }}"></script> <script src="{{ asset('assets/js/extensions/mobile/bootstrap-table-mobile.js') }}"></script> -<script src="{{ asset('assets/js/extensions/export/bootstrap-table-export.js?v=1') }}"></script> -<script src="{{ asset('assets/js/extensions/cookie/bootstrap-table-cookie.js?v=1') }}"></script> -<script src="//rawgit.com/kayalshri/tableExport.jquery.plugin/master/tableExport.js?v=1') }}"></script> -<script src="//rawgit.com/kayalshri/tableExport.jquery.plugin/master/jquery.base64.js?v=1') }}"></script> +<script src="{{ asset('assets/js/extensions/export/bootstrap-table-export.js') }}"></script> +<script src="//rawgit.com/kayalshri/tableExport.jquery.plugin/master/tableExport.js"></script> +<script src="//rawgit.com/kayalshri/tableExport.jquery.plugin/master/jquery.base64.js"></script> <script type="text/javascript"> $('#table').bootstrapTable({ classes: 'table table-responsive table-no-bordered', @@ -61,10 +67,10 @@ sortable: true, cookie: true, mobileResponsive: true, - columnsHidden: ['name'], showExport: true, - exportLabel: 'Export', showColumns: true, + exportDataType: 'all', + exportTypes: ['csv', 'txt','json', 'xml'], maintainSelected: true, paginationFirstText: "@lang('general.first')", paginationLastText: "@lang('general.last')", diff --git a/app/views/backend/hardware/index.blade.php b/app/views/backend/hardware/index.blade.php index 4b58be414c..9362168ad5 100755 --- a/app/views/backend/hardware/index.blade.php +++ b/app/views/backend/hardware/index.blade.php @@ -48,7 +48,13 @@ 'route' => ['hardware/bulkedit'], 'class' => 'form-horizontal' ]) }} - <table name="assets" id="table" data-url="{{route('api.hardware.list', array(''=>Input::get('status'),'order_number'=>Input::get('order_number')))}}"> + <table + name="assets" + id="table" + data-url="{{route('api.hardware.list', array(''=>Input::get('status'),'order_number'=>Input::get('order_number')))}}" + data-cookie="true" + data-click-to-select="true" + data-cookie-id-table="assetsTable"> <thead> <tr> <th data-class="hidden-xs" data-switchable="false" data-searchable="false" data-sortable="false" data-field="checkbox"><div class="text-center"><input type="checkbox" id="checkAll" style="padding-left: 0px;"></div></th> @@ -86,11 +92,11 @@ @section('moar_scripts') <script src="{{ asset('assets/js/bootstrap-table.js') }}"></script> +<script src="{{ asset('assets/js/extensions/cookie/bootstrap-table-cookie.js') }}"></script> <script src="{{ asset('assets/js/extensions/mobile/bootstrap-table-mobile.js') }}"></script> -<script src="{{ asset('assets/js/extensions/export/bootstrap-table-export.js?v=1') }}"></script> -<script src="{{ asset('assets/js/extensions/cookie/bootstrap-table-cookie.js?v=1') }}"></script> -<script src="//rawgit.com/kayalshri/tableExport.jquery.plugin/master/tableExport.js?v=1') }}"></script> -<script src="//rawgit.com/kayalshri/tableExport.jquery.plugin/master/jquery.base64.js?v=1') }}"></script> +<script src="{{ asset('assets/js/extensions/export/bootstrap-table-export.js') }}"></script> +<script src="//rawgit.com/kayalshri/tableExport.jquery.plugin/master/tableExport.js"></script> +<script src="//rawgit.com/kayalshri/tableExport.jquery.plugin/master/jquery.base64.js"></script> <script type="text/javascript"> $('#table').bootstrapTable({ classes: 'table table-responsive table-no-bordered', @@ -104,10 +110,10 @@ sortable: true, cookie: true, mobileResponsive: true, - columnsHidden: ['name'], showExport: true, - exportLabel: 'Export', showColumns: true, + exportDataType: 'all', + exportTypes: ['csv', 'txt','json', 'xml'], maintainSelected: true, paginationFirstText: "@lang('general.first')", paginationLastText: "@lang('general.last')", @@ -124,6 +130,7 @@ }); </script> + <script> $(function() { function checkForChecked() { diff --git a/app/views/backend/licenses/index.blade.php b/app/views/backend/licenses/index.blade.php index 67a794ac2b..d015f372aa 100755 --- a/app/views/backend/licenses/index.blade.php +++ b/app/views/backend/licenses/index.blade.php @@ -17,7 +17,13 @@ </div> <div class="row form-wrapper"> - <table name="licenses" id="table" data-url="{{route('api.licenses.list')}}"> + <table + name="licenses" + id="table" + data-url="{{route('api.licenses.list')}}" + data-cookie="true" + data-click-to-select="true" + data-cookie-id-table="licenseTable"> <thead> <tr> <th data-field="name">{{Lang::get('admin/licenses/table.title')}}</th> @@ -33,11 +39,11 @@ @section('moar_scripts') <script src="{{ asset('assets/js/bootstrap-table.js') }}"></script> +<script src="{{ asset('assets/js/extensions/cookie/bootstrap-table-cookie.js') }}"></script> <script src="{{ asset('assets/js/extensions/mobile/bootstrap-table-mobile.js') }}"></script> -<script src="{{ asset('assets/js/extensions/export/bootstrap-table-export.js?v=1') }}"></script> -<script src="{{ asset('assets/js/extensions/cookie/bootstrap-table-cookie.js?v=1') }}"></script> -<script src="//rawgit.com/kayalshri/tableExport.jquery.plugin/master/tableExport.js?v=1') }}"></script> -<script src="//rawgit.com/kayalshri/tableExport.jquery.plugin/master/jquery.base64.js?v=1') }}"></script> +<script src="{{ asset('assets/js/extensions/export/bootstrap-table-export.js') }}"></script> +<script src="//rawgit.com/kayalshri/tableExport.jquery.plugin/master/tableExport.js"></script> +<script src="//rawgit.com/kayalshri/tableExport.jquery.plugin/master/jquery.base64.js"></script> <script type="text/javascript"> $('#table').bootstrapTable({ classes: 'table table-responsive table-no-bordered', @@ -51,10 +57,10 @@ sortable: true, cookie: true, mobileResponsive: true, - columnsHidden: ['name'], showExport: true, - exportLabel: 'Export', showColumns: true, + exportDataType: 'all', + exportTypes: ['csv', 'txt','json', 'xml'], maintainSelected: true, paginationFirstText: "@lang('general.first')", paginationLastText: "@lang('general.last')", @@ -70,6 +76,7 @@ }); </script> + @stop @stop diff --git a/app/views/backend/users/index.blade.php b/app/views/backend/users/index.blade.php index 8795671df3..6930da4881 100755 --- a/app/views/backend/users/index.blade.php +++ b/app/views/backend/users/index.blade.php @@ -45,6 +45,7 @@ data-toggle="table" data-url="{{ route('api.users.list', array(''=>Input::get('status'))) }}" data-cookie="true" + data-click-to-select="true" data-cookie-id-table="userTable"> <thead> <tr> @@ -115,6 +116,8 @@ mobileResponsive: true, showExport: true, showColumns: true, + exportDataType: 'all', + exportTypes: ['csv', 'txt','json', 'xml'], maintainSelected: true, paginationFirstText: "@lang('general.first')", paginationLastText: "@lang('general.last')", diff --git a/public/assets/js/extensions/export/bootstrap-table-export.js b/public/assets/js/extensions/export/bootstrap-table-export.js index 5be5001d53..3669e3ebac 100755 --- a/public/assets/js/extensions/export/bootstrap-table-export.js +++ b/public/assets/js/extensions/export/bootstrap-table-export.js @@ -45,7 +45,7 @@ '<div class="export btn-group">', '<button class="btn btn-default dropdown-toggle" ' + 'data-toggle="dropdown" type="button">', - '<i class="glyphicon glyphicon-export icon-share"></i> ', + '<i class="fa fa-download"></i> ', '<span class="caret"></span>', '</button>', '<ul class="dropdown-menu" role="menu">', From a896bb0effbdd063fee87000872b3dd60f1d83ea Mon Sep 17 00:00:00 2001 From: snipe <snipe@snipe.net> Date: Wed, 21 Oct 2015 15:42:59 -0700 Subject: [PATCH 081/120] Updated categories with cookie and export stuff for #1266 --- app/views/backend/categories/index.blade.php | 22 ++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/app/views/backend/categories/index.blade.php b/app/views/backend/categories/index.blade.php index c4c44d748d..2052caa88c 100755 --- a/app/views/backend/categories/index.blade.php +++ b/app/views/backend/categories/index.blade.php @@ -19,7 +19,13 @@ <div class="user-profile"> <div class="row profile"> <div class="col-md-9 bio"> - <table name="models" id="table" data-url="{{route('api.categories.list')}}"> + <table + name="categories" + id="table" + data-url="{{route('api.categories.list')}}" + data-cookie="true" + data-click-to-select="true" + data-cookie-id-table="categoriesTable"> <thead> <tr> <th data-sortable="true" data-field="name">{{Lang::get('admin/categories/table.title')}}</th> @@ -45,14 +51,14 @@ @section('moar_scripts') <script src="{{ asset('assets/js/bootstrap-table.js') }}"></script> +<script src="{{ asset('assets/js/extensions/cookie/bootstrap-table-cookie.js') }}"></script> <script src="{{ asset('assets/js/extensions/mobile/bootstrap-table-mobile.js') }}"></script> -<script src="{{ asset('assets/js/extensions/export/bootstrap-table-export.js?v=1') }}"></script> -<script src="{{ asset('assets/js/extensions/cookie/bootstrap-table-cookie.js?v=1') }}"></script> -<script src="//rawgit.com/kayalshri/tableExport.jquery.plugin/master/tableExport.js?v=1') }}"></script> -<script src="//rawgit.com/kayalshri/tableExport.jquery.plugin/master/jquery.base64.js?v=1') }}"></script> +<script src="{{ asset('assets/js/extensions/export/bootstrap-table-export.js') }}"></script> +<script src="//rawgit.com/kayalshri/tableExport.jquery.plugin/master/tableExport.js"></script> +<script src="//rawgit.com/kayalshri/tableExport.jquery.plugin/master/jquery.base64.js"></script> <script type="text/javascript"> $('#table').bootstrapTable({ - classes: 'table table-hover table-no-bordered', + classes: 'table table-responsive table-no-bordered', undefinedText: '', iconsPrefix: 'fa', showRefresh: true, @@ -61,9 +67,12 @@ pagination: true, sidePagination: 'server', sortable: true, + cookie: true, mobileResponsive: true, showExport: true, showColumns: true, + exportDataType: 'all', + exportTypes: ['csv', 'txt','json', 'xml'], maintainSelected: true, paginationFirstText: "@lang('general.first')", paginationLastText: "@lang('general.last')", @@ -76,6 +85,7 @@ columns: 'fa-columns', refresh: 'fa-refresh' }, + }); </script> @stop From b5b8865b36e7609d2c888bb7125bfefe75ce1cbf Mon Sep 17 00:00:00 2001 From: snipe <snipe@snipe.net> Date: Wed, 21 Oct 2015 15:43:12 -0700 Subject: [PATCH 082/120] Locations in bootstrap tables for #1266 --- app/config/version.php | 4 +- app/controllers/admin/LocationsController.php | 73 ++++++++++++ app/models/Location.php | 28 ++++- app/routes.php | 16 ++- app/views/backend/locations/index.blade.php | 104 +++++++++++------- 5 files changed, 177 insertions(+), 48 deletions(-) diff --git a/app/config/version.php b/app/config/version.php index 064f7f6ef6..c5773f8794 100644 --- a/app/config/version.php +++ b/app/config/version.php @@ -1,5 +1,5 @@ <?php return array ( - 'app_version' => 'v2.0-262', - 'hash_version' => 'v2.0-262-gcab5dba', + 'app_version' => 'v2.0-264', + 'hash_version' => 'v2.0-264-g36a3d65', ); \ No newline at end of file diff --git a/app/controllers/admin/LocationsController.php b/app/controllers/admin/LocationsController.php index 0b3c0b4aac..01f24afdee 100755 --- a/app/controllers/admin/LocationsController.php +++ b/app/controllers/admin/LocationsController.php @@ -254,6 +254,79 @@ class LocationsController extends AdminController } + public function getDatatable() + { + $locations = Location::select(array('id','name','address','address2','city','state','zip','country')) + ->whereNull('deleted_at'); + + if (Input::has('search')) { + $locations = $locations->TextSearch(e(Input::get('search'))); + } + + if (Input::has('offset')) { + $offset = e(Input::get('offset')); + } else { + $offset = 0; + } + + if (Input::has('limit')) { + $limit = e(Input::get('limit')); + } else { + $limit = 50; + } + + + $allowed_columns = ['name','address','city','state','country']; + $order = Input::get('order') === 'asc' ? 'asc' : 'desc'; + $sort = in_array(Input::get('sort'), $allowed_columns) ? Input::get('sort') : 'created_at'; + + $locations->orderBy($sort, $order); + + $locationsCount = $locations->count(); + $locations = $locations->skip($offset)->take($limit)->get(); + + $rows = array(); + + foreach($locations as $location) { + $actions = '<a href="'.route('update/location', $location->id).'" class="btn btn-warning btn-sm" style="margin-right:5px;"><i class="fa fa-pencil icon-white"></i></a><a data-html="false" class="btn delete-asset btn-danger btn-sm" data-toggle="modal" href="'.route('delete/location', $location->id).'" data-content="'.Lang::get('admin/locations/message.delete.confirm').'" data-title="'.Lang::get('general.delete').' '.htmlspecialchars($location->name).'?" onClick="return false;"><i class="fa fa-trash icon-white"></i></a>'; + + $rows[] = array( + 'name' => link_to('admin/locations/'.$location->id.'/view', $location->name), + 'parent' => ($location->parent) ? $location->parent->name : '', + 'assets' => ($location->assets->count() + $location->assignedassets->count()), + 'address' => ($location->address) ? $location->address: '', + 'city' => $location->city, + 'state' => $location->state, + 'country' => $location->country, + 'actions' => $actions + ); + } + + $data = array('total' => $locationsCount, 'rows' => $rows); + + return $data; + + } + + public function getDataView($locationId) + { + $consumable = Consumable::find($consumableID); + $consumable_users = $consumable->users; + $count = $consumable_users->count(); + + $rows = array(); + + foreach ($consumable_users as $user) { + $rows[] = array( + 'name' => link_to('/admin/users/'.$user->id.'/view', $user->fullName()) + ); + } + + $data = array('total' => $count, 'rows' => $rows); + + return $data; + } + } diff --git a/app/models/Location.php b/app/models/Location.php index 8a83eaa809..880ffe34aa 100755 --- a/app/models/Location.php +++ b/app/models/Location.php @@ -29,7 +29,7 @@ class Location extends Elegant } public function parent() { - return $this->belongsTo('Location', 'parent_id'); + return $this->hasOne('Location', 'parent_id'); } public function childLocations() { @@ -88,5 +88,31 @@ class Location extends Elegant return $location_options; } + /** + * Query builder scope to search on text + * + * @param Illuminate\Database\Query\Builder $query Query builder instance + * @param text $search Search term + * + * @return Illuminate\Database\Query\Builder Modified query builder + */ + public function scopeTextsearch($query, $search) + { + + return $query->where('name', 'LIKE', "%$search%") + ->orWhere('address', 'LIKE', "%$search%") + ->orWhere('city', 'LIKE', "%$search%") + ->orWhere('state', 'LIKE', "%$search%") + ->orWhere('zip', 'LIKE', "%$search%") + ->orWhere(function($query) use ($search) { + $query->whereHas('parent', function($query) use ($search) { + $query->where(function($query) use ($search) { + $query->where('name','LIKE','%'.$search.'%'); + }); + }); + }); + + } + } diff --git a/app/routes.php b/app/routes.php index f901736f67..871e04df96 100755 --- a/app/routes.php +++ b/app/routes.php @@ -39,11 +39,17 @@ [ 'as' => 'api.accessories.view', 'uses' => 'AccessoriesController@getDataView' ] ); } ); - /*---Consumables API---*/ - Route::group(array('prefix'=>'consumables'), function () { - Route::get('list', array('as'=>'api.consumables.list', 'uses'=>'ConsumablesController@getDatatable')); - Route::get('{consumableID}/view', array('as'=>'api.consumables.view', 'uses'=>'ConsumablesController@getDataView')); - }); + /*---Consumables API---*/ + Route::group(array('prefix'=>'consumables'), function () { + Route::get('list', array('as'=>'api.consumables.list', 'uses'=>'ConsumablesController@getDatatable')); + Route::get('{consumableID}/view', array('as'=>'api.consumables.view', 'uses'=>'ConsumablesController@getDataView')); + }); + + /*---Locations API---*/ + Route::group(array('prefix'=>'locations'), function () { + Route::get('list', array('as'=>'api.locations.list', 'uses'=>'LocationsController@getDatatable')); + Route::get('{$locationID}/view', array('as'=>'api.locations.view', 'uses'=>'LocationsController@getDataView')); + }); /*---Users API---*/ Route::group( [ 'prefix' => 'users' ], function () { diff --git a/app/views/backend/locations/index.blade.php b/app/views/backend/locations/index.blade.php index f3d3d24fd4..332b41b0ad 100755 --- a/app/views/backend/locations/index.blade.php +++ b/app/views/backend/locations/index.blade.php @@ -18,47 +18,71 @@ Locations :: <div class="row form-wrapper"> -<table id="example"> - <thead> - <tr role="row"> - <th class="col-md-2">@lang('admin/locations/table.name')</th> - <th class="col-md-2">@lang('admin/locations/table.parent')</th> - <th class="col-md-1">@lang('general.assets')</th> - <th class="col-md-3">@lang('admin/locations/table.address')</th> - <th class="col-md-2">@lang('admin/locations/table.city'), - @lang('admin/locations/table.state') - @lang('admin/locations/table.country')</th> - <th class="col-md-1 actions">@lang('table.actions')</th> - </tr> - </thead> - <tbody> - @foreach ($locations as $location) - <tr> - <td>{{{ $location->name }}}</td> - <td> - @if ($location->parent) - {{{ $location->parent->name }}} - @endif - </td> - <td>{{{ ($location->assets->count() + $location->assignedassets->count()) }}}</td> - <td>{{{ $location->address }}} - @if($location->address2 != '') - , {{{ $location->address2 }}} - @endif - </td> - <td>{{{ $location->city }}}, {{{ strtoupper($location->state) }}} {{{ strtoupper($location->country) }}} </td> - <td> - <a href="{{ route('update/location', $location->id) }}" class="btn btn-warning btn-sm"><i class="fa fa-pencil icon-white"></i></a> - <a data-html="false" class="btn delete-asset btn-danger btn-sm" data-toggle="modal" href="{{ route('delete/location', $location->id) }}" data-content="@lang('admin/locations/message.delete.confirm')" - data-title="@lang('general.delete') - {{ htmlspecialchars($location->name) }}?" onClick="return false;"><i class="fa fa-trash icon-white"></i></a> - - </td> - </tr> - @endforeach - </tbody> -</table> + <table + name="categories" + id="table" + data-url="{{ route('api.locations.list') }}" + data-cookie="true" + data-click-to-select="true" + data-cookie-id-table="locationsTable"> + <thead> + <tr> + <th data-sortable="true" data-field="name">@lang('admin/locations/table.name')</th> + <th data-sortable="false" data-field="parent">@lang('admin/locations/table.parent')</th> + <th data-searchable="false" data-sortable="false" data-field="assets">@lang('general.assets')</th> + <th data-searchable="true" data-sortable="true" data-field="address">@lang('admin/locations/table.address')</th> + <th data-searchable="true" data-sortable="true" data-field="city">@lang('admin/locations/table.city') + </th> + <th data-searchable="true" data-sortable="true" data-field="state"> + @lang('admin/locations/table.state') + </th> + <th data-searchable="true" data-sortable="true" data-field="country"> + @lang('admin/locations/table.country')</th> + <th data-switchable="false" data-searchable="false" data-sortable="false" data-field="actions">{{ Lang::get('table.actions') }}</th> + </tr> + </thead> + </table> </div> +@section('moar_scripts') +<script src="{{ asset('assets/js/bootstrap-table.js') }}"></script> +<script src="{{ asset('assets/js/extensions/cookie/bootstrap-table-cookie.js') }}"></script> +<script src="{{ asset('assets/js/extensions/mobile/bootstrap-table-mobile.js') }}"></script> +<script src="{{ asset('assets/js/extensions/export/bootstrap-table-export.js') }}"></script> +<script src="//rawgit.com/kayalshri/tableExport.jquery.plugin/master/tableExport.js"></script> +<script src="//rawgit.com/kayalshri/tableExport.jquery.plugin/master/jquery.base64.js"></script> +<script type="text/javascript"> + $('#table').bootstrapTable({ + classes: 'table table-responsive table-no-bordered', + undefinedText: '', + iconsPrefix: 'fa', + showRefresh: true, + search: true, + pageSize: {{{ Setting::getSettings()->per_page }}}, + pagination: true, + sidePagination: 'server', + sortable: true, + cookie: true, + mobileResponsive: true, + showExport: true, + showColumns: true, + exportDataType: 'all', + exportTypes: ['csv', 'txt','json', 'xml'], + maintainSelected: true, + paginationFirstText: "@lang('general.first')", + paginationLastText: "@lang('general.last')", + paginationPreText: "@lang('general.previous')", + paginationNextText: "@lang('general.next')", + pageList: ['10','25','50','100','150','200'], + icons: { + paginationSwitchDown: 'fa-caret-square-o-down', + paginationSwitchUp: 'fa-caret-square-o-up', + columns: 'fa-columns', + refresh: 'fa-refresh' + }, + + }); +</script> +@stop @stop From 218c76592cda3142cfee1b95ee5f24611bd81c0a Mon Sep 17 00:00:00 2001 From: snipe <snipe@snipe.net> Date: Wed, 21 Oct 2015 16:01:44 -0700 Subject: [PATCH 083/120] Added currency to display table for #1266 --- app/config/version.php | 4 ++-- app/controllers/admin/LocationsController.php | 10 +++++----- app/views/backend/locations/index.blade.php | 1 + 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/app/config/version.php b/app/config/version.php index c5773f8794..bfc0530315 100644 --- a/app/config/version.php +++ b/app/config/version.php @@ -1,5 +1,5 @@ <?php return array ( - 'app_version' => 'v2.0-264', - 'hash_version' => 'v2.0-264-g36a3d65', + 'app_version' => 'v2.0-265', + 'hash_version' => 'v2.0-265-ga896bb0', ); \ No newline at end of file diff --git a/app/controllers/admin/LocationsController.php b/app/controllers/admin/LocationsController.php index 01f24afdee..798c372aee 100755 --- a/app/controllers/admin/LocationsController.php +++ b/app/controllers/admin/LocationsController.php @@ -256,7 +256,7 @@ class LocationsController extends AdminController public function getDatatable() { - $locations = Location::select(array('id','name','address','address2','city','state','zip','country')) + $locations = Location::select(array('id','name','address','address2','city','state','zip','country','parent_id','currency'))->with('assets') ->whereNull('deleted_at'); if (Input::has('search')) { @@ -275,8 +275,7 @@ class LocationsController extends AdminController $limit = 50; } - - $allowed_columns = ['name','address','city','state','country']; + $allowed_columns = ['name','address','city','state','country','currency']; $order = Input::get('order') === 'asc' ? 'asc' : 'desc'; $sort = in_array(Input::get('sort'), $allowed_columns) ? Input::get('sort') : 'created_at'; @@ -293,11 +292,12 @@ class LocationsController extends AdminController $rows[] = array( 'name' => link_to('admin/locations/'.$location->id.'/view', $location->name), 'parent' => ($location->parent) ? $location->parent->name : '', - 'assets' => ($location->assets->count() + $location->assignedassets->count()), + 'assets' => ($location->assets->count() + $location->assignedassets->count()), 'address' => ($location->address) ? $location->address: '', 'city' => $location->city, - 'state' => $location->state, + 'state' => $location->state, 'country' => $location->country, + 'currency' => $location->currency, 'actions' => $actions ); } diff --git a/app/views/backend/locations/index.blade.php b/app/views/backend/locations/index.blade.php index 332b41b0ad..0a72aeea16 100755 --- a/app/views/backend/locations/index.blade.php +++ b/app/views/backend/locations/index.blade.php @@ -30,6 +30,7 @@ Locations :: <th data-sortable="true" data-field="name">@lang('admin/locations/table.name')</th> <th data-sortable="false" data-field="parent">@lang('admin/locations/table.parent')</th> <th data-searchable="false" data-sortable="false" data-field="assets">@lang('general.assets')</th> + <th data-searchable="true" data-sortable="true" data-field="currency">@lang('general.currency')</th> <th data-searchable="true" data-sortable="true" data-field="address">@lang('admin/locations/table.address')</th> <th data-searchable="true" data-sortable="true" data-field="city">@lang('admin/locations/table.city') </th> From 7dc0039c3b1d794b2a4706d9e16389b55c2ee1d0 Mon Sep 17 00:00:00 2001 From: snipe <snipe@snipe.net> Date: Wed, 21 Oct 2015 16:01:54 -0700 Subject: [PATCH 084/120] Fixed parent relationship --- app/config/version.php | 4 ++-- app/models/Location.php | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/config/version.php b/app/config/version.php index bfc0530315..acb087675a 100644 --- a/app/config/version.php +++ b/app/config/version.php @@ -1,5 +1,5 @@ <?php return array ( - 'app_version' => 'v2.0-265', - 'hash_version' => 'v2.0-265-ga896bb0', + 'app_version' => 'v2.0-266', + 'hash_version' => 'v2.0-266-gb5b8865', ); \ No newline at end of file diff --git a/app/models/Location.php b/app/models/Location.php index 880ffe34aa..9dbecbfbee 100755 --- a/app/models/Location.php +++ b/app/models/Location.php @@ -29,7 +29,7 @@ class Location extends Elegant } public function parent() { - return $this->hasOne('Location', 'parent_id'); + return $this->belongsTo('Location', 'parent_id'); } public function childLocations() { From b18be5aee8a5d2d7003f847d780917ecee7c5411 Mon Sep 17 00:00:00 2001 From: snipe <snipe@snipe.net> Date: Wed, 21 Oct 2015 16:14:15 -0700 Subject: [PATCH 085/120] Fixed relationshop again? --- app/config/version.php | 4 ++-- app/models/Location.php | 2 ++ app/models/User.php | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/app/config/version.php b/app/config/version.php index acb087675a..fe2444a51e 100644 --- a/app/config/version.php +++ b/app/config/version.php @@ -1,5 +1,5 @@ <?php return array ( - 'app_version' => 'v2.0-266', - 'hash_version' => 'v2.0-266-gb5b8865', + 'app_version' => 'v2.0-267', + 'hash_version' => 'v2.0-267-g218c765', ); \ No newline at end of file diff --git a/app/models/Location.php b/app/models/Location.php index 9dbecbfbee..df49df8dbf 100755 --- a/app/models/Location.php +++ b/app/models/Location.php @@ -104,6 +104,8 @@ class Location extends Elegant ->orWhere('city', 'LIKE', "%$search%") ->orWhere('state', 'LIKE', "%$search%") ->orWhere('zip', 'LIKE', "%$search%") + + // This doesn't actually work - need to use a table alias maybe? ->orWhere(function($query) use ($search) { $query->whereHas('parent', function($query) use ($search) { $query->where(function($query) use ($search) { diff --git a/app/models/User.php b/app/models/User.php index c44ebe25bd..dfc9151f91 100755 --- a/app/models/User.php +++ b/app/models/User.php @@ -80,7 +80,7 @@ class User extends SentryUserModel **/ public function manager() { - return $this->hasOne('User','manager_id')->withTrashed(); + return $this->belongsTo('User','manager_id')->withTrashed(); } From 9724d118e6aa45a18aa5ab16eeaee1aa6ae1b435 Mon Sep 17 00:00:00 2001 From: Daniel Dreier <ddreier@gmail.com> Date: Wed, 21 Oct 2015 19:17:55 -0500 Subject: [PATCH 086/120] Changing the comparison to not care about type allows for auth to fail when no user is found in the LDAP directory. --- app/controllers/AuthController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/AuthController.php b/app/controllers/AuthController.php index c4a300e770..4121faa042 100755 --- a/app/controllers/AuthController.php +++ b/app/controllers/AuthController.php @@ -45,7 +45,7 @@ class AuthController extends BaseController if ($connection) { // binding to ldap server $ldapbind = ldap_bind($connection, $ldaprdn, $ldappass); - if ( ($results = @ldap_search($connection, $baseDn, $filterQuery)) !==false ) { + if ( ($results = @ldap_search($connection, $baseDn, $filterQuery)) != false ) { $entry = ldap_first_entry($connection, $results); if ( ($userDn = @ldap_get_dn($connection, $entry)) !== false ) { if( ($isBound = ldap_bind($connection, $userDn, $password)) == "true") { From 348a566f894d568d8ce9d1b58ffe6ce03cfb7e65 Mon Sep 17 00:00:00 2001 From: snipe <snipe@snipe.net> Date: Wed, 21 Oct 2015 18:05:03 -0700 Subject: [PATCH 087/120] More responsive fixes --- app/controllers/admin/UsersController.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/controllers/admin/UsersController.php b/app/controllers/admin/UsersController.php index 6bdc2118c3..2b0668e77b 100755 --- a/app/controllers/admin/UsersController.php +++ b/app/controllers/admin/UsersController.php @@ -904,7 +904,10 @@ class UsersController extends AdminController { $rows[] = array( 'checkbox' =>'<div class="text-center hidden-xs hidden-sm"><input type="checkbox" name="edit_user['.$user->id.']" class="one_required"></div>', 'name' => '<a title="'.$user->fullName().'" href="../admin/users/'.$user->id.'/view">'.$user->fullName().'</a>', - 'email' => ($user->email!='') ? '<span class="hidden-md hidden-lg" style="display: inline !important;"><a href="mailto:'.$user->email.'">'.$user->email.'</a></span> <span class="hidden-xs hidden-sm"><a href="mailto:'.$user->email.'"><i class="fa fa-envelope"></i></a></span>' : '', + 'email' => ($user->email!='') ? + '<a href="mailto:'.$user->email.'" class="hidden-md hidden-lg">'.$user->email.'</a>' + .'<a href="mailto:'.$user->email.'" class="hidden-xs hidden-sm"><i class="fa fa-envelope"></i></a>' + .'</span>' : '', 'username' => $user->username, 'location' => ($user->location_id!='') ? $user->userloc->name : '', 'manager' => ($user->manager) ? '<a title="' . $user->manager->fullName() . '" href="users/' . $user->manager->id . '/view">' . $user->manager->fullName() . '</a>' : '', From d1192095d03584644fb1a8e26d5830383631cc11 Mon Sep 17 00:00:00 2001 From: snipe <snipe@snipe.net> Date: Wed, 21 Oct 2015 18:05:27 -0700 Subject: [PATCH 088/120] Fix for showing deleted items --- app/models/User.php | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/app/models/User.php b/app/models/User.php index dfc9151f91..b245f87ad2 100755 --- a/app/models/User.php +++ b/app/models/User.php @@ -211,11 +211,12 @@ class User extends SentryUserModel public function scopeTextsearch($query, $search) { - return $query->where('first_name', 'LIKE', "%$search%") - ->orWhere('last_name', 'LIKE', "%$search%") + return $query->where(function($query) use ($search) { + $query->where('first_name', 'LIKE', "%$search%") + ->orWhere('last_name', 'LIKE', "%$search%") ->orWhere('email', 'LIKE', "%$search%") ->orWhere('username', 'LIKE', "%$search%") - ->orWhere('notes', 'LIKE', "%$search%") + ->orWhere('notes', 'LIKE', "%$search%") ->orWhere(function($query) use ($search) { $query->whereHas('userloc', function($query) use ($search) { $query->where('name','LIKE','%'.$search.'%'); @@ -231,6 +232,7 @@ class User extends SentryUserModel }); }); }); + }); } From 7087a191c6e6761b27cd691d73d30940f40b18bd Mon Sep 17 00:00:00 2001 From: Patrick Gallagher <patgmac@gmail.com> Date: Wed, 21 Oct 2015 21:18:06 -0400 Subject: [PATCH 089/120] Typo in package name php-gd should be php5-gd. --- install.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/install.sh b/install.sh index 47895871f7..1deeac96e6 100755 --- a/install.sh +++ b/install.sh @@ -104,7 +104,7 @@ if [[ $distro == "u" ]]; then #We already established MySQL root & user PWs, so we dont need to be prompted. Let's go ahead and install Apache, PHP and MySQL. sudo DEBIAN_FRONTEND=noninteractive apt-get install -y lamp-server^ - sudo apt-get install -y php5 php5-mcrypt php5-curl php5-mysql php-gd + sudo apt-get install -y php5 php5-mcrypt php5-curl php5-mysql php5-gd #Create MySQL accounts echo "Create MySQL accounts" From 8ad220701eed66b49173a9e12e2883e7d355fbf7 Mon Sep 17 00:00:00 2001 From: Daniel Dreier <ddreier@gmail.com> Date: Wed, 21 Oct 2015 20:24:07 -0500 Subject: [PATCH 090/120] Fixes Purchase Cost not showing up on custom reports --- app/controllers/admin/ReportsController.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/controllers/admin/ReportsController.php b/app/controllers/admin/ReportsController.php index bab54d29f1..ce6ed1fa38 100644 --- a/app/controllers/admin/ReportsController.php +++ b/app/controllers/admin/ReportsController.php @@ -405,7 +405,7 @@ class ReportsController extends AdminController if (e( Input::get( 'purchase_date' ) ) == '1') { $header[] = 'Purchase Date'; } - if (( e( Input::get( 'purchase_cost' ) ) == '1' ) && ( e( Input::get( 'depreciation' ) ) == '0' )) { + if (( e( Input::get( 'purchase_cost' ) ) == '1' ) && ( e( Input::get( 'depreciation' ) ) != '1' )) { $header[] = 'Purchase Cost'; } if (e( Input::get( 'order' ) ) == '1') { @@ -461,7 +461,7 @@ class ReportsController extends AdminController if (e( Input::get( 'purchase_date' ) ) == '1') { $row[] = $asset->purchase_date; } - if (e( Input::get( 'purchase_cost' ) ) == '1') { + if (e( Input::get( 'purchase_cost' ) ) == '1' && ( e( Input::get( 'depreciation' ) ) != '1' )) { $row[] = '"' . number_format( $asset->purchase_cost ) . '"'; } if (e( Input::get( 'order' ) ) == '1') { From 0c830fa564105964d8c735cbc4d8604a131a78cf Mon Sep 17 00:00:00 2001 From: snipe <snipe@snipe.net> Date: Wed, 21 Oct 2015 19:08:30 -0700 Subject: [PATCH 091/120] Added hidden ID column --- app/controllers/admin/AssetsController.php | 3 ++- app/controllers/admin/CategoriesController.php | 3 ++- app/controllers/admin/ConsumablesController.php | 3 ++- app/controllers/admin/LicensesController.php | 3 ++- app/views/backend/categories/index.blade.php | 1 + app/views/backend/consumables/index.blade.php | 1 + app/views/backend/hardware/index.blade.php | 4 +++- app/views/backend/licenses/index.blade.php | 1 + app/views/backend/locations/index.blade.php | 1 + 9 files changed, 15 insertions(+), 5 deletions(-) diff --git a/app/controllers/admin/AssetsController.php b/app/controllers/admin/AssetsController.php index 6e87d49619..bf4a76160b 100755 --- a/app/controllers/admin/AssetsController.php +++ b/app/controllers/admin/AssetsController.php @@ -1131,7 +1131,7 @@ class AssetsController extends AdminController $assets = $assets->TextSearch(Input::get('search')); } - $allowed_columns = ['name','asset_tag','serial','model','checkout_date','category','notes']; + $allowed_columns = ['id','name','asset_tag','serial','model','checkout_date','category','notes']; $order = Input::get('order') === 'asc' ? 'asc' : 'desc'; $sort = in_array(Input::get('sort'), $allowed_columns) ? Input::get('sort') : 'asset_tag'; @@ -1177,6 +1177,7 @@ class AssetsController extends AdminController $rows[] = array( 'checkbox' =>'<div class="text-center"><input type="checkbox" name="edit_asset['.$asset->id.']" class="one_required"></div>', + 'id' => $asset->id, 'name' => '<a title="'.$asset->name.'" href="hardware/'.$asset->id.'/view">'.$asset->name.'</a>', 'asset_tag' => '<a title="'.$asset->asset_tag.'" href="hardware/'.$asset->id.'/view">'.$asset->asset_tag.'</a>', 'serial' => $asset->serial, diff --git a/app/controllers/admin/CategoriesController.php b/app/controllers/admin/CategoriesController.php index 5514879126..f407742e25 100755 --- a/app/controllers/admin/CategoriesController.php +++ b/app/controllers/admin/CategoriesController.php @@ -224,7 +224,7 @@ class CategoriesController extends AdminController $categories = $categories->TextSearch(Input::get('search')); } - $allowed_columns = ['name','category_type']; + $allowed_columns = ['id','name','category_type']; $order = Input::get('order') === 'asc' ? 'asc' : 'desc'; $sort = in_array(Input::get('sort'), $allowed_columns) ? Input::get('sort') : 'created_at'; @@ -239,6 +239,7 @@ class CategoriesController extends AdminController $actions = '<a href="'.route('update/category', $category->id).'" class="btn btn-warning btn-sm" style="margin-right:5px;"><i class="fa fa-pencil icon-white"></i></a><a data-html="false" class="btn delete-asset btn-danger btn-sm" data-toggle="modal" href="'.route('delete/category', $category->id).'" data-content="'.Lang::get('admin/categories/message.delete.confirm').'" data-title="'.Lang::get('general.delete').' '.htmlspecialchars($category->name).'?" onClick="return false;"><i class="fa fa-trash icon-white"></i></a>'; $rows[] = array( + 'id' => $category->id, 'name' => $category->name, 'category_type' => ucwords($category->category_type), 'count' => ($category->category_type=='asset') ? link_to('/admin/settings/categories/'.$category->id.'/view', $category->assetscount()) : $category->accessoriescount(), diff --git a/app/controllers/admin/ConsumablesController.php b/app/controllers/admin/ConsumablesController.php index a1c9913f59..0c232f965d 100644 --- a/app/controllers/admin/ConsumablesController.php +++ b/app/controllers/admin/ConsumablesController.php @@ -344,7 +344,7 @@ class ConsumablesController extends AdminController $consumables = $consumables->TextSearch(Input::get('search')); } - $allowed_columns = ['name']; + $allowed_columns = ['id','name']; $order = Input::get('order') === 'asc' ? 'asc' : 'desc'; $sort = in_array(Input::get('sort'), $allowed_columns) ? Input::get('sort') : 'created_at'; @@ -359,6 +359,7 @@ class ConsumablesController extends AdminController $actions = '<a href="'.route('checkout/consumable', $consumable->id).'" style="margin-right:5px;" class="btn btn-info btn-sm" '.(($consumable->numRemaining() > 0 ) ? '' : ' disabled').'>'.Lang::get('general.checkout').'</a><a href="'.route('update/consumable', $consumable->id).'" class="btn btn-warning btn-sm" style="margin-right:5px;"><i class="fa fa-pencil icon-white"></i></a><a data-html="false" class="btn delete-asset btn-danger btn-sm" data-toggle="modal" href="'.route('delete/consumable', $consumable->id).'" data-content="'.Lang::get('admin/consumables/message.delete.confirm').'" data-title="'.Lang::get('general.delete').' '.htmlspecialchars($consumable->name).'?" onClick="return false;"><i class="fa fa-trash icon-white"></i></a>'; $rows[] = array( + 'id' => $consumable->id, 'name' => link_to('admin/consumables/'.$consumable->id.'/view', $consumable->name), 'qty' => $consumable->qty, 'numRemaining' => $consumable->numRemaining(), diff --git a/app/controllers/admin/LicensesController.php b/app/controllers/admin/LicensesController.php index c19fa72334..fe7743b1af 100755 --- a/app/controllers/admin/LicensesController.php +++ b/app/controllers/admin/LicensesController.php @@ -893,7 +893,7 @@ class LicensesController extends AdminController $licenses = $licenses->TextSearch(Input::get('search')); } - $allowed_columns = ['name']; + $allowed_columns = ['id','name']; $order = Input::get('order') === 'asc' ? 'asc' : 'desc'; $sort = in_array(Input::get('sort'), $allowed_columns) ? Input::get('sort') : 'created_at'; @@ -908,6 +908,7 @@ class LicensesController extends AdminController $actions = '<span style="white-space: nowrap;"><a href="'.route('freecheckout/license', $license->id).'" class="btn btn-primary btn-sm" style="margin-right:5px;" '.(($license->remaincount() > 0) ? '' : 'disabled').'>'.Lang::get('general.checkout').'</a> <a href="'.route('clone/license', $license->id).'" class="btn btn-info btn-sm" style="margin-right:5px;" title="Clone asset"><i class="fa fa-files-o"></i></a><a href="'.route('update/license', $license->id).'" class="btn btn-warning btn-sm" style="margin-right:5px;"><i class="fa fa-pencil icon-white"></i></a><a data-html="false" class="btn delete-asset btn-danger btn-sm" data-toggle="modal" href="'.route('delete/license', $license->id).'" data-content="'.Lang::get('admin/licenses/message.delete.confirm').'" data-title="'.Lang::get('general.delete').' '.htmlspecialchars($license->name).'?" onClick="return false;"><i class="fa fa-trash icon-white"></i></a></span>'; $rows[] = array( + 'id' => $license->id, 'name' => link_to('/admin/licenses/'.$license->id.'/view', $license->name), 'serial' => link_to('/admin/licenses/'.$license->id.'/view', mb_strimwidth($license->serial, 0, 50, "...")), 'totalSeats' => $license->totalSeatsByLicenseID(), diff --git a/app/views/backend/categories/index.blade.php b/app/views/backend/categories/index.blade.php index 2052caa88c..741a9bde7b 100755 --- a/app/views/backend/categories/index.blade.php +++ b/app/views/backend/categories/index.blade.php @@ -28,6 +28,7 @@ data-cookie-id-table="categoriesTable"> <thead> <tr> + <th data-sortable="true" data-field="id" data-visible="false">@lang('general.id')</th> <th data-sortable="true" data-field="name">{{Lang::get('admin/categories/table.title')}}</th> <th data-sortable="true" data-field="category_type">{{Lang::get('general.type')}}</th> <th data-searchable="false" data-sortable="false" data-field="count">{{Lang::get('general.assets')}}</th> diff --git a/app/views/backend/consumables/index.blade.php b/app/views/backend/consumables/index.blade.php index 0e66dffe8f..3379d7b53e 100644 --- a/app/views/backend/consumables/index.blade.php +++ b/app/views/backend/consumables/index.blade.php @@ -28,6 +28,7 @@ data-cookie-id-table="consumablesTable"> <thead> <tr> + <th data-sortable="true" data-field="id" data-visible="false">@lang('general.id')</th> <th data-sortable="true" data-field="name">{{Lang::get('admin/consumables/table.title')}}</th> <th data-switchable="false" data-searchable="false" data-sortable="false" data-field="qty">{{Lang::get('admin/consumables/general.total')}}</th> <th data-switchable="false" data-searchable="false" data-sortable="false" data-field="numRemaining">{{Lang::get('admin/consumables/general.remaining')}}</th> diff --git a/app/views/backend/hardware/index.blade.php b/app/views/backend/hardware/index.blade.php index 9362168ad5..64d6886d78 100755 --- a/app/views/backend/hardware/index.blade.php +++ b/app/views/backend/hardware/index.blade.php @@ -57,8 +57,10 @@ data-cookie-id-table="assetsTable"> <thead> <tr> + <th data-class="hidden-xs" data-switchable="false" data-searchable="false" data-sortable="false" data-field="checkbox"><div class="text-center"><input type="checkbox" id="checkAll" style="padding-left: 0px;"></div></th> - <th data-sortable="true" data-field="name">{{Lang::get('admin/hardware/form.name')}}</th> + <th data-sortable="true" data-field="id" data-visible="false">@lang('general.id')</th> + <th data-sortable="true" data-field="name" data-visible="false">{{Lang::get('admin/hardware/form.name')}}</th> <th data-sortable="true" data-field="asset_tag">{{Lang::get('admin/hardware/table.asset_tag')}}</th> <th data-sortable="true" data-field="serial">{{Lang::get('admin/hardware/table.serial')}}</th> <th data-sortable="true" data-field="model">{{Lang::get('admin/hardware/form.model')}}</th> diff --git a/app/views/backend/licenses/index.blade.php b/app/views/backend/licenses/index.blade.php index d015f372aa..1ca2fb0879 100755 --- a/app/views/backend/licenses/index.blade.php +++ b/app/views/backend/licenses/index.blade.php @@ -26,6 +26,7 @@ data-cookie-id-table="licenseTable"> <thead> <tr> + <th data-sortable="true" data-field="id" data-visible="false">@lang('general.id')</th> <th data-field="name">{{Lang::get('admin/licenses/table.title')}}</th> <th data-field="serial">{{Lang::get('admin/licenses/table.serial')}}</th> <th data-field="totalSeats">{{Lang::get('admin/licenses/form.seats')}}</th> diff --git a/app/views/backend/locations/index.blade.php b/app/views/backend/locations/index.blade.php index 0a72aeea16..820a7b3380 100755 --- a/app/views/backend/locations/index.blade.php +++ b/app/views/backend/locations/index.blade.php @@ -27,6 +27,7 @@ Locations :: data-cookie-id-table="locationsTable"> <thead> <tr> + <th data-sortable="true" data-field="id" data-visible="false">@lang('general.id')</th> <th data-sortable="true" data-field="name">@lang('admin/locations/table.name')</th> <th data-sortable="false" data-field="parent">@lang('admin/locations/table.parent')</th> <th data-searchable="false" data-sortable="false" data-field="assets">@lang('general.assets')</th> From e03f07bb441735103463ed995c2f47c9e7278e2f Mon Sep 17 00:00:00 2001 From: snipe <snipe@snipe.net> Date: Wed, 21 Oct 2015 19:09:02 -0700 Subject: [PATCH 092/120] Manufacturers for #1266 --- .../admin/ManufacturersController.php | 50 +++++++++++- app/models/Manufacturer.php | 16 ++++ .../backend/manufacturers/index.blade.php | 81 +++++++++++++------ 3 files changed, 120 insertions(+), 27 deletions(-) diff --git a/app/controllers/admin/ManufacturersController.php b/app/controllers/admin/ManufacturersController.php index 8551e19b2b..3c267b61e3 100755 --- a/app/controllers/admin/ManufacturersController.php +++ b/app/controllers/admin/ManufacturersController.php @@ -20,9 +20,6 @@ class ManufacturersController extends AdminController */ public function getIndex() { - // Grab all the manufacturers - $manufacturers = Manufacturer::orderBy('created_at', 'DESC')->get(); - // Show the page return View::make('backend/manufacturers/index', compact('manufacturers')); } @@ -192,7 +189,54 @@ class ManufacturersController extends AdminController } + public function getDatatable() + { + $manufacturers = Manufacturer::select(array('id','name'))->with('assets') + ->whereNull('deleted_at'); + if (Input::has('search')) { + $manufacturers = $manufacturers->TextSearch(e(Input::get('search'))); + } + + if (Input::has('offset')) { + $offset = e(Input::get('offset')); + } else { + $offset = 0; + } + + if (Input::has('limit')) { + $limit = e(Input::get('limit')); + } else { + $limit = 50; + } + + $allowed_columns = ['id','name']; + $order = Input::get('order') === 'asc' ? 'asc' : 'desc'; + $sort = in_array(Input::get('sort'), $allowed_columns) ? Input::get('sort') : 'created_at'; + + $manufacturers->orderBy($sort, $order); + + $manufacturersCount = $manufacturers->count(); + $manufacturers = $manufacturers->skip($offset)->take($limit)->get(); + + $rows = array(); + + foreach($manufacturers as $manufacturer) { + $actions = '<a href="'.route('update/manufacturer', $manufacturer->id).'" class="btn btn-warning btn-sm" style="margin-right:5px;"><i class="fa fa-pencil icon-white"></i></a><a data-html="false" class="btn delete-asset btn-danger btn-sm" data-toggle="modal" href="'.route('delete/location', $manufacturer->id).'" data-content="'.Lang::get('admin/locations/message.delete.confirm').'" data-title="'.Lang::get('general.delete').' '.htmlspecialchars($manufacturer->name).'?" onClick="return false;"><i class="fa fa-trash icon-white"></i></a>'; + + $rows[] = array( + 'id' => $manufacturer->id, + 'name' => link_to('admin/manufacturers/'.$manufacturer->id.'/view', $manufacturer->name), + 'assets' => $manufacturer->assetscount(), + 'actions' => $actions + ); + } + + $data = array('total' => $manufacturersCount, 'rows' => $rows); + + return $data; + + } } diff --git a/app/models/Manufacturer.php b/app/models/Manufacturer.php index 6051237152..1831c150f5 100755 --- a/app/models/Manufacturer.php +++ b/app/models/Manufacturer.php @@ -26,4 +26,20 @@ class Manufacturer extends Elegant return $this->hasManyThrough('Asset', 'Model'); } + /** + * Query builder scope to search on text + * + * @param Illuminate\Database\Query\Builder $query Query builder instance + * @param text $search Search term + * + * @return Illuminate\Database\Query\Builder Modified query builder + */ + public function scopeTextSearch($query, $search) + { + + return $query->where(function($query) use ($search) + { + $query->where('name', 'LIKE', '%'.$search.'%'); + }); + } } diff --git a/app/views/backend/manufacturers/index.blade.php b/app/views/backend/manufacturers/index.blade.php index c70445ab47..da29369f0d 100755 --- a/app/views/backend/manufacturers/index.blade.php +++ b/app/views/backend/manufacturers/index.blade.php @@ -22,32 +22,24 @@ <div class="table-responsive"> -<table id="example"> - <thead> - <tr role="row"> - <th class="col-md-7" bSortable="true">@lang('admin/manufacturers/table.name')</th> - <th bSortable="true">@lang('general.assets')</th> - <th class="col-md-2 actions">@lang('table.actions')</th> - </tr> - </thead> - <tbody> - @foreach ($manufacturers as $manufacturer) - <tr> - <td>{{{ $manufacturer->name }}}</td> - <td><a href="{{ route('view/manufacturer',$manufacturer->id) }}">{{ $manufacturer->assetscount() }}</a></td> - <td> - <a href="{{ route('update/manufacturer', $manufacturer->id) }}" class="btn btn-warning btn-sm"><i class="fa fa-pencil icon-white"></i></a> - <a data-html="false" class="btn delete-asset btn-danger btn-sm" data-toggle="modal" href="{{ route('delete/manufacturer', $manufacturer->id) }}" data-content="@lang('admin/manufacturers/message.delete.confirm')" - data-title="@lang('general.delete') - {{ htmlspecialchars($manufacturer->name) }}?" onClick="return false;"><i class="fa fa-trash icon-white"></i></a> + <table + name="manufacturers" + id="table" + data-url="{{route('api.manufacturers.list')}}" + data-cookie="true" + data-click-to-select="true" + data-cookie-id-table="manufacturersTable"> + <thead> + <tr> + <th data-sortable="true" data-field="id" data-visible="false">@lang('general.id')</th> + <th data-sortable="true" data-field="name">@lang('admin/manufacturers/table.name')</th> + <th data-switchable="true" data-searchable="false" data-sortable="false" data-field="assets">@lang('general.assets')</th> + <th data-switchable="false" data-searchable="false" data-sortable="false" data-field="actions">@lang('table.actions')</th> + </tr> + </thead> + </table> - - </td> - </tr> - @endforeach - </tbody> -</table> </div> </div> @@ -69,5 +61,46 @@ </div> +@section('moar_scripts') +<script src="{{ asset('assets/js/bootstrap-table.js') }}"></script> +<script src="{{ asset('assets/js/extensions/cookie/bootstrap-table-cookie.js') }}"></script> +<script src="{{ asset('assets/js/extensions/mobile/bootstrap-table-mobile.js') }}"></script> +<script src="{{ asset('assets/js/extensions/export/bootstrap-table-export.js') }}"></script> +<script src="//rawgit.com/kayalshri/tableExport.jquery.plugin/master/tableExport.js"></script> +<script src="//rawgit.com/kayalshri/tableExport.jquery.plugin/master/jquery.base64.js"></script> +<script type="text/javascript"> + $('#table').bootstrapTable({ + classes: 'table table-responsive table-no-bordered', + undefinedText: '', + iconsPrefix: 'fa', + showRefresh: true, + search: true, + pageSize: {{{ Setting::getSettings()->per_page }}}, + pagination: true, + sidePagination: 'server', + sortable: true, + cookie: true, + mobileResponsive: true, + showExport: true, + showColumns: true, + exportDataType: 'all', + exportTypes: ['csv', 'txt','json', 'xml'], + maintainSelected: true, + paginationFirstText: "@lang('general.first')", + paginationLastText: "@lang('general.last')", + paginationPreText: "@lang('general.previous')", + paginationNextText: "@lang('general.next')", + pageList: ['10','25','50','100','150','200'], + icons: { + paginationSwitchDown: 'fa-caret-square-o-down', + paginationSwitchUp: 'fa-caret-square-o-up', + columns: 'fa-columns', + refresh: 'fa-refresh' + }, + + }); +</script> + +@stop @stop From f761b2e953f7abeb5f1f2bd21c42bf99516b8295 Mon Sep 17 00:00:00 2001 From: snipe <snipe@snipe.net> Date: Wed, 21 Oct 2015 19:09:20 -0700 Subject: [PATCH 093/120] Suppliers for #1266 --- app/controllers/admin/SuppliersController.php | 63 ++++++++- app/models/Supplier.php | 17 +++ app/views/backend/suppliers/index.blade.php | 120 +++++++++--------- 3 files changed, 138 insertions(+), 62 deletions(-) diff --git a/app/controllers/admin/SuppliersController.php b/app/controllers/admin/SuppliersController.php index 2244459285..281095657f 100755 --- a/app/controllers/admin/SuppliersController.php +++ b/app/controllers/admin/SuppliersController.php @@ -103,7 +103,7 @@ class SuppliersController extends AdminController return Redirect::to('admin/settings/suppliers/create')->with('error', Lang::get('admin/suppliers/message.create.error')); } - + public function store() { $supplier=new Supplier; @@ -115,7 +115,7 @@ class SuppliersController extends AdminController //$supplier->fill($new); $supplier->name=$new['name']; $supplier->user_id = Sentry::getId(); - + if($supplier->save()) { return JsonResponse::create($supplier); } else { @@ -163,7 +163,7 @@ class SuppliersController extends AdminController if ($validator->fails()) { - // The given data did not pass validation + // The given data did not pass validation return Redirect::back()->withInput()->withErrors($validator->messages()); } // attempt validation @@ -204,7 +204,7 @@ class SuppliersController extends AdminController // Redirect to the new supplier page return Redirect::to("admin/settings/suppliers")->with('success', Lang::get('admin/suppliers/message.update.success')); } - } + } // Redirect to the supplier management page return Redirect::to("admin/settings/suppliers/$supplierId/edit")->with('error', Lang::get('admin/suppliers/message.update.error')); @@ -264,6 +264,61 @@ class SuppliersController extends AdminController } + public function getDatatable() + { + $suppliers = Supplier::select(array('id','name','address','address2','city','state','country','fax', 'phone','email','contact')) + ->whereNull('deleted_at'); + + if (Input::has('search')) { + $suppliers = $suppliers->TextSearch(e(Input::get('search'))); + } + + if (Input::has('offset')) { + $offset = e(Input::get('offset')); + } else { + $offset = 0; + } + + if (Input::has('limit')) { + $limit = e(Input::get('limit')); + } else { + $limit = 50; + } + + $allowed_columns = ['id','name','address','phone','contact','fax','email']; + $order = Input::get('order') === 'asc' ? 'asc' : 'desc'; + $sort = in_array(Input::get('sort'), $allowed_columns) ? Input::get('sort') : 'created_at'; + + $suppliers->orderBy($sort, $order); + + $suppliersCount = $suppliers->count(); + $suppliers = $suppliers->skip($offset)->take($limit)->get(); + + $rows = array(); + + foreach($suppliers as $supplier) { + $actions = '<a href="'.route('update/supplier', $supplier->id).'" class="btn btn-warning btn-sm" style="margin-right:5px;"><i class="fa fa-pencil icon-white"></i></a><a data-html="false" class="btn delete-asset btn-danger btn-sm" data-toggle="modal" href="'.route('delete/location', $supplier->id).'" data-content="'.Lang::get('admin/locations/message.delete.confirm').'" data-title="'.Lang::get('general.delete').' '.htmlspecialchars($supplier->name).'?" onClick="return false;"><i class="fa fa-trash icon-white"></i></a>'; + + $rows[] = array( + 'id' => $supplier->id, + 'name' => link_to('admin/settings/suppliers/'.$supplier->id.'/view', $supplier->name), + 'contact' => $supplier->contact, + 'address' => $supplier->address.' '.$supplier->address2.' '.$supplier->city.' '.$supplier->state.' '.$supplier->country, + 'phone' => $supplier->phone, + 'fax' => $supplier->fax, + 'email' => ($supplier->email!='') ? '<a href="mailto:'.$supplier->email.'">'.$supplier->email.'</a>' : '', + 'assets' => $supplier->num_assets(), + 'licenses' => $supplier->num_licenses(), + 'actions' => $actions + ); + } + + $data = array('total' => $suppliersCount, 'rows' => $rows); + + return $data; + + } + } diff --git a/app/models/Supplier.php b/app/models/Supplier.php index b2b34ad906..d5f3df938a 100755 --- a/app/models/Supplier.php +++ b/app/models/Supplier.php @@ -52,4 +52,21 @@ class Supplier extends Elegant } return $url; } + + /** + * Query builder scope to search on text + * + * @param Illuminate\Database\Query\Builder $query Query builder instance + * @param text $search Search term + * + * @return Illuminate\Database\Query\Builder Modified query builder + */ + public function scopeTextSearch($query, $search) + { + + return $query->where(function($query) use ($search) + { + $query->where('name', 'LIKE', '%'.$search.'%'); + }); + } } diff --git a/app/views/backend/suppliers/index.blade.php b/app/views/backend/suppliers/index.blade.php index 665f39597d..47173d8e8e 100755 --- a/app/views/backend/suppliers/index.blade.php +++ b/app/views/backend/suppliers/index.blade.php @@ -19,66 +19,70 @@ <div class="user-profile"> <div class="row profile"> <div class="col-md-12"> - -@if ($suppliers->count() >= 1) -<table id="example"> - <thead> - <tr role="row"> - <th class="col-md-3">@lang('admin/suppliers/table.name')</th> - <th class="col-md-3">@lang('admin/suppliers/table.address')</th> - <th class="col-md-3">@lang('admin/suppliers/table.contact')</th> - <th class="col-md-3">@lang('admin/suppliers/table.phone')</th> - <th class="col-md-3">@lang('admin/suppliers/table.assets')</th> - <th class="col-md-3">@lang('admin/suppliers/table.licenses')</th> - <th class="col-md-2 actions">@lang('table.actions')</th> - </tr> - </thead> - <tbody> - @foreach ($suppliers as $supplier) - <tr> - <td><a href="{{ route('view/supplier', $supplier->id) }}"> - {{{ $supplier->name }}} - </a></td> - <td>{{{ $supplier->address }}} - - @if (($supplier->address2) || ($supplier->city) || ($supplier->state)) - - {{{ $supplier->city }}} - {{{ $supplier->state }}} {{{ $supplier->zip }}} - @endif - </td> - <td> - @if ($supplier->email) - <a href="mailto:{{{ $supplier->email }}}"> - {{{ $supplier->contact }}} - </a> - @else {{{ $supplier->contact }}} - @endif - </td> - <td>{{{ $supplier->phone }}}</td> - <td>{{{ $supplier->num_assets() }}}</td> - <td>{{{ $supplier->num_licenses() }}}</td> - <td> - <a href="{{ route('update/supplier', $supplier->id) }}" class="btn btn-warning btn-sm"><i class="fa fa-pencil icon-white"></i></a> - <a data-html="false" class="btn delete-asset btn-danger btn-sm" data-toggle="modal" href="{{ route('delete/supplier', $supplier->id) }}" data-content="@lang('admin/suppliers/message.delete.confirm')" - data-title="@lang('general.delete') - {{ htmlspecialchars($supplier->name) }}?" onClick="return false;"><i class="fa fa-trash icon-white"></i></a> - - - </td> - </tr> - @endforeach - </tbody> -</table> -@else - @lang('general.no_results') - - @endif + <table + name="suppliers" + id="table" + data-url="{{ route('api.suppliers.list') }}" + data-cookie="true" + data-click-to-select="true" + data-cookie-id-table="suppliersTable"> + <thead> + <tr> + <th data-sortable="true" data-field="id" data-visible="false">@lang('admin/suppliers/table.id')</th> + <th data-sortable="true" data-field="name">@lang('admin/locations/table.name')</th> + <th data-sortable="true" data-field="address">@lang('admin/suppliers/table.address')</th> + <th data-searchable="true" data-sortable="true" data-field="contact">@lang('admin/suppliers/table.contact')</th> + <th data-searchable="true" data-sortable="true" data-field="email">@lang('admin/suppliers/table.email')</th> + <th data-searchable="true" data-sortable="true" data-field="phone">@lang('admin/suppliers/table.phone')</th> + <th data-searchable="true" data-sortable="true" data-field="fax" data-visible="false">@lang('admin/suppliers/table.fax')</th> + <th data-searchable="false" data-sortable="false" data-field="assets">@lang('admin/suppliers/table.assets')</th> + <th data-searchable="false" data-sortable="false" data-field="licenses">@lang('admin/suppliers/table.licenses')</th> + <th data-switchable="false" data-searchable="false" data-sortable="false" data-field="actions">{{ Lang::get('table.actions') }}</th> + </tr> + </thead> + </table> + </div> </div> +@section('moar_scripts') +<script src="{{ asset('assets/js/bootstrap-table.js') }}"></script> +<script src="{{ asset('assets/js/extensions/cookie/bootstrap-table-cookie.js') }}"></script> +<script src="{{ asset('assets/js/extensions/mobile/bootstrap-table-mobile.js') }}"></script> +<script src="{{ asset('assets/js/extensions/export/bootstrap-table-export.js') }}"></script> +<script src="//rawgit.com/kayalshri/tableExport.jquery.plugin/master/tableExport.js"></script> +<script src="//rawgit.com/kayalshri/tableExport.jquery.plugin/master/jquery.base64.js"></script> +<script type="text/javascript"> + $('#table').bootstrapTable({ + classes: 'table table-responsive table-no-bordered', + undefinedText: '', + iconsPrefix: 'fa', + showRefresh: true, + search: true, + pageSize: {{{ Setting::getSettings()->per_page }}}, + pagination: true, + sidePagination: 'server', + sortable: true, + cookie: true, + mobileResponsive: true, + showExport: true, + showColumns: true, + exportDataType: 'all', + exportTypes: ['csv', 'txt','json', 'xml'], + maintainSelected: true, + paginationFirstText: "@lang('general.first')", + paginationLastText: "@lang('general.last')", + paginationPreText: "@lang('general.previous')", + paginationNextText: "@lang('general.next')", + pageList: ['10','25','50','100','150','200'], + icons: { + paginationSwitchDown: 'fa-caret-square-o-down', + paginationSwitchUp: 'fa-caret-square-o-up', + columns: 'fa-columns', + refresh: 'fa-refresh' + }, - -</div> - + }); +</script> +@stop @stop From 68e7941c212674b1c439dd005a7c09812077302c Mon Sep 17 00:00:00 2001 From: snipe <snipe@snipe.net> Date: Wed, 21 Oct 2015 19:09:35 -0700 Subject: [PATCH 094/120] Added hidden ID field for #1266 --- app/controllers/admin/LocationsController.php | 22 ++----------------- 1 file changed, 2 insertions(+), 20 deletions(-) diff --git a/app/controllers/admin/LocationsController.php b/app/controllers/admin/LocationsController.php index 798c372aee..e1d27421bd 100755 --- a/app/controllers/admin/LocationsController.php +++ b/app/controllers/admin/LocationsController.php @@ -275,7 +275,7 @@ class LocationsController extends AdminController $limit = 50; } - $allowed_columns = ['name','address','city','state','country','currency']; + $allowed_columns = ['id','name','address','city','state','country','currency']; $order = Input::get('order') === 'asc' ? 'asc' : 'desc'; $sort = in_array(Input::get('sort'), $allowed_columns) ? Input::get('sort') : 'created_at'; @@ -290,6 +290,7 @@ class LocationsController extends AdminController $actions = '<a href="'.route('update/location', $location->id).'" class="btn btn-warning btn-sm" style="margin-right:5px;"><i class="fa fa-pencil icon-white"></i></a><a data-html="false" class="btn delete-asset btn-danger btn-sm" data-toggle="modal" href="'.route('delete/location', $location->id).'" data-content="'.Lang::get('admin/locations/message.delete.confirm').'" data-title="'.Lang::get('general.delete').' '.htmlspecialchars($location->name).'?" onClick="return false;"><i class="fa fa-trash icon-white"></i></a>'; $rows[] = array( + 'id' => $location->id, 'name' => link_to('admin/locations/'.$location->id.'/view', $location->name), 'parent' => ($location->parent) ? $location->parent->name : '', 'assets' => ($location->assets->count() + $location->assignedassets->count()), @@ -308,25 +309,6 @@ class LocationsController extends AdminController } - public function getDataView($locationId) - { - $consumable = Consumable::find($consumableID); - $consumable_users = $consumable->users; - $count = $consumable_users->count(); - - $rows = array(); - - foreach ($consumable_users as $user) { - $rows[] = array( - 'name' => link_to('/admin/users/'.$user->id.'/view', $user->fullName()) - ); - } - - $data = array('total' => $count, 'rows' => $rows); - - return $data; - } - } From 9c914e7ef543821134c6c64c1a620588a979c526 Mon Sep 17 00:00:00 2001 From: snipe <snipe@snipe.net> Date: Wed, 21 Oct 2015 19:09:47 -0700 Subject: [PATCH 095/120] New API routes for #1266 --- app/routes.php | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/app/routes.php b/app/routes.php index 871e04df96..eefcdda15e 100755 --- a/app/routes.php +++ b/app/routes.php @@ -28,7 +28,11 @@ } else { return '0'; } - } ); + + }); + + Route::get( 'list', [ 'as' => 'api.statuslabels.list', 'uses' => 'StatuslabelsController@getDatatable' ] ); + } ); /*---Accessories API---*/ @@ -48,7 +52,22 @@ /*---Locations API---*/ Route::group(array('prefix'=>'locations'), function () { Route::get('list', array('as'=>'api.locations.list', 'uses'=>'LocationsController@getDatatable')); - Route::get('{$locationID}/view', array('as'=>'api.locations.view', 'uses'=>'LocationsController@getDataView')); + }); + + /*---Depreciations API---*/ + Route::group(array('prefix'=>'depreciations'), function () { + Route::get('list', array('as'=>'api.depreciations.list', 'uses'=>'DepreciationsController@getDatatable')); + Route::get('{$depreciationID}/view', array('as'=>'api.depreciations.view', 'uses'=>'DepreciationsController@getDataView')); + }); + + /*---Manufacturers API---*/ + Route::group(array('prefix'=>'manufacturers'), function () { + Route::get('list', array('as'=>'api.manufacturers.list', 'uses'=>'ManufacturersController@getDatatable')); + }); + + /*---Suppliers API---*/ + Route::group(array('prefix'=>'suppliers'), function () { + Route::get('list', array('as'=>'api.suppliers.list', 'uses'=>'SuppliersController@getDatatable')); }); /*---Users API---*/ From 0b87357f3b9290f2802685a1c7226a778194d93b Mon Sep 17 00:00:00 2001 From: snipe <snipe@snipe.net> Date: Wed, 21 Oct 2015 19:10:00 -0700 Subject: [PATCH 096/120] Search text method for #1266 --- app/config/version.php | 4 ++-- app/models/Statuslabel.php | 17 +++++++++++++++++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/app/config/version.php b/app/config/version.php index fe2444a51e..989daa6980 100644 --- a/app/config/version.php +++ b/app/config/version.php @@ -1,5 +1,5 @@ <?php return array ( - 'app_version' => 'v2.0-267', - 'hash_version' => 'v2.0-267-g218c765', + 'app_version' => 'v2.0-275', + 'hash_version' => 'v2.0-275-g68e7941', ); \ No newline at end of file diff --git a/app/models/Statuslabel.php b/app/models/Statuslabel.php index 0192e20685..aece44319a 100755 --- a/app/models/Statuslabel.php +++ b/app/models/Statuslabel.php @@ -55,4 +55,21 @@ class Statuslabel extends Elegant return $statustype; } + + /** + * Query builder scope to search on text + * + * @param Illuminate\Database\Query\Builder $query Query builder instance + * @param text $search Search term + * + * @return Illuminate\Database\Query\Builder Modified query builder + */ + public function scopeTextSearch($query, $search) + { + + return $query->where(function($query) use ($search) + { + $query->where('name', 'LIKE', '%'.$search.'%'); + }); + } } From ea4dfdd50c2ad6acfab3046f65536821266b07ea Mon Sep 17 00:00:00 2001 From: snipe <snipe@snipe.net> Date: Wed, 21 Oct 2015 19:24:01 -0700 Subject: [PATCH 097/120] Status labels for #1266 --- app/config/version.php | 4 +- .../admin/StatuslabelsController.php | 65 ++++++++++++- .../backend/statuslabels/index.blade.php | 97 +++++++++++-------- 3 files changed, 123 insertions(+), 43 deletions(-) diff --git a/app/config/version.php b/app/config/version.php index 989daa6980..5ac4781d73 100644 --- a/app/config/version.php +++ b/app/config/version.php @@ -1,5 +1,5 @@ <?php return array ( - 'app_version' => 'v2.0-275', - 'hash_version' => 'v2.0-275-g68e7941', + 'app_version' => 'v2.0-276', + 'hash_version' => 'v2.0-276-g9c914e7', ); \ No newline at end of file diff --git a/app/controllers/admin/StatuslabelsController.php b/app/controllers/admin/StatuslabelsController.php index ced912ca5f..dfbf08d0ec 100755 --- a/app/controllers/admin/StatuslabelsController.php +++ b/app/controllers/admin/StatuslabelsController.php @@ -24,9 +24,6 @@ class StatuslabelsController extends AdminController public function getIndex() { - // Grab all the statuslabels - $statuslabels = Statuslabel::orderBy('created_at', 'DESC')->get(); - // Show the page return View::make('backend/statuslabels/index', compact('statuslabels')); } @@ -230,5 +227,67 @@ class StatuslabelsController extends AdminController } + public function getDatatable() + { + $statuslabels = Statuslabel::select(array('id','name','deployable','pending','archived')) + ->whereNull('deleted_at'); + + if (Input::has('search')) { + $statuslabels = $statuslabels->TextSearch(e(Input::get('search'))); + } + + if (Input::has('offset')) { + $offset = e(Input::get('offset')); + } else { + $offset = 0; + } + + if (Input::has('limit')) { + $limit = e(Input::get('limit')); + } else { + $limit = 50; + } + + $allowed_columns = ['id','name']; + $order = Input::get('order') === 'asc' ? 'asc' : 'desc'; + $sort = in_array(Input::get('sort'), $allowed_columns) ? Input::get('sort') : 'created_at'; + + $statuslabels->orderBy($sort, $order); + + $statuslabelsCount = $statuslabels->count(); + $statuslabels = $statuslabels->skip($offset)->take($limit)->get(); + + $rows = array(); + + foreach($statuslabels as $statuslabel) { + + if ($statuslabel->deployable == 1) { + $label_type = Lang::get('admin/statuslabels/table.deployable'); + } elseif ($statuslabel->pending == 1) { + $label_type = Lang::get('admin/statuslabels/table.pending'); + } elseif ($statuslabel->archived == 1) { + $label_type = Lang::get('admin/statuslabels/table.archived'); + } else { + $label_type = Lang::get('admin/statuslabels/table.undeployable'); + } + + $actions = '<a href="'.route('update/location', $statuslabel->id).'" class="btn btn-warning btn-sm" style="margin-right:5px;"><i class="fa fa-pencil icon-white"></i></a><a data-html="false" class="btn delete-asset btn-danger btn-sm" data-toggle="modal" href="'.route('delete/statuslabel', $statuslabel->id).'" data-content="'.Lang::get('admin/locations/message.delete.confirm').'" data-title="'.Lang::get('general.delete').' '.htmlspecialchars($statuslabel->name).'?" onClick="return false;"><i class="fa fa-trash icon-white"></i></a>'; + + $rows[] = array( + 'id' => $statuslabel->id, + 'type' => $label_type, + 'name' => e($statuslabel->name), + 'actions' => $actions + ); + } + + $data = array('total' => $statuslabelsCount, 'rows' => $rows); + + return $data; + + } + + + } diff --git a/app/views/backend/statuslabels/index.blade.php b/app/views/backend/statuslabels/index.blade.php index b34b7887dd..2cb5335546 100755 --- a/app/views/backend/statuslabels/index.blade.php +++ b/app/views/backend/statuslabels/index.blade.php @@ -21,44 +21,23 @@ <div class="row profile"> <div class="col-md-9 bio"> - <br> - <!-- checked out assets table --> - - <table id="example"> - <thead> - <tr role="row"> - <th class="col-md-4">@lang('admin/statuslabels/table.name')</th> - <th class="col-md-4">@lang('admin/statuslabels/table.status_type')</th> - <th class="col-md-2 actions">@lang('table.actions')</th> - </tr> - </thead> - <tbody> - @foreach ($statuslabels as $statuslabel) - <tr> - <td>{{{ $statuslabel->name }}}</td> - <td> - @if ($statuslabel->deployable == 1) - @lang('admin/statuslabels/table.deployable') - @elseif ($statuslabel->pending == 1) - @lang('admin/statuslabels/table.pending') - @elseif ($statuslabel->archived == 1) - @lang('admin/statuslabels/table.archived') - @else - @lang('admin/statuslabels/table.undeployable') - @endif - </td> - <td> - <a href="{{ route('update/statuslabel', $statuslabel->id) }}" class="btn btn-warning btn-sm"><i class="fa fa-pencil icon-white"></i></a> -<a data-html="false" class="btn delete-asset btn-danger btn-sm" data-toggle="modal" href="{{ route('delete/statuslabel', $statuslabel->id) }}" data-content="@lang('admin/statuslabels/message.delete.confirm')" - data-title="@lang('general.delete') - {{ htmlspecialchars($statuslabel->name) }}?" onClick="return false;"><i class="fa fa-trash icon-white"></i></a> - </td> - </tr> - @endforeach - </tbody> - </table> - - </div> + <table + name="statuslabels" + id="table" + data-url="{{ route('api.statuslabels.list') }}" + data-cookie="true" + data-click-to-select="true" + data-cookie-id-table="statuslabelsTable"> + <thead> + <tr> + <th data-sortable="true" data-field="id" data-visible="false">@lang('general.id')</th> + <th data-sortable="true" data-field="name">@lang('admin/statuslabels/table.name')</th> + <th data-sortable="false" data-field="type">@lang('admin/statuslabels/table.status_type')</th> + <th data-switchable="false" data-searchable="false" data-sortable="false" data-field="actions">{{ Lang::get('table.actions') }}</th> + </tr> + </thead> + </table> +</div> <!-- side address column --> <div class="col-md-3 col-xs-12 address pull-right"> @@ -70,4 +49,46 @@ </div> + +@section('moar_scripts') +<script src="{{ asset('assets/js/bootstrap-table.js') }}"></script> +<script src="{{ asset('assets/js/extensions/cookie/bootstrap-table-cookie.js') }}"></script> +<script src="{{ asset('assets/js/extensions/mobile/bootstrap-table-mobile.js') }}"></script> +<script src="{{ asset('assets/js/extensions/export/bootstrap-table-export.js') }}"></script> +<script src="//rawgit.com/kayalshri/tableExport.jquery.plugin/master/tableExport.js"></script> +<script src="//rawgit.com/kayalshri/tableExport.jquery.plugin/master/jquery.base64.js"></script> +<script type="text/javascript"> + $('#table').bootstrapTable({ + classes: 'table table-responsive table-no-bordered', + undefinedText: '', + iconsPrefix: 'fa', + showRefresh: true, + search: true, + pageSize: {{{ Setting::getSettings()->per_page }}}, + pagination: true, + sidePagination: 'server', + sortable: true, + cookie: true, + mobileResponsive: true, + showExport: true, + showColumns: true, + exportDataType: 'all', + exportTypes: ['csv', 'txt','json', 'xml'], + maintainSelected: true, + paginationFirstText: "@lang('general.first')", + paginationLastText: "@lang('general.last')", + paginationPreText: "@lang('general.previous')", + paginationNextText: "@lang('general.next')", + pageList: ['10','25','50','100','150','200'], + icons: { + paginationSwitchDown: 'fa-caret-square-o-down', + paginationSwitchUp: 'fa-caret-square-o-up', + columns: 'fa-columns', + refresh: 'fa-refresh' + }, + + }); +</script> +@stop + @stop From 95b033bdb8c4fe37e9b89029b5cd1752db9a279f Mon Sep 17 00:00:00 2001 From: snipe <snipe@snipe.net> Date: Wed, 21 Oct 2015 19:33:22 -0700 Subject: [PATCH 098/120] Load table export helpers locally --- app/config/version.php | 4 +- app/views/backend/accessories/index.blade.php | 4 +- app/views/backend/categories/index.blade.php | 4 +- app/views/backend/consumables/index.blade.php | 4 +- app/views/backend/hardware/index.blade.php | 4 +- app/views/backend/licenses/index.blade.php | 4 +- app/views/backend/locations/index.blade.php | 4 +- .../backend/manufacturers/index.blade.php | 4 +- .../backend/statuslabels/index.blade.php | 4 +- app/views/backend/suppliers/index.blade.php | 4 +- app/views/backend/users/index.blade.php | 4 +- .../js/extensions/export/jquery.base64.js | 189 +++++++++ .../js/extensions/export/tableExport.js | 359 ++++++++++++++++++ 13 files changed, 570 insertions(+), 22 deletions(-) create mode 100644 public/assets/js/extensions/export/jquery.base64.js create mode 100644 public/assets/js/extensions/export/tableExport.js diff --git a/app/config/version.php b/app/config/version.php index 5ac4781d73..3d0e6adff4 100644 --- a/app/config/version.php +++ b/app/config/version.php @@ -1,5 +1,5 @@ <?php return array ( - 'app_version' => 'v2.0-276', - 'hash_version' => 'v2.0-276-g9c914e7', + 'app_version' => 'v2.0-277', + 'hash_version' => 'v2.0-277-g0b87357', ); \ No newline at end of file diff --git a/app/views/backend/accessories/index.blade.php b/app/views/backend/accessories/index.blade.php index bb63435f0e..4c71781633 100755 --- a/app/views/backend/accessories/index.blade.php +++ b/app/views/backend/accessories/index.blade.php @@ -54,8 +54,8 @@ <script src="{{ asset('assets/js/extensions/cookie/bootstrap-table-cookie.js') }}"></script> <script src="{{ asset('assets/js/extensions/mobile/bootstrap-table-mobile.js') }}"></script> <script src="{{ asset('assets/js/extensions/export/bootstrap-table-export.js') }}"></script> -<script src="//rawgit.com/kayalshri/tableExport.jquery.plugin/master/tableExport.js"></script> -<script src="//rawgit.com/kayalshri/tableExport.jquery.plugin/master/jquery.base64.js"></script> +<script src="{{ asset('assets/js/extensions/export/tableExport.js') }}"></script> +<script src="{{ asset('assets/js/extensions/export/jquery.base64.js') }}"></script> <script type="text/javascript"> $('#table').bootstrapTable({ classes: 'table table-responsive table-no-bordered', diff --git a/app/views/backend/categories/index.blade.php b/app/views/backend/categories/index.blade.php index 741a9bde7b..56716b5852 100755 --- a/app/views/backend/categories/index.blade.php +++ b/app/views/backend/categories/index.blade.php @@ -55,8 +55,8 @@ <script src="{{ asset('assets/js/extensions/cookie/bootstrap-table-cookie.js') }}"></script> <script src="{{ asset('assets/js/extensions/mobile/bootstrap-table-mobile.js') }}"></script> <script src="{{ asset('assets/js/extensions/export/bootstrap-table-export.js') }}"></script> -<script src="//rawgit.com/kayalshri/tableExport.jquery.plugin/master/tableExport.js"></script> -<script src="//rawgit.com/kayalshri/tableExport.jquery.plugin/master/jquery.base64.js"></script> +<script src="{{ asset('assets/js/extensions/export/tableExport.js') }}"></script> +<script src="{{ asset('assets/js/extensions/export/jquery.base64.js') }}"></script> <script type="text/javascript"> $('#table').bootstrapTable({ classes: 'table table-responsive table-no-bordered', diff --git a/app/views/backend/consumables/index.blade.php b/app/views/backend/consumables/index.blade.php index 3379d7b53e..22d5fb0849 100644 --- a/app/views/backend/consumables/index.blade.php +++ b/app/views/backend/consumables/index.blade.php @@ -53,8 +53,8 @@ <script src="{{ asset('assets/js/extensions/cookie/bootstrap-table-cookie.js') }}"></script> <script src="{{ asset('assets/js/extensions/mobile/bootstrap-table-mobile.js') }}"></script> <script src="{{ asset('assets/js/extensions/export/bootstrap-table-export.js') }}"></script> -<script src="//rawgit.com/kayalshri/tableExport.jquery.plugin/master/tableExport.js"></script> -<script src="//rawgit.com/kayalshri/tableExport.jquery.plugin/master/jquery.base64.js"></script> +<script src="{{ asset('assets/js/extensions/export/tableExport.js') }}"></script> +<script src="{{ asset('assets/js/extensions/export/jquery.base64.js') }}"></script> <script type="text/javascript"> $('#table').bootstrapTable({ classes: 'table table-responsive table-no-bordered', diff --git a/app/views/backend/hardware/index.blade.php b/app/views/backend/hardware/index.blade.php index 64d6886d78..ba85c2cdc8 100755 --- a/app/views/backend/hardware/index.blade.php +++ b/app/views/backend/hardware/index.blade.php @@ -97,8 +97,8 @@ <script src="{{ asset('assets/js/extensions/cookie/bootstrap-table-cookie.js') }}"></script> <script src="{{ asset('assets/js/extensions/mobile/bootstrap-table-mobile.js') }}"></script> <script src="{{ asset('assets/js/extensions/export/bootstrap-table-export.js') }}"></script> -<script src="//rawgit.com/kayalshri/tableExport.jquery.plugin/master/tableExport.js"></script> -<script src="//rawgit.com/kayalshri/tableExport.jquery.plugin/master/jquery.base64.js"></script> +<script src="{{ asset('assets/js/extensions/export/tableExport.js') }}"></script> +<script src="{{ asset('assets/js/extensions/export/jquery.base64.js') }}"></script> <script type="text/javascript"> $('#table').bootstrapTable({ classes: 'table table-responsive table-no-bordered', diff --git a/app/views/backend/licenses/index.blade.php b/app/views/backend/licenses/index.blade.php index 1ca2fb0879..22281a6858 100755 --- a/app/views/backend/licenses/index.blade.php +++ b/app/views/backend/licenses/index.blade.php @@ -43,8 +43,8 @@ <script src="{{ asset('assets/js/extensions/cookie/bootstrap-table-cookie.js') }}"></script> <script src="{{ asset('assets/js/extensions/mobile/bootstrap-table-mobile.js') }}"></script> <script src="{{ asset('assets/js/extensions/export/bootstrap-table-export.js') }}"></script> -<script src="//rawgit.com/kayalshri/tableExport.jquery.plugin/master/tableExport.js"></script> -<script src="//rawgit.com/kayalshri/tableExport.jquery.plugin/master/jquery.base64.js"></script> +<script src="{{ asset('assets/js/extensions/export/tableExport.js') }}"></script> +<script src="{{ asset('assets/js/extensions/export/jquery.base64.js') }}"></script> <script type="text/javascript"> $('#table').bootstrapTable({ classes: 'table table-responsive table-no-bordered', diff --git a/app/views/backend/locations/index.blade.php b/app/views/backend/locations/index.blade.php index 820a7b3380..3e15960c78 100755 --- a/app/views/backend/locations/index.blade.php +++ b/app/views/backend/locations/index.blade.php @@ -51,8 +51,8 @@ Locations :: <script src="{{ asset('assets/js/extensions/cookie/bootstrap-table-cookie.js') }}"></script> <script src="{{ asset('assets/js/extensions/mobile/bootstrap-table-mobile.js') }}"></script> <script src="{{ asset('assets/js/extensions/export/bootstrap-table-export.js') }}"></script> -<script src="//rawgit.com/kayalshri/tableExport.jquery.plugin/master/tableExport.js"></script> -<script src="//rawgit.com/kayalshri/tableExport.jquery.plugin/master/jquery.base64.js"></script> +<script src="{{ asset('assets/js/extensions/export/tableExport.js') }}"></script> +<script src="{{ asset('assets/js/extensions/export/jquery.base64.js') }}"></script> <script type="text/javascript"> $('#table').bootstrapTable({ classes: 'table table-responsive table-no-bordered', diff --git a/app/views/backend/manufacturers/index.blade.php b/app/views/backend/manufacturers/index.blade.php index da29369f0d..8b345ac2dd 100755 --- a/app/views/backend/manufacturers/index.blade.php +++ b/app/views/backend/manufacturers/index.blade.php @@ -66,8 +66,8 @@ <script src="{{ asset('assets/js/extensions/cookie/bootstrap-table-cookie.js') }}"></script> <script src="{{ asset('assets/js/extensions/mobile/bootstrap-table-mobile.js') }}"></script> <script src="{{ asset('assets/js/extensions/export/bootstrap-table-export.js') }}"></script> -<script src="//rawgit.com/kayalshri/tableExport.jquery.plugin/master/tableExport.js"></script> -<script src="//rawgit.com/kayalshri/tableExport.jquery.plugin/master/jquery.base64.js"></script> +<script src="{{ asset('assets/js/extensions/export/tableExport.js') }}"></script> +<script src="{{ asset('assets/js/extensions/export/jquery.base64.js') }}"></script> <script type="text/javascript"> $('#table').bootstrapTable({ classes: 'table table-responsive table-no-bordered', diff --git a/app/views/backend/statuslabels/index.blade.php b/app/views/backend/statuslabels/index.blade.php index 2cb5335546..c40df384fb 100755 --- a/app/views/backend/statuslabels/index.blade.php +++ b/app/views/backend/statuslabels/index.blade.php @@ -55,8 +55,8 @@ <script src="{{ asset('assets/js/extensions/cookie/bootstrap-table-cookie.js') }}"></script> <script src="{{ asset('assets/js/extensions/mobile/bootstrap-table-mobile.js') }}"></script> <script src="{{ asset('assets/js/extensions/export/bootstrap-table-export.js') }}"></script> -<script src="//rawgit.com/kayalshri/tableExport.jquery.plugin/master/tableExport.js"></script> -<script src="//rawgit.com/kayalshri/tableExport.jquery.plugin/master/jquery.base64.js"></script> +<script src="{{ asset('assets/js/extensions/export/tableExport.js') }}"></script> +<script src="{{ asset('assets/js/extensions/export/jquery.base64.js') }}"></script> <script type="text/javascript"> $('#table').bootstrapTable({ classes: 'table table-responsive table-no-bordered', diff --git a/app/views/backend/suppliers/index.blade.php b/app/views/backend/suppliers/index.blade.php index 47173d8e8e..519e458a30 100755 --- a/app/views/backend/suppliers/index.blade.php +++ b/app/views/backend/suppliers/index.blade.php @@ -49,8 +49,8 @@ <script src="{{ asset('assets/js/extensions/cookie/bootstrap-table-cookie.js') }}"></script> <script src="{{ asset('assets/js/extensions/mobile/bootstrap-table-mobile.js') }}"></script> <script src="{{ asset('assets/js/extensions/export/bootstrap-table-export.js') }}"></script> -<script src="//rawgit.com/kayalshri/tableExport.jquery.plugin/master/tableExport.js"></script> -<script src="//rawgit.com/kayalshri/tableExport.jquery.plugin/master/jquery.base64.js"></script> +<script src="{{ asset('assets/js/extensions/export/tableExport.js') }}"></script> +<script src="{{ asset('assets/js/extensions/export/jquery.base64.js') }}"></script> <script type="text/javascript"> $('#table').bootstrapTable({ classes: 'table table-responsive table-no-bordered', diff --git a/app/views/backend/users/index.blade.php b/app/views/backend/users/index.blade.php index 6930da4881..558553dd43 100755 --- a/app/views/backend/users/index.blade.php +++ b/app/views/backend/users/index.blade.php @@ -99,8 +99,8 @@ <script src="{{ asset('assets/js/extensions/cookie/bootstrap-table-cookie.js') }}"></script> <script src="{{ asset('assets/js/extensions/mobile/bootstrap-table-mobile.js') }}"></script> <script src="{{ asset('assets/js/extensions/export/bootstrap-table-export.js') }}"></script> -<script src="//rawgit.com/kayalshri/tableExport.jquery.plugin/master/tableExport.js"></script> -<script src="//rawgit.com/kayalshri/tableExport.jquery.plugin/master/jquery.base64.js"></script> +<script src="{{ asset('assets/js/extensions/export/tableExport.js') }}"></script> +<script src="{{ asset('assets/js/extensions/export/jquery.base64.js') }}"></script> <script type="text/javascript"> $('#table').bootstrapTable({ classes: 'table table-responsive table-no-bordered', diff --git a/public/assets/js/extensions/export/jquery.base64.js b/public/assets/js/extensions/export/jquery.base64.js new file mode 100644 index 0000000000..937705ce3a --- /dev/null +++ b/public/assets/js/extensions/export/jquery.base64.js @@ -0,0 +1,189 @@ +/*jslint adsafe: false, bitwise: true, browser: true, cap: false, css: false, + debug: false, devel: true, eqeqeq: true, es5: false, evil: false, + forin: false, fragment: false, immed: true, laxbreak: false, newcap: true, + nomen: false, on: false, onevar: true, passfail: false, plusplus: true, + regexp: false, rhino: true, safe: false, strict: false, sub: false, + undef: true, white: false, widget: false, windows: false */ +/*global jQuery: false, window: false */ +//"use strict"; + +/* + * Original code (c) 2010 Nick Galbreath + * http://code.google.com/p/stringencoders/source/browse/#svn/trunk/javascript + * + * jQuery port (c) 2010 Carlo Zottmann + * http://github.com/carlo/jquery-base64 + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. +*/ + +/* base64 encode/decode compatible with window.btoa/atob + * + * window.atob/btoa is a Firefox extension to convert binary data (the "b") + * to base64 (ascii, the "a"). + * + * It is also found in Safari and Chrome. It is not available in IE. + * + * if (!window.btoa) window.btoa = $.base64.encode + * if (!window.atob) window.atob = $.base64.decode + * + * The original spec's for atob/btoa are a bit lacking + * https://developer.mozilla.org/en/DOM/window.atob + * https://developer.mozilla.org/en/DOM/window.btoa + * + * window.btoa and $.base64.encode takes a string where charCodeAt is [0,255] + * If any character is not [0,255], then an exception is thrown. + * + * window.atob and $.base64.decode take a base64-encoded string + * If the input length is not a multiple of 4, or contains invalid characters + * then an exception is thrown. + */ + +jQuery.base64 = ( function( $ ) { + + var _PADCHAR = "=", + _ALPHA = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/", + _VERSION = "1.0"; + + + function _getbyte64( s, i ) { + // This is oddly fast, except on Chrome/V8. + // Minimal or no improvement in performance by using a + // object with properties mapping chars to value (eg. 'A': 0) + + var idx = _ALPHA.indexOf( s.charAt( i ) ); + + if ( idx === -1 ) { + throw "Cannot decode base64"; + } + + return idx; + } + + + function _decode( s ) { + var pads = 0, + i, + b10, + imax = s.length, + x = []; + + s = String( s ); + + if ( imax === 0 ) { + return s; + } + + if ( imax % 4 !== 0 ) { + throw "Cannot decode base64"; + } + + if ( s.charAt( imax - 1 ) === _PADCHAR ) { + pads = 1; + + if ( s.charAt( imax - 2 ) === _PADCHAR ) { + pads = 2; + } + + // either way, we want to ignore this last block + imax -= 4; + } + + for ( i = 0; i < imax; i += 4 ) { + b10 = ( _getbyte64( s, i ) << 18 ) | ( _getbyte64( s, i + 1 ) << 12 ) | ( _getbyte64( s, i + 2 ) << 6 ) | _getbyte64( s, i + 3 ); + x.push( String.fromCharCode( b10 >> 16, ( b10 >> 8 ) & 0xff, b10 & 0xff ) ); + } + + switch ( pads ) { + case 1: + b10 = ( _getbyte64( s, i ) << 18 ) | ( _getbyte64( s, i + 1 ) << 12 ) | ( _getbyte64( s, i + 2 ) << 6 ); + x.push( String.fromCharCode( b10 >> 16, ( b10 >> 8 ) & 0xff ) ); + break; + + case 2: + b10 = ( _getbyte64( s, i ) << 18) | ( _getbyte64( s, i + 1 ) << 12 ); + x.push( String.fromCharCode( b10 >> 16 ) ); + break; + } + + return x.join( "" ); + } + + + function _getbyte( s, i ) { + var x = s.charCodeAt( i ); + + if ( x > 255 ) { + throw "INVALID_CHARACTER_ERR: DOM Exception 5"; + } + + return x; + } + + + function _encode( s ) { + if ( arguments.length !== 1 ) { + throw "SyntaxError: exactly one argument required"; + } + + s = String( s ); + + var i, + b10, + x = [], + imax = s.length - s.length % 3; + + if ( s.length === 0 ) { + return s; + } + + for ( i = 0; i < imax; i += 3 ) { + b10 = ( _getbyte( s, i ) << 16 ) | ( _getbyte( s, i + 1 ) << 8 ) | _getbyte( s, i + 2 ); + x.push( _ALPHA.charAt( b10 >> 18 ) ); + x.push( _ALPHA.charAt( ( b10 >> 12 ) & 0x3F ) ); + x.push( _ALPHA.charAt( ( b10 >> 6 ) & 0x3f ) ); + x.push( _ALPHA.charAt( b10 & 0x3f ) ); + } + + switch ( s.length - imax ) { + case 1: + b10 = _getbyte( s, i ) << 16; + x.push( _ALPHA.charAt( b10 >> 18 ) + _ALPHA.charAt( ( b10 >> 12 ) & 0x3F ) + _PADCHAR + _PADCHAR ); + break; + + case 2: + b10 = ( _getbyte( s, i ) << 16 ) | ( _getbyte( s, i + 1 ) << 8 ); + x.push( _ALPHA.charAt( b10 >> 18 ) + _ALPHA.charAt( ( b10 >> 12 ) & 0x3F ) + _ALPHA.charAt( ( b10 >> 6 ) & 0x3f ) + _PADCHAR ); + break; + } + + return x.join( "" ); + } + + + return { + decode: _decode, + encode: _encode, + VERSION: _VERSION + }; + +}( jQuery ) ); diff --git a/public/assets/js/extensions/export/tableExport.js b/public/assets/js/extensions/export/tableExport.js new file mode 100644 index 0000000000..20e709fd16 --- /dev/null +++ b/public/assets/js/extensions/export/tableExport.js @@ -0,0 +1,359 @@ +/*The MIT License (MIT) + +Copyright (c) 2014 https://github.com/kayalshri/ + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE.*/ + +(function($){ + $.fn.extend({ + tableExport: function(options) { + var defaults = { + separator: ',', + ignoreColumn: [], + tableName:'yourTableName', + type:'csv', + pdfFontSize:14, + pdfLeftMargin:20, + escape:'true', + htmlContent:'false', + consoleLog:'false' + }; + + var options = $.extend(defaults, options); + var el = this; + + if(defaults.type == 'csv' || defaults.type == 'txt'){ + + // Header + var tdData =""; + $(el).find('thead').find('tr').each(function() { + tdData += "\n"; + $(this).filter(':visible').find('th').each(function(index,data) { + if ($(this).css('display') != 'none'){ + if(defaults.ignoreColumn.indexOf(index) == -1){ + tdData += '"' + parseString($(this)) + '"' + defaults.separator; + } + } + + }); + tdData = $.trim(tdData); + tdData = $.trim(tdData).substring(0, tdData.length -1); + }); + + // Row vs Column + $(el).find('tbody').find('tr').each(function() { + tdData += "\n"; + $(this).filter(':visible').find('td').each(function(index,data) { + if ($(this).css('display') != 'none'){ + if(defaults.ignoreColumn.indexOf(index) == -1){ + tdData += '"'+ parseString($(this)) + '"'+ defaults.separator; + } + } + }); + //tdData = $.trim(tdData); + tdData = $.trim(tdData).substring(0, tdData.length -1); + }); + + //output + if(defaults.consoleLog == 'true'){ + console.log(tdData); + } + var base64data = "base64," + $.base64.encode(tdData); + window.open('data:application/'+defaults.type+';filename=exportData;' + base64data); + }else if(defaults.type == 'sql'){ + + // Header + var tdData ="INSERT INTO `"+defaults.tableName+"` ("; + $(el).find('thead').find('tr').each(function() { + + $(this).filter(':visible').find('th').each(function(index,data) { + if ($(this).css('display') != 'none'){ + if(defaults.ignoreColumn.indexOf(index) == -1){ + tdData += '`' + parseString($(this)) + '`,' ; + } + } + + }); + tdData = $.trim(tdData); + tdData = $.trim(tdData).substring(0, tdData.length -1); + }); + tdData += ") VALUES "; + // Row vs Column + $(el).find('tbody').find('tr').each(function() { + tdData += "("; + $(this).filter(':visible').find('td').each(function(index,data) { + if ($(this).css('display') != 'none'){ + if(defaults.ignoreColumn.indexOf(index) == -1){ + tdData += '"'+ parseString($(this)) + '",'; + } + } + }); + + tdData = $.trim(tdData).substring(0, tdData.length -1); + tdData += "),"; + }); + tdData = $.trim(tdData).substring(0, tdData.length -1); + tdData += ";"; + + //output + //console.log(tdData); + + if(defaults.consoleLog == 'true'){ + console.log(tdData); + } + + var base64data = "base64," + $.base64.encode(tdData); + window.open('data:application/sql;filename=exportData;' + base64data); + + + }else if(defaults.type == 'json'){ + + var jsonHeaderArray = []; + $(el).find('thead').find('tr').each(function() { + var tdData =""; + var jsonArrayTd = []; + + $(this).filter(':visible').find('th').each(function(index,data) { + if ($(this).css('display') != 'none'){ + if(defaults.ignoreColumn.indexOf(index) == -1){ + jsonArrayTd.push(parseString($(this))); + } + } + }); + jsonHeaderArray.push(jsonArrayTd); + + }); + + var jsonArray = []; + $(el).find('tbody').find('tr').each(function() { + var tdData =""; + var jsonArrayTd = []; + + $(this).filter(':visible').find('td').each(function(index,data) { + if ($(this).css('display') != 'none'){ + if(defaults.ignoreColumn.indexOf(index) == -1){ + jsonArrayTd.push(parseString($(this))); + } + } + }); + jsonArray.push(jsonArrayTd); + + }); + + var jsonExportArray =[]; + jsonExportArray.push({header:jsonHeaderArray,data:jsonArray}); + + //Return as JSON + //console.log(JSON.stringify(jsonExportArray)); + + //Return as Array + //console.log(jsonExportArray); + if(defaults.consoleLog == 'true'){ + console.log(JSON.stringify(jsonExportArray)); + } + var base64data = "base64," + $.base64.encode(JSON.stringify(jsonExportArray)); + window.open('data:application/json;filename=exportData;' + base64data); + }else if(defaults.type == 'xml'){ + + var xml = '<?xml version="1.0" encoding="utf-8"?>'; + xml += '<tabledata><fields>'; + + // Header + $(el).find('thead').find('tr').each(function() { + $(this).filter(':visible').find('th').each(function(index,data) { + if ($(this).css('display') != 'none'){ + if(defaults.ignoreColumn.indexOf(index) == -1){ + xml += "<field>" + parseString($(this)) + "</field>"; + } + } + }); + }); + xml += '</fields><data>'; + + // Row Vs Column + var rowCount=1; + $(el).find('tbody').find('tr').each(function() { + xml += '<row id="'+rowCount+'">'; + var colCount=0; + $(this).filter(':visible').find('td').each(function(index,data) { + if ($(this).css('display') != 'none'){ + if(defaults.ignoreColumn.indexOf(index) == -1){ + xml += "<column-"+colCount+">"+parseString($(this))+"</column-"+colCount+">"; + } + } + colCount++; + }); + rowCount++; + xml += '</row>'; + }); + xml += '</data></tabledata>' + + if(defaults.consoleLog == 'true'){ + console.log(xml); + } + + var base64data = "base64," + $.base64.encode(xml); + window.open('data:application/xml;filename=exportData;' + base64data); + + }else if(defaults.type == 'excel' || defaults.type == 'doc'|| defaults.type == 'powerpoint' ){ + //console.log($(this).html()); + var excel="<table>"; + // Header + $(el).find('thead').find('tr').each(function() { + excel += "<tr>"; + $(this).filter(':visible').find('th').each(function(index,data) { + if ($(this).css('display') != 'none'){ + if(defaults.ignoreColumn.indexOf(index) == -1){ + excel += "<td>" + parseString($(this))+ "</td>"; + } + } + }); + excel += '</tr>'; + + }); + + + // Row Vs Column + var rowCount=1; + $(el).find('tbody').find('tr').each(function() { + excel += "<tr>"; + var colCount=0; + $(this).filter(':visible').find('td').each(function(index,data) { + if ($(this).css('display') != 'none'){ + if(defaults.ignoreColumn.indexOf(index) == -1){ + excel += "<td>"+parseString($(this))+"</td>"; + } + } + colCount++; + }); + rowCount++; + excel += '</tr>'; + }); + excel += '</table>' + + if(defaults.consoleLog == 'true'){ + console.log(excel); + } + + var excelFile = "<html xmlns:o='urn:schemas-microsoft-com:office:office' xmlns:x='urn:schemas-microsoft-com:office:"+defaults.type+"' xmlns='http://www.w3.org/TR/REC-html40'>"; + excelFile += "<head>"; + excelFile += "<!--[if gte mso 9]>"; + excelFile += "<xml>"; + excelFile += "<x:ExcelWorkbook>"; + excelFile += "<x:ExcelWorksheets>"; + excelFile += "<x:ExcelWorksheet>"; + excelFile += "<x:Name>"; + excelFile += "{worksheet}"; + excelFile += "</x:Name>"; + excelFile += "<x:WorksheetOptions>"; + excelFile += "<x:DisplayGridlines/>"; + excelFile += "</x:WorksheetOptions>"; + excelFile += "</x:ExcelWorksheet>"; + excelFile += "</x:ExcelWorksheets>"; + excelFile += "</x:ExcelWorkbook>"; + excelFile += "</xml>"; + excelFile += "<![endif]-->"; + excelFile += "</head>"; + excelFile += "<body>"; + excelFile += excel; + excelFile += "</body>"; + excelFile += "</html>"; + + var base64data = "base64," + $.base64.encode(excelFile); + window.open('data:application/vnd.ms-'+defaults.type+';filename=exportData.doc;' + base64data); + + }else if(defaults.type == 'png'){ + html2canvas($(el), { + onrendered: function(canvas) { + var img = canvas.toDataURL("image/png"); + window.open(img); + + + } + }); + }else if(defaults.type == 'pdf'){ + + var doc = new jsPDF('p','pt', 'a4', true); + doc.setFontSize(defaults.pdfFontSize); + + // Header + var startColPosition=defaults.pdfLeftMargin; + $(el).find('thead').find('tr').each(function() { + $(this).filter(':visible').find('th').each(function(index,data) { + if ($(this).css('display') != 'none'){ + if(defaults.ignoreColumn.indexOf(index) == -1){ + var colPosition = startColPosition+ (index * 50); + doc.text(colPosition,20, parseString($(this))); + } + } + }); + }); + + + // Row Vs Column + var startRowPosition = 20; var page =1;var rowPosition=0; + $(el).find('tbody').find('tr').each(function(index,data) { + rowCalc = index+1; + + if (rowCalc % 26 == 0){ + doc.addPage(); + page++; + startRowPosition=startRowPosition+10; + } + rowPosition=(startRowPosition + (rowCalc * 10)) - ((page -1) * 280); + + $(this).filter(':visible').find('td').each(function(index,data) { + if ($(this).css('display') != 'none'){ + if(defaults.ignoreColumn.indexOf(index) == -1){ + var colPosition = startColPosition+ (index * 50); + doc.text(colPosition,rowPosition, parseString($(this))); + } + } + + }); + + }); + + // Output as Data URI + doc.output('datauri'); + + } + + + function parseString(data){ + + if(defaults.htmlContent == 'true'){ + content_data = data.html().trim(); + }else{ + content_data = data.text().trim(); + } + + if(defaults.escape == 'true'){ + content_data = escape(content_data); + } + + + + return content_data; + } + + } + }); + })(jQuery); + From 7a306cd0f0889cef2077443441847e7bb5728c22 Mon Sep 17 00:00:00 2001 From: snipe <snipe@snipe.net> Date: Wed, 21 Oct 2015 19:43:09 -0700 Subject: [PATCH 099/120] Depreciations bootstrap tables for #1266 --- app/config/version.php | 4 +- .../admin/DepreciationsController.php | 57 +++++++++- app/models/Depreciation.php | 18 ++++ .../backend/depreciations/index.blade.php | 101 ++++++++++++------ 4 files changed, 138 insertions(+), 42 deletions(-) diff --git a/app/config/version.php b/app/config/version.php index 3d0e6adff4..0d0157ce26 100644 --- a/app/config/version.php +++ b/app/config/version.php @@ -1,5 +1,5 @@ <?php return array ( - 'app_version' => 'v2.0-277', - 'hash_version' => 'v2.0-277-g0b87357', + 'app_version' => 'v2.0-278', + 'hash_version' => 'v2.0-278-gea4dfdd', ); \ No newline at end of file diff --git a/app/controllers/admin/DepreciationsController.php b/app/controllers/admin/DepreciationsController.php index d45b3ff67f..7ab62ed3ab 100755 --- a/app/controllers/admin/DepreciationsController.php +++ b/app/controllers/admin/DepreciationsController.php @@ -22,9 +22,6 @@ class DepreciationsController extends AdminController public function getIndex() { - // Grab all the depreciations - $depreciations = Depreciation::orderBy('created_at', 'DESC')->get(); - // Show the page return View::make('backend/depreciations/index', compact('depreciations')); } @@ -123,7 +120,7 @@ class DepreciationsController extends AdminController if ($validator->fails()) { - // The given data did not pass validation + // The given data did not pass validation return Redirect::back()->withInput()->withErrors($validator->messages()); } // attempt validation @@ -137,7 +134,7 @@ class DepreciationsController extends AdminController // Redirect to the depreciation page return Redirect::to("admin/settings/depreciations/")->with('success', Lang::get('admin/depreciations/message.update.success')); } - } + } // Redirect to the depreciation management page return Redirect::to("admin/settings/depreciations/$depreciationId/edit")->with('error', Lang::get('admin/depreciations/message.update.error')); @@ -174,5 +171,55 @@ class DepreciationsController extends AdminController } + public function getDatatable() + { + $depreciations = Depreciation::select(array('id','name','months')); + + if (Input::has('search')) { + $depreciations = $depreciations->TextSearch(e(Input::get('search'))); + } + + if (Input::has('offset')) { + $offset = e(Input::get('offset')); + } else { + $offset = 0; + } + + if (Input::has('limit')) { + $limit = e(Input::get('limit')); + } else { + $limit = 50; + } + + $allowed_columns = ['id','name','months']; + $order = Input::get('order') === 'asc' ? 'asc' : 'desc'; + $sort = in_array(Input::get('sort'), $allowed_columns) ? Input::get('sort') : 'created_at'; + + $depreciations->orderBy($sort, $order); + + $depreciationsCount = $depreciations->count(); + $depreciations = $depreciations->skip($offset)->take($limit)->get(); + + $rows = array(); + + foreach($depreciations as $depreciation) { + $actions = '<a href="'.route('update/depreciations', $depreciation->id).'" class="btn btn-warning btn-sm" style="margin-right:5px;"><i class="fa fa-pencil icon-white"></i></a><a data-html="false" class="btn delete-asset btn-danger btn-sm" data-toggle="modal" href="'.route('delete/depreciations', $depreciation->id).'" data-content="'.Lang::get('admin/locations/message.delete.confirm').'" data-title="'.Lang::get('general.delete').' '.htmlspecialchars($depreciation->name).'?" onClick="return false;"><i class="fa fa-trash icon-white"></i></a>'; + + $rows[] = array( + 'id' => $depreciation->id, + 'name' => $depreciation->name, + 'months' => $depreciation->months, + 'actions' => $actions + ); + } + + $data = array('total' => $depreciationsCount, 'rows' => $rows); + + return $data; + + } + + + } diff --git a/app/models/Depreciation.php b/app/models/Depreciation.php index 1b1506f9d0..ac656c9716 100755 --- a/app/models/Depreciation.php +++ b/app/models/Depreciation.php @@ -17,4 +17,22 @@ class Depreciation extends Elegant { return $this->hasMany('License','depreciation_id')->count(); } + + /** + * Query builder scope to search on text + * + * @param Illuminate\Database\Query\Builder $query Query builder instance + * @param text $search Search term + * + * @return Illuminate\Database\Query\Builder Modified query builder + */ + public function scopeTextSearch($query, $search) + { + + return $query->where(function($query) use ($search) + { + $query->where('name', 'LIKE', '%'.$search.'%') + ->orWhere('months', 'LIKE', '%'.$search.'%'); + }); + } } diff --git a/app/views/backend/depreciations/index.blade.php b/app/views/backend/depreciations/index.blade.php index 78bc425d74..def43273f5 100755 --- a/app/views/backend/depreciations/index.blade.php +++ b/app/views/backend/depreciations/index.blade.php @@ -17,45 +17,76 @@ Asset Depreciations :: </div> <div class="user-profile"> -<div class="row profile"> -<div class="col-md-9 bio"> + <div class="row profile"> + <div class="col-md-9 bio"> - <table id="example"> - <thead> - <tr role="row"> - <th class="col-md-4">@lang('admin/depreciations/table.title')</th> - <th class="col-md-2">@lang('admin/depreciations/table.term')</th> - <th class="col-md-2 actions">@lang('table.actions')</th> - </tr> - </thead> - <tbody> - @foreach ($depreciations as $depreciation) - <tr> - <td>{{ $depreciation->name }}</td> - <td>{{ $depreciation->months }} @lang('admin/depreciations/table.months') </td> - <td> - <a href="{{ route('update/depreciations', $depreciation->id) }}" class="btn btn-warning btn-sm"><i class="fa fa-pencil icon-white"></i></a> -<a data-html="false" class="btn delete-asset btn-danger btn-sm" data-toggle="modal" href="{{ route('delete/depreciations', $depreciation->id) }}" data-content="@lang('admin/depreciations/message.delete.confirm')" -data-title="@lang('general.delete') - {{{ htmlspecialchars($depreciation->name) }}}?" onClick="return false;"><i class="fa fa-trash icon-white"></i></a> + <table + name="depreciations" + id="table" + data-url="{{ route('api.depreciations.list') }}" + data-cookie="true" + data-cookie-id-table="depreciationsTable"> + <thead> + <tr> + <th data-sortable="true" data-field="id" data-visible="false">@lang('general.id')</th> + <th data-sortable="true" data-field="name">@lang('admin/depreciations/table.title')</th> + <th data-sortable="false" data-field="months">@lang('admin/depreciations/table.term')</th> + <th data-switchable="false" data-searchable="false" data-sortable="false" data-field="actions">{{ Lang::get('table.actions') }}</th> + </tr> + </thead> + </table> + </div> - </td> - </tr> - @endforeach - </tbody> - </table> + <!-- side address column --> + <div class="col-md-3 col-xs-12 address pull-right"> + <br /><br /> + <h6>@lang('admin/depreciations/general.about_asset_depreciations')</h6> + <p>@lang('admin/depreciations/general.about_depreciations') </p> + </div> + </div> +</div> - </div> +@section('moar_scripts') +<script src="{{ asset('assets/js/bootstrap-table.js') }}"></script> +<script src="{{ asset('assets/js/extensions/cookie/bootstrap-table-cookie.js') }}"></script> +<script src="{{ asset('assets/js/extensions/mobile/bootstrap-table-mobile.js') }}"></script> +<script src="{{ asset('assets/js/extensions/export/bootstrap-table-export.js') }}"></script> +<script src="{{ asset('assets/js/extensions/export/tableExport.js') }}"></script> +<script src="{{ asset('assets/js/extensions/export/jquery.base64.js') }}"></script> +<script type="text/javascript"> +$('#table').bootstrapTable({ + classes: 'table table-responsive table-no-bordered', + undefinedText: '', + iconsPrefix: 'fa', + showRefresh: true, + search: true, + pageSize: {{{ Setting::getSettings()->per_page }}}, + pagination: true, + sidePagination: 'server', + sortable: true, + cookie: true, + mobileResponsive: true, + showExport: true, + showColumns: true, + exportDataType: 'all', + exportTypes: ['csv', 'txt','json', 'xml'], + maintainSelected: true, + paginationFirstText: "@lang('general.first')", + paginationLastText: "@lang('general.last')", + paginationPreText: "@lang('general.previous')", + paginationNextText: "@lang('general.next')", + pageList: ['10','25','50','100','150','200'], + icons: { + paginationSwitchDown: 'fa-caret-square-o-down', + paginationSwitchUp: 'fa-caret-square-o-up', + columns: 'fa-columns', + refresh: 'fa-refresh' + }, + +}); +</script> +@stop - - <!-- side address column --> - <div class="col-md-3 col-xs-12 address pull-right"> - <br /><br /> - <h6>@lang('admin/depreciations/general.about_asset_depreciations')</h6> - <p>@lang('admin/depreciations/general.about_depreciations') </p> - </div> - </div> - </div> @stop From bf32e89e0c52448869ded188256f65b79149770d Mon Sep 17 00:00:00 2001 From: snipe <snipe@snipe.net> Date: Wed, 21 Oct 2015 19:46:50 -0700 Subject: [PATCH 100/120] Corrected delete modal string for #1266 --- app/config/version.php | 4 ++-- app/controllers/admin/DepreciationsController.php | 2 +- app/controllers/admin/ManufacturersController.php | 2 +- app/controllers/admin/StatuslabelsController.php | 2 +- app/controllers/admin/SuppliersController.php | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/app/config/version.php b/app/config/version.php index 0d0157ce26..e281c2b60a 100644 --- a/app/config/version.php +++ b/app/config/version.php @@ -1,5 +1,5 @@ <?php return array ( - 'app_version' => 'v2.0-278', - 'hash_version' => 'v2.0-278-gea4dfdd', + 'app_version' => 'v2.0-279', + 'hash_version' => 'v2.0-279-g95b033b', ); \ No newline at end of file diff --git a/app/controllers/admin/DepreciationsController.php b/app/controllers/admin/DepreciationsController.php index 7ab62ed3ab..5161829b36 100755 --- a/app/controllers/admin/DepreciationsController.php +++ b/app/controllers/admin/DepreciationsController.php @@ -203,7 +203,7 @@ class DepreciationsController extends AdminController $rows = array(); foreach($depreciations as $depreciation) { - $actions = '<a href="'.route('update/depreciations', $depreciation->id).'" class="btn btn-warning btn-sm" style="margin-right:5px;"><i class="fa fa-pencil icon-white"></i></a><a data-html="false" class="btn delete-asset btn-danger btn-sm" data-toggle="modal" href="'.route('delete/depreciations', $depreciation->id).'" data-content="'.Lang::get('admin/locations/message.delete.confirm').'" data-title="'.Lang::get('general.delete').' '.htmlspecialchars($depreciation->name).'?" onClick="return false;"><i class="fa fa-trash icon-white"></i></a>'; + $actions = '<a href="'.route('update/depreciations', $depreciation->id).'" class="btn btn-warning btn-sm" style="margin-right:5px;"><i class="fa fa-pencil icon-white"></i></a><a data-html="false" class="btn delete-asset btn-danger btn-sm" data-toggle="modal" href="'.route('delete/depreciations', $depreciation->id).'" data-content="'.Lang::get('admin/depreciations/message.delete.confirm').'" data-title="'.Lang::get('general.delete').' '.htmlspecialchars($depreciation->name).'?" onClick="return false;"><i class="fa fa-trash icon-white"></i></a>'; $rows[] = array( 'id' => $depreciation->id, diff --git a/app/controllers/admin/ManufacturersController.php b/app/controllers/admin/ManufacturersController.php index 3c267b61e3..0b4c8a34c6 100755 --- a/app/controllers/admin/ManufacturersController.php +++ b/app/controllers/admin/ManufacturersController.php @@ -222,7 +222,7 @@ class ManufacturersController extends AdminController $rows = array(); foreach($manufacturers as $manufacturer) { - $actions = '<a href="'.route('update/manufacturer', $manufacturer->id).'" class="btn btn-warning btn-sm" style="margin-right:5px;"><i class="fa fa-pencil icon-white"></i></a><a data-html="false" class="btn delete-asset btn-danger btn-sm" data-toggle="modal" href="'.route('delete/location', $manufacturer->id).'" data-content="'.Lang::get('admin/locations/message.delete.confirm').'" data-title="'.Lang::get('general.delete').' '.htmlspecialchars($manufacturer->name).'?" onClick="return false;"><i class="fa fa-trash icon-white"></i></a>'; + $actions = '<a href="'.route('update/manufacturer', $manufacturer->id).'" class="btn btn-warning btn-sm" style="margin-right:5px;"><i class="fa fa-pencil icon-white"></i></a><a data-html="false" class="btn delete-asset btn-danger btn-sm" data-toggle="modal" href="'.route('delete/location', $manufacturer->id).'" data-content="'.Lang::get('admin/manufacturers/message.delete.confirm').'" data-title="'.Lang::get('general.delete').' '.htmlspecialchars($manufacturer->name).'?" onClick="return false;"><i class="fa fa-trash icon-white"></i></a>'; $rows[] = array( 'id' => $manufacturer->id, diff --git a/app/controllers/admin/StatuslabelsController.php b/app/controllers/admin/StatuslabelsController.php index dfbf08d0ec..1266a8dfb0 100755 --- a/app/controllers/admin/StatuslabelsController.php +++ b/app/controllers/admin/StatuslabelsController.php @@ -271,7 +271,7 @@ class StatuslabelsController extends AdminController $label_type = Lang::get('admin/statuslabels/table.undeployable'); } - $actions = '<a href="'.route('update/location', $statuslabel->id).'" class="btn btn-warning btn-sm" style="margin-right:5px;"><i class="fa fa-pencil icon-white"></i></a><a data-html="false" class="btn delete-asset btn-danger btn-sm" data-toggle="modal" href="'.route('delete/statuslabel', $statuslabel->id).'" data-content="'.Lang::get('admin/locations/message.delete.confirm').'" data-title="'.Lang::get('general.delete').' '.htmlspecialchars($statuslabel->name).'?" onClick="return false;"><i class="fa fa-trash icon-white"></i></a>'; + $actions = '<a href="'.route('update/location', $statuslabel->id).'" class="btn btn-warning btn-sm" style="margin-right:5px;"><i class="fa fa-pencil icon-white"></i></a><a data-html="false" class="btn delete-asset btn-danger btn-sm" data-toggle="modal" href="'.route('delete/statuslabel', $statuslabel->id).'" data-content="'.Lang::get('admin/statuslabels/message.delete.confirm').'" data-title="'.Lang::get('general.delete').' '.htmlspecialchars($statuslabel->name).'?" onClick="return false;"><i class="fa fa-trash icon-white"></i></a>'; $rows[] = array( 'id' => $statuslabel->id, diff --git a/app/controllers/admin/SuppliersController.php b/app/controllers/admin/SuppliersController.php index 281095657f..1b078bbd59 100755 --- a/app/controllers/admin/SuppliersController.php +++ b/app/controllers/admin/SuppliersController.php @@ -297,7 +297,7 @@ class SuppliersController extends AdminController $rows = array(); foreach($suppliers as $supplier) { - $actions = '<a href="'.route('update/supplier', $supplier->id).'" class="btn btn-warning btn-sm" style="margin-right:5px;"><i class="fa fa-pencil icon-white"></i></a><a data-html="false" class="btn delete-asset btn-danger btn-sm" data-toggle="modal" href="'.route('delete/location', $supplier->id).'" data-content="'.Lang::get('admin/locations/message.delete.confirm').'" data-title="'.Lang::get('general.delete').' '.htmlspecialchars($supplier->name).'?" onClick="return false;"><i class="fa fa-trash icon-white"></i></a>'; + $actions = '<a href="'.route('update/supplier', $supplier->id).'" class="btn btn-warning btn-sm" style="margin-right:5px;"><i class="fa fa-pencil icon-white"></i></a><a data-html="false" class="btn delete-asset btn-danger btn-sm" data-toggle="modal" href="'.route('delete/location', $supplier->id).'" data-content="'.Lang::get('admin/suppliers/message.delete.confirm').'" data-title="'.Lang::get('general.delete').' '.htmlspecialchars($supplier->name).'?" onClick="return false;"><i class="fa fa-trash icon-white"></i></a>'; $rows[] = array( 'id' => $supplier->id, From 7087e86ca5cc0e0f95289f1eeb6a2f81ba8538ea Mon Sep 17 00:00:00 2001 From: snipe <snipe@snipe.net> Date: Wed, 21 Oct 2015 21:23:58 -0700 Subject: [PATCH 101/120] Nicer (tho non-ajaxy) table --- app/config/version.php | 4 ++-- app/views/backend/hardware/view.blade.php | 10 ++++---- app/views/backend/suppliers/view.blade.php | 27 +++++++++++----------- 3 files changed, 22 insertions(+), 19 deletions(-) diff --git a/app/config/version.php b/app/config/version.php index e281c2b60a..05e6c43052 100644 --- a/app/config/version.php +++ b/app/config/version.php @@ -1,5 +1,5 @@ <?php return array ( - 'app_version' => 'v2.0-279', - 'hash_version' => 'v2.0-279-g95b033b', + 'app_version' => 'v2.0-280', + 'hash_version' => 'v2.0-280-g7a306cd', ); \ No newline at end of file diff --git a/app/views/backend/hardware/view.blade.php b/app/views/backend/hardware/view.blade.php index f02ba9842b..a2ecca7bfc 100755 --- a/app/views/backend/hardware/view.blade.php +++ b/app/views/backend/hardware/view.blade.php @@ -105,10 +105,12 @@ @endif @if ($asset->supplier_id) - <div class="col-md-6" style="padding-bottom: 5px;"><strong>@lang('admin/hardware/form.supplier'): </strong> - <a href="{{ route('view/supplier', $asset->supplier_id) }}"> - {{{ $asset->supplier->name }}} - </a> </div> + <div class="col-md-6" style="padding-bottom: 5px;"> + <strong>@lang('admin/hardware/form.supplier'): </strong> + <a href="{{ route('view/supplier', $asset->supplier_id) }}"> + {{{ $asset->supplier->name }}} + </a> + </div> @endif @if ($asset->warranty_months) diff --git a/app/views/backend/suppliers/view.blade.php b/app/views/backend/suppliers/view.blade.php index 76da20659c..d9773519da 100755 --- a/app/views/backend/suppliers/view.blade.php +++ b/app/views/backend/suppliers/view.blade.php @@ -23,19 +23,19 @@ <div class="user-profile"> <div class="row profile"> <div class="col-md-9 bio"> - <div class="profile-box"> - <!-- checked out suppliers table --> - <h6>Assets</h6> - <br> - @if (count($supplier->assets) > 0) - <table id="example"> + <!-- checked out suppliers table --> + <h6>Assets</h6> + <br> + @if (count($supplier->assets) > 0) + <div class="table-responsive"> + <table class="display table table-hover"> <thead> <tr role="row"> <th class="col-md-3">Asset Tag</th> - <th class="col-md-3">Name</th> - <th class="col-md-3">User</th> - <th class="col-md-2">Actions</th> + <th class="col-md-3"><span class="line"></span>Name</th> + <th class="col-md-3"><span class="line"></span>User</th> + <th class="col-md-2"><span class="line"></span>Actions</th> </tr> </thead> <tbody> @@ -54,9 +54,9 @@ </td> <td> @if ($supplierassets->assigned_to != '') - <a href="{{ route('checkin/hardware', $supplierassets->id) }}" class="btn-flat info">Checkin</a> + <a href="{{ route('checkin/hardware', $supplierassets->id) }}" class="btn btn-info btn-sm">Checkin</a> @else - <a href="{{ route('checkout/hardware', $supplierassets->id) }}" class="btn-flat success">Checkout</a> + <a href="{{ route('checkout/hardware', $supplierassets->id) }}" class="btn btn-success btn-sm">Checkout</a> @endif </td> @@ -66,6 +66,7 @@ </tbody> </table> + </div> @else <div class="col-md-12"> @@ -83,7 +84,7 @@ <table class="table table-hover"> <thead> <tr> - <th class="col-md-4"><span class="line"></span>Name</th> + <th class="col-md-4">Name</th> <th class="col-md-4"><span class="line"></span>Serial</th> </tr> </thead> @@ -163,7 +164,7 @@ </div> @endif - </div> + </div> From 28fcd2b8abcee12f08095781aee6d6701d451c73 Mon Sep 17 00:00:00 2001 From: snipe <snipe@snipe.net> Date: Wed, 21 Oct 2015 21:31:38 -0700 Subject: [PATCH 102/120] Fixed indenting --- app/views/backend/users/view.blade.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/backend/users/view.blade.php b/app/views/backend/users/view.blade.php index 3f4be378e7..b6ff07b5b7 100755 --- a/app/views/backend/users/view.blade.php +++ b/app/views/backend/users/view.blade.php @@ -82,7 +82,7 @@ <!-- checked out assets table --> @if (count($user->assets) > 0) <div class="table-responsive"> - <table class="display table table-hover"> + <table class="display table table-hover"> <thead> <tr> <th class="col-md-3">@lang('admin/hardware/table.asset_model')</th> From 9d6608c8f1810ff7ba40c2b624cea1b4c86ff5da Mon Sep 17 00:00:00 2001 From: snipe <snipe@snipe.net> Date: Wed, 21 Oct 2015 22:19:02 -0700 Subject: [PATCH 103/120] Asset maintenances for #1266 --- app/config/version.php | 4 +- .../admin/AssetMaintenancesController.php | 98 ++++++++--------- app/lang/en/admin/asset_maintenances/form.php | 12 +- .../en/admin/asset_maintenances/table.php | 6 +- app/models/AssetMaintenance.php | 24 +++- .../asset_maintenances/index.blade.php | 103 +++++++++++------- app/views/backend/categories/index.blade.php | 2 +- 7 files changed, 142 insertions(+), 107 deletions(-) diff --git a/app/config/version.php b/app/config/version.php index 05e6c43052..26f1c46129 100644 --- a/app/config/version.php +++ b/app/config/version.php @@ -1,5 +1,5 @@ <?php return array ( - 'app_version' => 'v2.0-280', - 'hash_version' => 'v2.0-280-g7a306cd', + 'app_version' => 'v2.0-282', + 'hash_version' => 'v2.0-282-g7087e86', ); \ No newline at end of file diff --git a/app/controllers/admin/AssetMaintenancesController.php b/app/controllers/admin/AssetMaintenancesController.php index 846b8ff153..85147a24b1 100644 --- a/app/controllers/admin/AssetMaintenancesController.php +++ b/app/controllers/admin/AssetMaintenancesController.php @@ -45,71 +45,63 @@ * @author Vincent Sposato <vincent.sposato@gmail.com> * @version v1.0 */ - public function getDatatable() - { - $assetMaintenances = AssetMaintenance::orderBy( 'created_at', 'DESC' ) - ->get(); + public function getDatatable() + { + $maintenances = AssetMaintenance::with('asset','supplier') + ->whereNull('deleted_at'); - $actions = new \Chumper\Datatable\Columns\FunctionColumn( 'actions', function ( $assetMaintenances ) { + if (Input::has('search')) { + $maintenances = $maintenances->TextSearch(e(Input::get('search'))); + } - return '<a href="' . route( 'update/asset_maintenance', $assetMaintenances->id ) - . '" class="btn btn-warning btn-sm" style="margin-right:5px;"><i class="fa fa-pencil icon-white"></i></a><a data-html="false" class="btn delete-asset btn-danger btn-sm" data-toggle="modal" href="' - . route( 'delete/asset_maintenance', $assetMaintenances->id ) . '" data-content="' - . Lang::get( 'admin/asset_maintenances/message.delete.confirm' ) . '" data-title="' - . Lang::get( 'general.delete' ) . ' ' . htmlspecialchars( $assetMaintenances->title ) - . '?" onClick="return false;"><i class="fa fa-trash icon-white"></i></a>'; - } ); + if (Input::has('offset')) { + $offset = e(Input::get('offset')); + } else { + $offset = 0; + } - return Datatable::collection( $assetMaintenances ) - ->addColumn( 'asset', function ( $assetMaintenances ) { + if (Input::has('limit')) { + $limit = e(Input::get('limit')); + } else { + $limit = 50; + } - return link_to( '/hardware/' . $assetMaintenances->asset_id . '/view', - mb_strimwidth( $assetMaintenances->asset->name, 0, 50, "..." ) ); - } ) - ->addColumn( 'supplier', function ( $assetMaintenances ) { + $allowed_columns = ['id','title','asset_maintenance_time','asset_maintenance_type','cost','start_date','completion_date','notes']; + $order = Input::get('order') === 'asc' ? 'asc' : 'desc'; + $sort = in_array(Input::get('sort'), $allowed_columns) ? Input::get('sort') : 'created_at'; - return link_to( '/admin/settings/suppliers/' . $assetMaintenances->supplier_id - . '/view', - mb_strimwidth( $assetMaintenances->supplier->name, 0, 50, "..." ) ); - } ) - ->addColumn( 'asset_maintenance_type', function ( $assetMaintenances ) { + $maintenances->orderBy($sort, $order); - return $assetMaintenances->asset_maintenance_type; - } ) - ->addColumn( 'title', function ( $assetMaintenances ) { + $maintenancesCount = $maintenances->count(); + $maintenances = $maintenances->skip($offset)->take($limit)->get(); - return link_to( '/admin/asset_maintenances/' . $assetMaintenances->id . '/view', - mb_strimwidth( $assetMaintenances->title, 0, 50, "..." ) ); - } ) - ->addColumn( 'start_date', function ( $assetMaintenances ) { + $rows = array(); - return $assetMaintenances->start_date; - } ) - ->addColumn( 'completion_date', function ( $assetMaintenances ) { + foreach($maintenances as $maintenance) { - return $assetMaintenances->completion_date; - } ) - ->addColumn( 'asset_maintenance_time', function ( $assetMaintenances ) { + $actions = '<a href="'.route('update/location', $maintenance->id).'" class="btn btn-warning btn-sm" style="margin-right:5px;"><i class="fa fa-pencil icon-white"></i></a><a data-html="false" class="btn delete-asset btn-danger btn-sm" data-toggle="modal" href="'.route('delete/statuslabel', $maintenance->id).'" data-content="'.Lang::get('admin/asset_maintenances/message.delete.confirm').'" data-title="'.Lang::get('general.delete').' '.htmlspecialchars($maintenance->title).'?" onClick="return false;"><i class="fa fa-trash icon-white"></i></a>'; - if (is_null( $assetMaintenances->asset_maintenance_time )) { - $assetMaintenances->asset_maintenance_time = Carbon::now() - ->diffInDays( Carbon::parse( $assetMaintenances->start_date ) ); - } + $rows[] = array( + 'id' => $maintenance->id, + 'asset_name' => $maintenance->asset->showAssetName(), + 'title' => $maintenance->title, + 'notes' => $maintenance->notes, + 'supplier' => $maintenance->supplier->name, + 'cost' => ($maintenance->cost) ? $maintenance->asset->assetloc->currency.''.$maintenance->cost : $maintenance->cost , + 'asset_maintenance_type' => e($maintenance->asset_maintenance_type), + 'start_date' => $maintenance->start_date, + 'time' => $maintenance->asset_maintenance_time, + 'completion_date' => $maintenance->completion_date, + 'actions' => $actions + ); + } - return intval( $assetMaintenances->asset_maintenance_time ); - } ) - ->addColumn( 'cost', function ( $assetMaintenances ) { + $data = array('total' => $maintenancesCount, 'rows' => $rows); - return sprintf( Lang::get( 'general.currency' ) . '%01.2f', $assetMaintenances->cost ); - } ) - ->addColumn( $actions ) - ->searchColumns( 'asset', 'supplier', 'asset_maintenance_type', 'title', 'start_date', - 'completion_date', 'asset_maintenance_time', 'cost', 'actions' ) - ->orderColumns( 'asset', 'supplier', 'asset_maintenance_type', 'title', 'start_date', - 'completion_date', 'asset_maintenance_time', 'cost', 'actions' ) - ->make(); - } + return $data; + + } /** * getCreate @@ -461,4 +453,4 @@ return View::make( 'backend/asset_maintenances/view')->with('assetMaintenance', $assetMaintenance); } - } \ No newline at end of file + } diff --git a/app/lang/en/admin/asset_maintenances/form.php b/app/lang/en/admin/asset_maintenances/form.php index 785d06b08f..2aa005c45f 100755 --- a/app/lang/en/admin/asset_maintenances/form.php +++ b/app/lang/en/admin/asset_maintenances/form.php @@ -1,14 +1,14 @@ <?php return [ - 'asset_maintenance_type' => 'Asset Maintenance Type', + 'asset_maintenance_type' => 'Maintenance Type', 'title' => 'Title', - 'start_date' => 'Start Date', - 'completion_date' => 'Completion Date', + 'start_date' => 'Started', + 'completion_date' => 'Completed', 'cost' => 'Cost', 'is_warranty' => 'Warranty Improvement', - 'asset_maintenance_time' => 'Asset Maintenance Time (in days)', + 'asset_maintenance_time' => 'Days', 'notes' => 'Notes', - 'update' => 'Update Asset Maintenance', - 'create' => 'Create Asset Maintenance' + 'update' => 'Update', + 'create' => 'Create' ]; diff --git a/app/lang/en/admin/asset_maintenances/table.php b/app/lang/en/admin/asset_maintenances/table.php index 02e9060bf6..5b83539914 100755 --- a/app/lang/en/admin/asset_maintenances/table.php +++ b/app/lang/en/admin/asset_maintenances/table.php @@ -2,8 +2,8 @@ return [ 'title' => 'Asset Maintenance', - 'asset_name' => 'Asset Name', - 'supplier_name' => 'Supplier Name', + 'asset_name' => 'Asset', + 'supplier_name' => 'Supplier', 'is_warranty' => 'Warranty', 'dl_csv' => 'Download CSV' - ]; \ No newline at end of file + ]; diff --git a/app/models/AssetMaintenance.php b/app/models/AssetMaintenance.php index 9d42f381ba..9a99c8d99f 100644 --- a/app/models/AssetMaintenance.php +++ b/app/models/AssetMaintenance.php @@ -81,4 +81,26 @@ return $query->whereNotNull( 'deleted_at' ); } - } \ No newline at end of file + + /** + * Query builder scope to search on text + * + * @param Illuminate\Database\Query\Builder $query Query builder instance + * @param text $search Search term + * + * @return Illuminate\Database\Query\Builder Modified query builder + */ + public function scopeTextSearch($query, $search) + { + + return $query->where(function($query) use ($search) + { + $query->where('title', 'LIKE', '%'.$search.'%') + ->orWhere('notes', 'LIKE', '%'.$search.'%') + ->orWhere('asset_maintenance_type', 'LIKE', '%'.$search.'%') + ->orWhere('cost', 'LIKE', '%'.$search.'%') + ->orWhere('start_date', 'LIKE', '%'.$search.'%') + ->orWhere('completion_date', 'LIKE', '%'.$search.'%'); + }); + } + } diff --git a/app/views/backend/asset_maintenances/index.blade.php b/app/views/backend/asset_maintenances/index.blade.php index f3bbe4c6f4..57601f1491 100644 --- a/app/views/backend/asset_maintenances/index.blade.php +++ b/app/views/backend/asset_maintenances/index.blade.php @@ -20,49 +20,70 @@ </div> <div class="row form-wrapper"> - {{ Datatable::table() - ->addColumn(Lang::get('admin/asset_maintenances/table.asset_name'), - Lang::get('admin/asset_maintenances/table.supplier_name'), - Lang::get('admin/asset_maintenances/form.asset_maintenance_type'), - Lang::get('admin/asset_maintenances/form.title'), - Lang::get('admin/asset_maintenances/form.start_date'), - Lang::get('admin/asset_maintenances/form.completion_date'), - Lang::get('admin/asset_maintenances/form.asset_maintenance_time'), - Lang::get('admin/asset_maintenances/form.cost'), - Lang::get('table.actions')) - ->setOptions( - [ - 'language' => [ - 'search' => Lang::get('general.search'), - 'lengthMenu' => Lang::get('general.page_menu'), - 'loadingRecords' => Lang::get('general.loading'), - 'zeroRecords' => Lang::get('general.no_results'), - 'info' => Lang::get('general.pagination_info'), - 'processing' => Lang::get('general.processing'), - 'paginate'=> [ - 'first'=>Lang::get('general.first'), - 'previous'=>Lang::get('general.previous'), - 'next'=>Lang::get('general.next'), - 'last'=>Lang::get('general.last'), - ], - ], - 'sAjaxSource'=>route('api.asset_maintenances.list'), - 'dom' =>'CT<"clear">lfrtip', - 'colVis'=> ['showAll'=>'Show All','restore'=>'Restore','activate'=>'mouseover'], - 'columnDefs'=> [ - ['bSortable'=>false,'targets'=>[8]], - ['width'=>'12%','targets'=>[8]], - ], - 'order'=>[[0,'asc']], - ] - ) - ->render() }} + <table + name="maintenances" + id="table" + data-url="{{route('api.asset_maintenances.list')}}" + data-cookie="true" + data-click-to-select="true" + data-cookie-id-table="maintenancesTable"> + <thead> + <tr> + <th data-sortable="true" data-field="id" data-visible="false">@lang('general.id')</th> + <th data-sortable="false" data-field="asset_name">@lang('admin/asset_maintenances/table.asset_name')</th> + <th data-sortable="false" data-field="supplier">@lang('admin/asset_maintenances/table.supplier_name')</th> + <th data-searchable="true" data-sortable="true" data-field="asset_maintenance_type">@lang('admin/asset_maintenances/form.asset_maintenance_type')</th> + <th data-searchable="true" data-sortable="true" data-field="title">@lang('admin/asset_maintenances/form.title')</th> + <th data-searchable="true" data-sortable="false" data-field="start_date">@lang('admin/asset_maintenances/form.start_date')</th> + <th data-searchable="true" data-sortable="true" data-field="completion_date">@lang('admin/asset_maintenances/form.completion_date')</th> + <th data-searchable="true" data-sortable="true" data-field="asset_maintenance_time">@lang('admin/asset_maintenances/form.asset_maintenance_time')</th> + <th data-searchable="true" data-sortable="true" data-field="cost" class="text-right">@lang('admin/asset_maintenances/form.cost')</th> + <th data-searchable="true" data-sortable="true" data-field="notes" data-visible="false">@lang('admin/asset_maintenances/form.notes')</th> + <th data-switchable="false" data-searchable="false" data-sortable="false" data-field="actions">{{ Lang::get('table.actions') }}</th> + </tr> + </thead> + </table> </div> @section('moar_scripts') -<script src="https://demo.snipeitapp.com/assets/js/jquery.dataTables.min.js"></script> -<script src="https://demo.snipeitapp.com/assets/js/dataTables.colVis.js"></script> -<script src="https://demo.snipeitapp.com/assets/js/dataTables.tableTools.js"></script> +<script src="{{ asset('assets/js/bootstrap-table.js') }}"></script> +<script src="{{ asset('assets/js/extensions/cookie/bootstrap-table-cookie.js') }}"></script> +<script src="{{ asset('assets/js/extensions/mobile/bootstrap-table-mobile.js') }}"></script> +<script src="{{ asset('assets/js/extensions/export/bootstrap-table-export.js') }}"></script> +<script src="{{ asset('assets/js/extensions/export/tableExport.js') }}"></script> +<script src="{{ asset('assets/js/extensions/export/jquery.base64.js') }}"></script> +<script type="text/javascript"> + $('#table').bootstrapTable({ + classes: 'table table-responsive table-no-bordered', + undefinedText: '', + iconsPrefix: 'fa', + showRefresh: true, + search: true, + pageSize: {{{ Setting::getSettings()->per_page }}}, + pagination: true, + sidePagination: 'server', + sortable: true, + cookie: true, + mobileResponsive: true, + showExport: true, + showColumns: true, + exportDataType: 'all', + exportTypes: ['csv', 'txt','json', 'xml'], + maintainSelected: true, + paginationFirstText: "@lang('general.first')", + paginationLastText: "@lang('general.last')", + paginationPreText: "@lang('general.previous')", + paginationNextText: "@lang('general.next')", + pageList: ['10','25','50','100','150','200'], + icons: { + paginationSwitchDown: 'fa-caret-square-o-down', + paginationSwitchUp: 'fa-caret-square-o-up', + columns: 'fa-columns', + refresh: 'fa-refresh' + }, + + }); +</script> +@stop @stop -@stop diff --git a/app/views/backend/categories/index.blade.php b/app/views/backend/categories/index.blade.php index 56716b5852..0362ee9f9a 100755 --- a/app/views/backend/categories/index.blade.php +++ b/app/views/backend/categories/index.blade.php @@ -19,7 +19,7 @@ <div class="user-profile"> <div class="row profile"> <div class="col-md-9 bio"> - <table + <table name="categories" id="table" data-url="{{route('api.categories.list')}}" From 059993b064fb05e81c0711c19b147ee274bf45a4 Mon Sep 17 00:00:00 2001 From: snipe <snipe@snipe.net> Date: Wed, 21 Oct 2015 22:41:50 -0700 Subject: [PATCH 104/120] Make groups table responsive --- app/config/version.php | 4 ++-- app/views/backend/groups/index.blade.php | 11 ++++++----- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/app/config/version.php b/app/config/version.php index 26f1c46129..7132384593 100644 --- a/app/config/version.php +++ b/app/config/version.php @@ -1,5 +1,5 @@ <?php return array ( - 'app_version' => 'v2.0-282', - 'hash_version' => 'v2.0-282-g7087e86', + 'app_version' => 'v2.0-283', + 'hash_version' => 'v2.0-283-g28fcd2b', ); \ No newline at end of file diff --git a/app/views/backend/groups/index.blade.php b/app/views/backend/groups/index.blade.php index c55f4a6d68..89acb7767e 100755 --- a/app/views/backend/groups/index.blade.php +++ b/app/views/backend/groups/index.blade.php @@ -20,13 +20,14 @@ <div class="row form-wrapper"> -<table id="example"> +<div class="table-responsive"> +<table class="table table-hover"> <thead> <tr role="row"> <th class="col-md-3">@lang('admin/groups/table.name')</th> - <th class="col-md-2">@lang('admin/groups/table.users')</th> - <th class="col-md-2">@lang('general.created_at')</th> - <th class="col-md-1 actions">@lang('table.actions')</th> + <th class="col-md-2"><span class="line"></span>@lang('admin/groups/table.users')</th> + <th class="col-md-2"><span class="line"></span>@lang('general.created_at')</th> + <th class="col-md-1 actions"><span class="line"></span>@lang('table.actions')</th> </tr> </thead> <tbody> @@ -52,6 +53,6 @@ data-title="@lang('general.delete')" </tbody> </table> </div> - +</div> @stop From dba79831891a0ce8c309dea4926081ccc2daf75e Mon Sep 17 00:00:00 2001 From: snipe <snipe@snipe.net> Date: Wed, 21 Oct 2015 23:07:23 -0700 Subject: [PATCH 105/120] Added new fields to index view --- app/config/version.php | 4 ++-- app/controllers/admin/AccessoriesController.php | 7 +++++-- app/views/backend/accessories/index.blade.php | 9 ++++++--- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/app/config/version.php b/app/config/version.php index 7132384593..76fb97a8a4 100644 --- a/app/config/version.php +++ b/app/config/version.php @@ -1,5 +1,5 @@ <?php return array ( - 'app_version' => 'v2.0-283', - 'hash_version' => 'v2.0-283-g28fcd2b', + 'app_version' => 'v2.0-206', + 'hash_version' => 'v2.0-206-g69c95f1', ); \ No newline at end of file diff --git a/app/controllers/admin/AccessoriesController.php b/app/controllers/admin/AccessoriesController.php index d7f9265e6c..2d6d25b05c 100755 --- a/app/controllers/admin/AccessoriesController.php +++ b/app/controllers/admin/AccessoriesController.php @@ -493,7 +493,7 @@ class AccessoriesController extends AdminController public function getDatatable() { - $accessories = Accessory::select(array('id','name','qty','category_id'))->with('category') + $accessories = Accessory::with('category') ->whereNull('deleted_at'); if (Input::has('search')) { @@ -513,7 +513,7 @@ class AccessoriesController extends AdminController } - $allowed_columns = ['name']; + $allowed_columns = ['name','order_number','purchase_date','purchase_cost']; $order = Input::get('order') === 'asc' ? 'asc' : 'desc'; $sort = in_array(Input::get('sort'), $allowed_columns) ? Input::get('sort') : 'created_at'; @@ -531,6 +531,9 @@ class AccessoriesController extends AdminController 'name' => link_to('admin/accessories/'.$accessory->id.'/view', $accessory->name), 'category' => $accessory->category->name, 'qty' => $accessory->qty, + 'order_number' => $accessory->order_number, + 'purchase_date' => $accessory->purchase_date, + 'purchase_cost' => $accessory->purchase_cost, 'numRemaining' => $accessory->numRemaining(), 'actions' => $actions ); diff --git a/app/views/backend/accessories/index.blade.php b/app/views/backend/accessories/index.blade.php index 4c71781633..7837d93aee 100755 --- a/app/views/backend/accessories/index.blade.php +++ b/app/views/backend/accessories/index.blade.php @@ -29,9 +29,12 @@ <thead> <tr> <th data-sortable="true" data-field="name">{{Lang::get('admin/accessories/table.title')}}</th> - <th data-switchable="false" data-searchable="false" data-sortable="false" data-field="category">{{Lang::get('admin/accessories/general.accessory_category')}}</th> - <th data-switchable="false" data-searchable="false" data-sortable="false" data-field="qty">{{Lang::get('admin/accessories/general.total')}}</th> - <th data-switchable="false" data-searchable="false" data-sortable="false" data-field="numRemaining">{{Lang::get('admin/accessories/general.remaining')}}</th> + <th data-searchable="false" data-sortable="false" data-field="category">{{Lang::get('admin/accessories/general.accessory_category')}}</th> + <th data-searchable="false" data-sortable="false" data-field="qty">{{Lang::get('admin/accessories/general.total')}}</th> + <th data-searchable="true" data-sortable="true" data-field="purchase_date">{{Lang::get('admin/accessories/general.date')}}</th> + <th data-searchable="true" data-sortable="true" data-field="purchase_cost">{{Lang::get('admin/accessories/general.cost')}}</th> + <th data-searchable="true" data-sortable="true" data-field="order_number">{{Lang::get('admin/accessories/general.order')}}</th> + <th data-searchable="false" data-sortable="false" data-field="numRemaining">{{Lang::get('admin/accessories/general.remaining')}}</th> <th data-switchable="false" data-searchable="false" data-sortable="false" data-field="actions">{{Lang::get('table.actions')}}</th> </tr> </thead> From 440bc1a4b446695dc8613a2f31f024b15fbdfebb Mon Sep 17 00:00:00 2001 From: snipe <snipe@snipe.net> Date: Wed, 21 Oct 2015 23:15:35 -0700 Subject: [PATCH 106/120] Fixes bug in people display --- app/controllers/admin/UsersController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/admin/UsersController.php b/app/controllers/admin/UsersController.php index 2b0668e77b..a509cf35f1 100755 --- a/app/controllers/admin/UsersController.php +++ b/app/controllers/admin/UsersController.php @@ -909,7 +909,7 @@ class UsersController extends AdminController { .'<a href="mailto:'.$user->email.'" class="hidden-xs hidden-sm"><i class="fa fa-envelope"></i></a>' .'</span>' : '', 'username' => $user->username, - 'location' => ($user->location_id!='') ? $user->userloc->name : '', + 'location' => ($user->userloc) ? $user->userloc->name : '', 'manager' => ($user->manager) ? '<a title="' . $user->manager->fullName() . '" href="users/' . $user->manager->id . '/view">' . $user->manager->fullName() . '</a>' : '', 'assets' => $user->assets->count(), 'licenses' => $user->licenses->count(), From bd418d142261c2bea551966e7da04ba179cf5b7e Mon Sep 17 00:00:00 2001 From: snipe <snipe@snipe.net> Date: Wed, 21 Oct 2015 23:17:22 -0700 Subject: [PATCH 107/120] Eager load some models --- app/config/version.php | 4 ++-- app/controllers/admin/AssetsController.php | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/config/version.php b/app/config/version.php index 76fb97a8a4..c0fcad7579 100644 --- a/app/config/version.php +++ b/app/config/version.php @@ -1,5 +1,5 @@ <?php return array ( - 'app_version' => 'v2.0-206', - 'hash_version' => 'v2.0-206-g69c95f1', + 'app_version' => 'v2.0-314', + 'hash_version' => 'v2.0-314-gdba7983', ); \ No newline at end of file diff --git a/app/controllers/admin/AssetsController.php b/app/controllers/admin/AssetsController.php index bf4a76160b..dfab338750 100755 --- a/app/controllers/admin/AssetsController.php +++ b/app/controllers/admin/AssetsController.php @@ -1095,7 +1095,7 @@ class AssetsController extends AdminController $limit = 50; } - $assets = Asset::with('model','assigneduser','assigneduser.userloc','assetstatus','defaultLoc','assetlog','model','model.category')->Hardware()->select(array('assets.id', 'assets.name','assets.model_id','assets.assigned_to','assets.asset_tag','assets.serial','assets.status_id','assets.purchase_date','assets.deleted_at','assets.rtd_location_id','assets.notes','assets.order_number')); + $assets = Asset::with('model','assigneduser','assigneduser.userloc','assetstatus','defaultLoc','assetlog','model','model.category','assetstatus')->Hardware()->select(array('assets.id', 'assets.name','assets.model_id','assets.assigned_to','assets.asset_tag','assets.serial','assets.status_id','assets.purchase_date','assets.deleted_at','assets.rtd_location_id','assets.notes','assets.order_number')); switch ($status) { From 2e044bf0a3031c8620280654bc88f67cffb12461 Mon Sep 17 00:00:00 2001 From: snipe <snipe@snipe.net> Date: Wed, 21 Oct 2015 23:18:40 -0700 Subject: [PATCH 108/120] Fixed category bug --- app/config/version.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/config/version.php b/app/config/version.php index c0fcad7579..757e19b234 100644 --- a/app/config/version.php +++ b/app/config/version.php @@ -1,5 +1,5 @@ <?php return array ( - 'app_version' => 'v2.0-314', - 'hash_version' => 'v2.0-314-gdba7983', + 'app_version' => 'v2.0-315', + 'hash_version' => 'v2.0-315-g440bc1a', ); \ No newline at end of file From b1d5812ae275095f8d50057e61276025aa529b0a Mon Sep 17 00:00:00 2001 From: snipe <snipe@snipe.net> Date: Wed, 21 Oct 2015 23:19:27 -0700 Subject: [PATCH 109/120] Fixed categorys page --- app/config/version.php | 4 ++-- app/views/backend/categories/index.blade.php | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/app/config/version.php b/app/config/version.php index 757e19b234..1fb756b852 100644 --- a/app/config/version.php +++ b/app/config/version.php @@ -1,5 +1,5 @@ <?php return array ( - 'app_version' => 'v2.0-315', - 'hash_version' => 'v2.0-315-g440bc1a', + 'app_version' => 'v2.0-316', + 'hash_version' => 'v2.0-316-gbd418d1', ); \ No newline at end of file diff --git a/app/views/backend/categories/index.blade.php b/app/views/backend/categories/index.blade.php index 004957ee31..cf9abf2d40 100755 --- a/app/views/backend/categories/index.blade.php +++ b/app/views/backend/categories/index.blade.php @@ -90,3 +90,4 @@ }); </script> @stop +@stop From f06af973642d9cac353f02a0dc8adae18d5076f1 Mon Sep 17 00:00:00 2001 From: snipe <snipe@snipe.net> Date: Wed, 21 Oct 2015 23:23:22 -0700 Subject: [PATCH 110/120] Account for no limit or offset passed --- app/config/version.php | 4 +-- .../admin/CategoriesController.php | 21 +++++++++++++-- .../admin/ConsumablesController.php | 26 ++++++++++++++----- 3 files changed, 40 insertions(+), 11 deletions(-) diff --git a/app/config/version.php b/app/config/version.php index 1fb756b852..9606d9ca1b 100644 --- a/app/config/version.php +++ b/app/config/version.php @@ -1,5 +1,5 @@ <?php return array ( - 'app_version' => 'v2.0-316', - 'hash_version' => 'v2.0-316-gbd418d1', + 'app_version' => 'v2.0-317', + 'hash_version' => 'v2.0-317-g2e044bf', ); \ No newline at end of file diff --git a/app/controllers/admin/CategoriesController.php b/app/controllers/admin/CategoriesController.php index 0b97d4cb89..b1e051b872 100755 --- a/app/controllers/admin/CategoriesController.php +++ b/app/controllers/admin/CategoriesController.php @@ -218,7 +218,24 @@ class CategoriesController extends AdminController public function getDatatable() { // Grab all the categories - $categories = Category::orderBy('created_at', 'DESC')->get(); + $categories = Category::orderBy('created_at', 'DESC'); + + if (Input::has('search')) { + $categories = $categories->TextSearch(e(Input::get('search'))); + } + + if (Input::has('offset')) { + $offset = e(Input::get('offset')); + } else { + $offset = 0; + } + + if (Input::has('limit')) { + $limit = e(Input::get('limit')); + } else { + $limit = 50; + } + $actions = new \Chumper\Datatable\Columns\FunctionColumn('actions', function($categories) { return '<a href="'.route('update/category', $categories->id).'" class="btn btn-warning btn-sm" style="margin-right:5px;"><i class="fa fa-pencil icon-white"></i></a><a data-html="false" class="btn delete-asset btn-danger btn-sm" data-toggle="modal" href="'.route('delete/category', $categories->id).'" data-content="'.Lang::get('admin/categories/message.delete.confirm').'" data-title="'.Lang::get('general.delete').' '.htmlspecialchars($categories->name).'?" onClick="return false;"><i class="fa fa-trash icon-white"></i></a>'; @@ -231,7 +248,7 @@ class CategoriesController extends AdminController $categories = $categories->orderBy($sort, $order); $catCount = $categories->count(); - $categories = $categories->skip(Input::get('offset'))->take(Input::get('limit'))->get(); + $categories = $categories->skip($offset)->take($limit)->get(); $rows = array(); diff --git a/app/controllers/admin/ConsumablesController.php b/app/controllers/admin/ConsumablesController.php index 8da78e8340..173cbfd173 100644 --- a/app/controllers/admin/ConsumablesController.php +++ b/app/controllers/admin/ConsumablesController.php @@ -69,19 +69,19 @@ class ConsumablesController extends AdminController $consumable->name = e(Input::get('name')); $consumable->category_id = e(Input::get('category_id')); $consumable->order_number = e(Input::get('order_number')); - + if (e(Input::get('purchase_date')) == '') { $consumable->purchase_date = NULL; } else { $consumable->purchase_date = e(Input::get('purchase_date')); } - + if (e(Input::get('purchase_cost')) == '0.00') { $consumable->purchase_cost = NULL; } else { $consumable->purchase_cost = ParseFloat(e(Input::get('purchase_cost'))); } - + $consumable->qty = e(Input::get('qty')); $consumable->user_id = Sentry::getId(); @@ -151,19 +151,19 @@ class ConsumablesController extends AdminController $consumable->name = e(Input::get('name')); $consumable->category_id = e(Input::get('category_id')); $consumable->order_number = e(Input::get('order_number')); - + if (e(Input::get('purchase_date')) == '') { $consumable->purchase_date = NULL; } else { $consumable->purchase_date = e(Input::get('purchase_date')); } - + if (e(Input::get('purchase_cost')) == '0.00') { $consumable->purchase_cost = NULL; } else { $consumable->purchase_cost = ParseFloat(e(Input::get('purchase_cost'))); } - + $consumable->qty = e(Input::get('qty')); // Was the consumable created? @@ -372,6 +372,18 @@ class ConsumablesController extends AdminController $consumables = $consumables->TextSearch(Input::get('search')); } + if (Input::has('offset')) { + $offset = e(Input::get('offset')); + } else { + $offset = 0; + } + + if (Input::has('limit')) { + $limit = e(Input::get('limit')); + } else { + $limit = 50; + } + $allowed_columns = ['id','name']; $order = Input::get('order') === 'asc' ? 'asc' : 'desc'; $sort = in_array(Input::get('sort'), $allowed_columns) ? Input::get('sort') : 'created_at'; @@ -379,7 +391,7 @@ class ConsumablesController extends AdminController $consumables->orderBy($sort, $order); $consumCount = $consumables->count(); - $consumables = $consumables->skip(Input::get('offset'))->take(Input::get('limit'))->get(); + $consumables = $consumables->skip($offset)->take($limit)->get(); $rows = array(); From eb5649d0b37c8ff0c1f380b02df38926d7306979 Mon Sep 17 00:00:00 2001 From: snipe <snipe@snipe.net> Date: Wed, 21 Oct 2015 23:25:23 -0700 Subject: [PATCH 111/120] Eager load assets --- app/config/version.php | 4 ++-- app/controllers/admin/CategoriesController.php | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/config/version.php b/app/config/version.php index 9606d9ca1b..50d302e07a 100644 --- a/app/config/version.php +++ b/app/config/version.php @@ -1,5 +1,5 @@ <?php return array ( - 'app_version' => 'v2.0-317', - 'hash_version' => 'v2.0-317-g2e044bf', + 'app_version' => 'v2.0-318', + 'hash_version' => 'v2.0-318-gb1d5812', ); \ No newline at end of file diff --git a/app/controllers/admin/CategoriesController.php b/app/controllers/admin/CategoriesController.php index b1e051b872..df381bb907 100755 --- a/app/controllers/admin/CategoriesController.php +++ b/app/controllers/admin/CategoriesController.php @@ -218,7 +218,7 @@ class CategoriesController extends AdminController public function getDatatable() { // Grab all the categories - $categories = Category::orderBy('created_at', 'DESC'); + $categories = Category::with('assets'); if (Input::has('search')) { $categories = $categories->TextSearch(e(Input::get('search'))); From c91113ac95767f17b8ce475d19447d3fda683dc0 Mon Sep 17 00:00:00 2001 From: snipe <snipe@snipe.net> Date: Wed, 21 Oct 2015 23:25:33 -0700 Subject: [PATCH 112/120] Eager load accessories --- app/config/version.php | 4 ++-- app/controllers/admin/CategoriesController.php | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/config/version.php b/app/config/version.php index 50d302e07a..ee1bdeaec0 100644 --- a/app/config/version.php +++ b/app/config/version.php @@ -1,5 +1,5 @@ <?php return array ( - 'app_version' => 'v2.0-318', - 'hash_version' => 'v2.0-318-gb1d5812', + 'app_version' => 'v2.0-319', + 'hash_version' => 'v2.0-319-gf06af97', ); \ No newline at end of file diff --git a/app/controllers/admin/CategoriesController.php b/app/controllers/admin/CategoriesController.php index df381bb907..ded6aa1e88 100755 --- a/app/controllers/admin/CategoriesController.php +++ b/app/controllers/admin/CategoriesController.php @@ -218,7 +218,7 @@ class CategoriesController extends AdminController public function getDatatable() { // Grab all the categories - $categories = Category::with('assets'); + $categories = Category::with('assets', 'accessories'); if (Input::has('search')) { $categories = $categories->TextSearch(e(Input::get('search'))); From 4cb19d1aaeafc7d9f102415f0298378738bf0558 Mon Sep 17 00:00:00 2001 From: snipe <snipe@snipe.net> Date: Wed, 21 Oct 2015 23:31:28 -0700 Subject: [PATCH 113/120] More eager loading, pass $statuslabel_types to view --- app/controllers/admin/AssetsController.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/controllers/admin/AssetsController.php b/app/controllers/admin/AssetsController.php index dfab338750..b8640528d6 100755 --- a/app/controllers/admin/AssetsController.php +++ b/app/controllers/admin/AssetsController.php @@ -238,6 +238,7 @@ class AssetsController extends AdminController $view = $view->with('supplier_list',$supplier_list); $view = $view->with('location_list',$location_list); $view = $view->with('statuslabel_list',$statuslabel_list); + $view = $view->with('statuslabel_types',$statuslabel_types); $view = $view->with('manufacturer',$manufacturer_list); $view = $view->with('category',$category_list); $view = $view->with('assigned_to',$assigned_to); @@ -1095,7 +1096,7 @@ class AssetsController extends AdminController $limit = 50; } - $assets = Asset::with('model','assigneduser','assigneduser.userloc','assetstatus','defaultLoc','assetlog','model','model.category','assetstatus')->Hardware()->select(array('assets.id', 'assets.name','assets.model_id','assets.assigned_to','assets.asset_tag','assets.serial','assets.status_id','assets.purchase_date','assets.deleted_at','assets.rtd_location_id','assets.notes','assets.order_number')); + $assets = Asset::with('model','assigneduser','assigneduser.userloc','assetstatus','defaultLoc','assetlog','model','model.category','assetstatus','assetloc')->Hardware()->select(array('assets.id', 'assets.name','assets.model_id','assets.assigned_to','assets.asset_tag','assets.serial','assets.status_id','assets.purchase_date','assets.deleted_at','assets.rtd_location_id','assets.notes','assets.order_number')); switch ($status) { From 27799dc78ae3615822bb67bebf636488e4a03b9e Mon Sep 17 00:00:00 2001 From: snipe <snipe@snipe.net> Date: Wed, 21 Oct 2015 23:39:45 -0700 Subject: [PATCH 114/120] Nicer activity report display (This needs the API/Bootstrap tables treatment soon) --- app/config/version.php | 4 ++-- app/views/backend/reports/activity.blade.php | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/app/config/version.php b/app/config/version.php index ee1bdeaec0..ea32829a51 100644 --- a/app/config/version.php +++ b/app/config/version.php @@ -1,5 +1,5 @@ <?php return array ( - 'app_version' => 'v2.0-319', - 'hash_version' => 'v2.0-319-gf06af97', + 'app_version' => 'v2.0-321', + 'hash_version' => 'v2.0-321-gc91113a', ); \ No newline at end of file diff --git a/app/views/backend/reports/activity.blade.php b/app/views/backend/reports/activity.blade.php index f3a39fa6a4..77edc00868 100644 --- a/app/views/backend/reports/activity.blade.php +++ b/app/views/backend/reports/activity.blade.php @@ -19,15 +19,15 @@ <div class="row"> <div class="table-responsive"> -<table id="example"> +<table class="table table-hover"> <thead> <tr role="row"> <th class="col-sm-1">@lang('general.admin')</th> - <th class="col-sm-1">@lang('general.action')</th> - <th class="col-sm-1">@lang('general.type')</th> - <th class="col-sm-1">@lang('general.item')</th> - <th class="col-sm-1"></th> - <th class="col-sm-1">@lang('general.date')</th + <th class="col-sm-1"><span class="line"></span>@lang('general.action')</th> + <th class="col-sm-1"><span class="line"></span>@lang('general.type')</th> + <th class="col-sm-1"><span class="line"></span>@lang('general.item')</th> + <th class="col-sm-1"><span class="line"></span>@lang('general.user')</th> + <th class="col-sm-1"><span class="line"></span>@lang('general.date')</th </tr> </thead> <tbody> From 79a69d7633298c49bb8ec1ff4bfce5f7563c891d Mon Sep 17 00:00:00 2001 From: madd15 <joshdeakin@adam.com.au> Date: Thu, 22 Oct 2015 17:10:02 +1030 Subject: [PATCH 115/120] return getEdit to correct method --- app/controllers/admin/AssetsController.php | 38 ++++++---------------- 1 file changed, 10 insertions(+), 28 deletions(-) diff --git a/app/controllers/admin/AssetsController.php b/app/controllers/admin/AssetsController.php index b8640528d6..e88d702846 100755 --- a/app/controllers/admin/AssetsController.php +++ b/app/controllers/admin/AssetsController.php @@ -207,7 +207,6 @@ class AssetsController extends AdminController // Redirect to the asset management page return Redirect::to('hardware')->with('error', Lang::get('admin/hardware/message.does_not_exist')); } - // Grab the dropdown lists $model_list = modelList(); $statuslabel_list = statusLabelList(); @@ -217,33 +216,16 @@ class AssetsController extends AdminController $supplier_list = suppliersList(); $assigned_to = usersList(); $statuslabel_types = statusTypeList(); - - // Grab the dropdown list of models - $model_list = array('' => Lang::get('general.select_model')) + DB::table('models') - ->select(DB::raw('concat(name," / ",modelno) as name, id'))->orderBy('name', 'asc') - ->orderBy('modelno', 'asc') - ->lists('name', 'id'); - $supplier_list = array('' => Lang::get('general.select_supplier')) + Supplier::orderBy('name', 'asc')->lists('name', 'id'); - $location_list = array('' => Lang::get('general.select_location')) + Location::orderBy('name', 'asc')->lists('name', 'id'); - $assigned_to = array('' => Lang::get('general.select_user')) + DB::table('users')->select(DB::raw('concat(first_name," ",last_name) as full_name, id'))->whereNull('deleted_at')->lists('full_name', 'id'); - // grap dropdown lists for embedded create drop-downs - $manufacturer_list = array('' => 'Select One') + Manufacturer::lists('name', 'id'); - $category_list = array('' => '') + DB::table('categories')->whereNull('deleted_at')->lists('name', 'id'); - - // Grab the dropdown list of status - $statuslabel_list = Statuslabel::orderBy('name', 'asc')->lists('name', 'id'); - - $view = View::make('backend/hardware/edit', compact('asset')); - $view = $view->with('model_list',$model_list); - $view = $view->with('supplier_list',$supplier_list); - $view = $view->with('location_list',$location_list); - $view = $view->with('statuslabel_list',$statuslabel_list); - $view = $view->with('statuslabel_types',$statuslabel_types); - $view = $view->with('manufacturer',$manufacturer_list); - $view = $view->with('category',$category_list); - $view = $view->with('assigned_to',$assigned_to); - - return $view; + + return View::make('backend/hardware/edit', compact('asset')) + ->with('model_list',$model_list) + ->with('supplier_list',$supplier_list) + ->with('location_list',$location_list) + ->with('statuslabel_list',$statuslabel_list) + ->with('assigned_to',$assigned_to) + ->with('manufacturer',$manufacturer_list) + ->with('statuslabel_types',$statuslabel_types) + ->with('category',$category_list); } From 1bdd5886e658c9f56cb3987046932879ea02e152 Mon Sep 17 00:00:00 2001 From: snipe <snipe@snipe.net> Date: Wed, 21 Oct 2015 23:58:07 -0700 Subject: [PATCH 116/120] Select * because reasons --- app/controllers/admin/AssetsController.php | 41 +++++++++++----------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/app/controllers/admin/AssetsController.php b/app/controllers/admin/AssetsController.php index e88d702846..224aec8d4f 100755 --- a/app/controllers/admin/AssetsController.php +++ b/app/controllers/admin/AssetsController.php @@ -216,7 +216,7 @@ class AssetsController extends AdminController $supplier_list = suppliersList(); $assigned_to = usersList(); $statuslabel_types = statusTypeList(); - + return View::make('backend/hardware/edit', compact('asset')) ->with('model_list',$model_list) ->with('supplier_list',$supplier_list) @@ -1066,20 +1066,29 @@ class AssetsController extends AdminController public function getDatatable($status = null) { - if (Input::has('offset')) { - $offset = e(Input::get('offset')); - } else { - $offset = 0; - } - if (Input::has('limit')) { - $limit = e(Input::get('limit')); - } else { - $limit = 50; - } + $assets = Asset::with('model','assigneduser','assigneduser.userloc','assetstatus','defaultLoc','assetlog','model','model.category','assetstatus','assetloc') + ->Hardware(); - $assets = Asset::with('model','assigneduser','assigneduser.userloc','assetstatus','defaultLoc','assetlog','model','model.category','assetstatus','assetloc')->Hardware()->select(array('assets.id', 'assets.name','assets.model_id','assets.assigned_to','assets.asset_tag','assets.serial','assets.status_id','assets.purchase_date','assets.deleted_at','assets.rtd_location_id','assets.notes','assets.order_number')); + if (Input::has('search')) { + $assets = $assets->TextSearch(Input::get('search')); + } + if (Input::has('offset')) { + $offset = e(Input::get('offset')); + } else { + $offset = 0; + } + + if (Input::has('limit')) { + $limit = e(Input::get('limit')); + } else { + $limit = 50; + } + + if (Input::has('order_number')) { + $assets->where('order_number','=',e(Input::get('order_number'))); + } switch ($status) { case 'Deleted': @@ -1106,14 +1115,6 @@ class AssetsController extends AdminController } - if (Input::has('order_number')) { - $assets->where('order_number','=',e(Input::get('order_number'))); - } - - if (Input::has('search')) { - $assets = $assets->TextSearch(Input::get('search')); - } - $allowed_columns = ['id','name','asset_tag','serial','model','checkout_date','category','notes']; $order = Input::get('order') === 'asc' ? 'asc' : 'desc'; $sort = in_array(Input::get('sort'), $allowed_columns) ? Input::get('sort') : 'asset_tag'; From 8ea40d4e6d8e440158d3271f859dac167182b4c9 Mon Sep 17 00:00:00 2001 From: snipe <snipe@snipe.net> Date: Thu, 22 Oct 2015 00:17:45 -0700 Subject: [PATCH 117/120] Fixes default value for strict mode --- ..._10_22_003314_fix_defaults_accessories.php | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 app/database/migrations/2015_10_22_003314_fix_defaults_accessories.php diff --git a/app/database/migrations/2015_10_22_003314_fix_defaults_accessories.php b/app/database/migrations/2015_10_22_003314_fix_defaults_accessories.php new file mode 100644 index 0000000000..34059de1ee --- /dev/null +++ b/app/database/migrations/2015_10_22_003314_fix_defaults_accessories.php @@ -0,0 +1,32 @@ +<?php + +use Illuminate\Database\Schema\Blueprint; +use Illuminate\Database\Migrations\Migration; + +class FixDefaultsAccessories extends Migration { + + /** + * Run the migrations. + * + * @return void + */ + public function up() + { + DB::statement('ALTER TABLE `'.DB::getTablePrefix().'accessories` MODIFY `order_number` varchar(255) DEFAULT NULL;'); + + DB::statement('ALTER TABLE `'.DB::getTablePrefix().'consumables` MODIFY `order_number` varchar(255) DEFAULT NULL;'); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + // + DB::statement('ALTER TABLE `'.DB::getTablePrefix().'accessories` MODIFY `order_number` varchar(255);'); + DB::statement('ALTER TABLE `'.DB::getTablePrefix().'consumables` MODIFY `order_number` varchar(255);'); + } + +} From 7901b49503079923604e9b09a9a8c333a5be7e26 Mon Sep 17 00:00:00 2001 From: snipe <snipe@snipe.net> Date: Thu, 22 Oct 2015 00:18:44 -0700 Subject: [PATCH 118/120] Updated sample file --- app/config/version.php | 4 ++-- app/private_uploads/imports/assets/sample.csv | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/config/version.php b/app/config/version.php index ea32829a51..f5eb33330b 100644 --- a/app/config/version.php +++ b/app/config/version.php @@ -1,5 +1,5 @@ <?php return array ( - 'app_version' => 'v2.0-321', - 'hash_version' => 'v2.0-321-gc91113a', + 'app_version' => 'v2.0-326', + 'hash_version' => 'v2.0-326-g1bdd588', ); \ No newline at end of file diff --git a/app/private_uploads/imports/assets/sample.csv b/app/private_uploads/imports/assets/sample.csv index 3bf49568df..cb5ac9a7da 100644 --- a/app/private_uploads/imports/assets/sample.csv +++ b/app/private_uploads/imports/assets/sample.csv @@ -1 +1 @@ -Name,Email,Username,Asset Category,Asset Model,Manufacturer,Asset Model Number,Asset Serial,Asset Tag,Location Name,Asset Notes,Purchase Date,Purchase Cost William Dixon,miranda@selfware.ch,,Malesuada,Et,Nisi,5,4D47A5B7-007D-47F3-B1F2-28C33D3F2C54,58SG1MLI,"Tanzania, United Republic of",Accumsan condimentum sed purus ante mauris tincidunt aliquam libero tempor arcu posuere curabitur sodales imperdiet.,2/16/13,892.46 Debbie Mullins,jesper@madefeed.cf,,At,Platea,Torquent,9,6DEC0B69-32DB-4801-81FA-07C58E5386CC,FIM4P54T,Isle of Man,Sodales enim duis egestas turpis arcu justo aliquam ipsum erat in cursus iaculis taciti nullam.,4/12/10,961.03 Wolfgang Mitchell,kirk@tagbase.kp,,Id,Vel,Eu,5,D4017718-D68C-40EC-8669-52745A34B048,SY4NFU7S,Cook Islands,Ac platea nunc nibh in nibh eu arcu eu felis congue nibh aenean morbi quis scelerisque.,4/29/14,771.68 Anne-Marie Wallace,le@tidything.ac,,Morbi,Sociosqu,Nisl,5,56CC5079-F44B-4D62-BC45-1A4CA4FB8C9F,SK6VTSTG,Uruguay,Nostra ut mauris consectetuer donec scelerisque est per pellentesque nec id urna magna.,8/18/14,325.22 Shane Booker,alain@quitsource.pa,,Fusce,Fermentum,Sagittis,7,ED248E82-046B-4046-84DA-E4F4A0B55D0E,DBEUH6H2,Curaí_ao,Sed magna inceptos fames ultrices per ut eleifend tellus in class.,10/12/12,951.21 Olivier Walter,margaret@quitbot.tf,,Malesuada,Et,Nisi,6,FC741D83-3F19-4259-94EC-FFAB3C15C747,40SI9NUR,El Salvador,Orci tortor sed vestibulum nec imperdiet vivamus ridiculus feugiat neque ut pellentesque felis.,8/14/11,368.9 Adrian Montgomery,welch@busybeat.kp,,Malesuada,Et,Nisi,6,E8E3709B-377E-4FC7-B1B7-1DE0EE60798B,LUXLI88S,Bosnia and Herzegovina,Dapibus scelerisque tempor nisl nascetur dictum vulputate mi.,9/2/13,276.77 Joan Merrill,massey@jetwords.at,,Malesuada,Et,Nisi,6,3D862DC2-74B5-4744-8D8B-41A757927EB8,ENAZFLV3,Tonga,Malesuada felis accumsan gravida sagittis lacinia pede orci nulla magna litora augue orci.,8/31/14,123.23 Stella Gilmore,wright@quitsource.jp,,Malesuada,Et,Nisi,5,1E420152-929A-4363-8864-7DE01D38BDE0,8JS4P5P2,Uruguay,Magna in interdum consectetuer consequat tristique dapibus class nulla quis massa dictumst ipsum imperdiet.,4/22/12,333.44 Georgina Wiley,rivera@lowwerk.lv,,Urna,Et,Integer,10,6E668691-2560-4E3D-89D4-1CDB7404BB8F,J3KHF9EK,Georgia,Consequat non per viverra porta torquent in non et suspendisse bibendum scelerisque sapien mi elit nostra imperdiet.,12/16/14,588.07 Barry Hudson,jane@tagbot.tc,,Nam,Vivamus,Nibh,5,26825937-9579-4B57-9678-0659A2BB75D7,1V1WQAZA,Poland,Molestie tortor posuere duis lacus feugiat nibh mollis pellentesque nibh mollis tincidunt nisl ut inceptos ac pretium.,4/7/13,839.61 Leigh Stewart,jim.douglas@quitpower.si,,In,Mauris,Et,9,F5A3666A-951B-46FD-84AF-C0B36BE34243,8PU2UCVH,Uzbekistan,Praesent lectus amet fusce a aliquet pellentesque justo etiam vulputate nec.,3/17/14,724.88 Travis Flynn,nigel.blackburn@gigabase.md,,Nonummy,Mattis,Justo,7,008A88C0-355D-40F9-B601-7478901147E4,8O77P76Z,Hungary,Massa suscipit porta sapien purus quis metus quis vivamus curae; suspendisse ut imperdiet dapibus.,4/3/12,625.79 Edward Park,sanders@madeclicks.travel,,Nonummy,Mattis,Justo,9,228F09D4-F8A4-4453-BD7F-6FDB4FCFCE0A,FNKJCPIY,Uzbekistan,Neque eu non a felis enim turpis eget mauris lorem.,6/22/12,122.28 Stig Molina,lester@getdesk.at,,Nonummy,Mattis,Justo,9,BA720380-E958-4D09-8EF2-D5B6FDF0736C,C4DXBUKJ,Georgia,Mollis ut sapien in id pede gravida ante eu nisl aenean ullamcorper potenti nulla parturient nam quisque.,7/10/13,178.12 Bruce Watts,ali.hobbs@gigawerk.gu,,Nonummy,Mattis,Justo,7,2AF6BE26-EB5F-4745-8822-D54B3536EF9E,W9PO94OR,Finland,Ante facilisis ullamcorper eleifend enim quam justo vestibulum.,8/26/15,583.97 Lincoln Soto,michelle.daniel@presssource.sk,,Nonummy,Mattis,Justo,5,913AEF6D-547C-41DD-9128-2A6FEF5E5118,9DOEWENU,Benin,Sociis aptent ipsum leo sodales mattis leo sociosqu at amet ligula.,6/22/11,581.01 Camilla Morrison,charles@chatspace.th,,Ad,Elit,Ullamcorper,7,2ACA4B3C-A619-48AF-9530-8B581E5F9DBA,2AF7QYGX,Uzbekistan,Molestie quis placerat magna turpis iaculis eget nam massa sit congue erat hac habitant lacinia nibh.,2/28/15,492.81 Josie English,stafford@rollthing.nf,,Eu,Aliquam,Enim,7,34302A6E-CB8F-4691-9D9B-845887D0F5B2,Q7ALASVU,Botswana,Rhoncus hymenaeos sed torquent vestibulum nec mauris id nulla nibh purus purus donec vel nibh morbi.,7/15/13,441.14 Alia Salazar,johan.cook@pressbit.ai,,Ipsum,Velit,Magna,9,E429BE64-8E1B-4C8F-BB31-C4B2F2754C3C,HKZ2HG9E,New Caledonia,Sed praesent sed rutrum massa suscipit magna mauris interdum massa.,3/28/13,384.99 Beth Sweeney,coral.le@chatsource.dj,,Ipsum,Velit,Magna,8,3FC9CF5F-EBCC-4482-8F0D-7F99EE2911A4,UM5HO5SD,Vanuatu,Aliquet porttitor elit sagittis mauris nibh rutrum tristique nunc erat mauris per integer nostra imperdiet.,9/2/15,575.23 Stig Bender,lydia@rollsimple.tp,,Ipsum,Velit,Magna,9,A39EB068-99C6-4377-AB3F-CACC83E083D1,NHYLZ75J,Burundi,Lobortis morbi massa praesent eu ac ad ut nunc aliquam neque scelerisque est fermentum eget elit aenean.,11/29/09,277.87 Angelique Lindsay,villarreal@selfserv.sg,,Ipsum,Velit,Magna,6,EA864247-21AF-44C9-96CC-D6900C599740,PZ9MMXYD,Lithuania,Id eu molestie adipiscing phasellus duis imperdiet aliquam conubia ligula eget morbi.,8/14/14,552.75 Guillermo Black,raimonds@gigadesk.bd,,Id,Class,Laoreet,5,543C547F-91CD-4AFD-AFBF-2E2B68FD514D,M3VRKBBJ,Equatorial Guinea,Egestas pretium sollicitudin suspendisse erat sem massa adipiscing eu tempor libero sollicitudin a curabitur mauris.,1/1/14,582.02 Christof Castaneda,campos@fuelserv.bg,,Eget,Congue,Nisi,6,CAB3E433-8409-475C-8EA0-2801C22B2C2B,B0CGYUG7,Syrian Arab Republic,Feugiat facilisis consequat sociosqu ac consequat lacinia consectetuer tellus leo.,12/2/14,487.02 Chloe Chen,antony@busybase.eu,,Quis,Tincidunt,Aliquam,7,E3862315-B49C-4EF6-B465-A93FF320A3EC,BTEBYEBS,Greenland,Et suscipit lectus nec morbi tristique mi in nunc tincidunt.,12/26/09,366.24 Andreas McCann,bjorn@jetwerk.hn,,Non,Ultrices,Congue,10,6F3B60E9-29B0-4421-8EF1-864C8318D20A,JPV00X2A,Estonia,Quis morbi eu sit mollis ad purus consectetuer consectetuer aliquam.,7/15/15,591.28 Owen Buckley,dragan.graves@quitdesk.cg,,Aliquam,Lacinia,Phasellus,6,52D97856-9714-4A13-9C64-A7E3028F3D64,HWH8ZXSN,"Saint Helena, Ascension and Tristan Da Cunha",Aliquam semper hac sit suspendisse mollis ligula volutpat sociosqu mi conubia porta lorem velit.,4/11/13,837.92 Damian Serrano,arnold.henderson@earlybeat.cz,,Aliquam,Lacinia,Phasellus,8,0D2E368D-83D4-4FCC-B583-F4F3750E8594,ICRKS93T,Hong Kong,Aliquet ante dui nec tempus a semper nisi non porttitor nisi magna cursus tellus facilisis cras massa.,11/30/10,856.89 Vicky Petty,tobias@tagbase.hk,,Accumsan,Lacinia,Enim,9,0A3AF79E-C848-4B7D-9B3E-AAD853908643,MC7RH905,Bahrain,Metus imperdiet suspendisse velit integer consectetuer purus per quisque.,11/19/15,285.9 Reginald Wong,adrian@fuellive.hu,,Et,In,Non,5,DAC224E4-858F-4824-9AB4-B32F8CAAD4B5,VRNKD7KV,Nicaragua,Class vulputate amet semper duis taciti libero morbi etiam tortor primis.,8/15/12,287.21 Belinda Gillespie,claudio.potts@rollblog.nz,,A,Consectetuer,Hac,10,699E97C0-9631-4207-9123-51990D860E54,ABWLPV48,Albania,Hac sociosqu ad lacinia bibendum sed rutrum sodales diam nisl mauris et quisque.,2/20/11,141.62 Isidro Kelly,guillermo@madewerk.ca,,Tristique,Sit,Mollis,10,B2E06E00-E797-4082-878F-0A584B583267,ORVTFDS1,Japan,Quis leo porta dui mi mattis enim ligula lectus tincidunt scelerisque dolor a quis libero venenatis class.,4/2/15,936.24 Kris Carlson,ballard@getserv.nr,,Elit,Quam,Magna,5,3D3B156A-C8E5-4F44-8271-231E5647234A,WYPZ7TL0,Cuba,Diam eu tellus curabitur augue mollis volutpat dictumst tellus non tempor non ultrices nostra egestas.,1/8/12,945.01 Ivo May,ilia.dunlap@rollsource.af,,Gravida,Mauris,Vivamus,9,033374F0-E202-4DD4-8909-3A376E94AAE3,AIMB2QVF,Paraguay,Ornare sem purus ad sapien egestas vulputate nec.,11/16/15,735.17 Valery Bailey,jenkins@tagclicks.gt,,Magna,Ante,Erat,8,8405FCDC-423C-4780-85A2-763B76F8E3E6,MTKQNQQ1,United States,Pellentesque sit curabitur cras felis eu ipsum sapien mattis suspendisse taciti tellus bibendum nulla nec.,9/20/14,871.22 Edna Hunt,huynh@busybase.sh,,Aliquam,Lacinia,Phasellus,9,CDD32EE0-5C1B-43E0-AD2C-AC70A7E49A5F,6PLCX7HA,Israel,Magna interdum lectus lacus ac pede duis class donec auctor tristique pulvinar aliquam adipiscing.,6/22/13,579.79 Debbie Padilla,anderson@fussbit.do,,Aliquam,Lacinia,Phasellus,6,1AE18842-F09E-4080-B269-B2222E265A07,L9JOMH1V,Pitcairn,Elementum nibh arcu mauris lacus nisl magnis nibh sollicitudin ligula proin.,4/12/14,821.68 Michael Carlson,russell.blake@tagserv.tt,,Dui,Justo,Vitae,8,184393AC-818C-411F-9835-382556AF6699,A2I31GTM,Canada,Sollicitudin id massa consectetuer at mauris ipsum amet sapien.,5/23/15,654.99 Jay Marsh,jorgen@putbase.mz,,Curae,Mollis,Elit,6,869A8F25-968F-4D02-A19F-765FE6AE8C84,0Z95CGIA,"Tanzania, United Republic of",Varius lacinia in nunc sit placerat posuere inceptos nibh.,11/27/15,694.94 Lawrence Golden,clay@jetlive.ms,,Consequat,Nibh,Nisi,8,178AEFF6-3CC9-4696-A819-2EDFBEF029D4,KL16BDUD,Afghanistan,Lorem a nisi nibh est tempor a etiam gravida neque pellentesque pharetra condimentum metus suspendisse at.,1/16/13,923.12 Jean Paul Mayer,salazar@shutsphere.fo,,Sit,Aliquam,Nunc,10,6D3F66BE-5AA1-4433-B6A9-340D84EAB6A9,V44K0F6X,Chile,Duis eu aliquam massa lorem aptent ligula eleifend vivamus mollis malesuada ac fusce est massa nostra non.,3/18/12,433.79 Kieran McIntyre,daisy.dunlap@selfware.ca,,Proin,Cursus,Justo,9,745D1136-623A-4AEE-A884-4689614CD977,4Y0JJQTL,French Southern Territories,Nibh sodales nulla adipiscing congue turpis facilisis eu quis libero cursus.,1/11/15,671.09 Amy Singleton,almir.carson@putunit.gn,,Litora,Quis,Nulla,10,FA7D5D32-9815-4073-93A3-50F1E82967B5,FLS5TGG8,Trinidad and Tobago,Mus elit in posuere nibh tincidunt sociis aliquet tristique morbi at imperdiet turpis.,11/20/10,794.63 Justine Buck,sharon@tidyware.nf,,Bibendum,Nunc,Massa,10,963FF749-90F2-4801-AB9C-C3B7D8331175,HKWWK3Z6,Niue,Mauris nibh sed et suspendisse mauris ante vestibulum a ullamcorper elit quis.,5/21/15,398.93 Clifton Watkins,jane.montoya@fuelblog.my,,Id,Duis,Viverra,5,419B9D22-5C4E-47CF-B390-C42A8BC95C1C,ZF8AA2X0,"Virgin Islands, British",Suscipit nec consequat tortor a nonummy commodo lacus cras nisi.,10/9/10,772.13 Javier Goodman,debbie@rollclicks.in,,Egestas,Mauris,Accumsan,6,AADE6BB0-0BEE-42FB-B8F7-C882C42830CD,OCT4I7OC,"Bolivia, Plurinational State of",Mi est arcu aliquet feugiat mi torquent magna massa at et vel hymenaeos in accumsan.,1/12/14,238.17 Andreas Cross,sarah@mybit.edu,,Lacinia,Ullamcorper,Torquent,9,FFD22AD7-3A9C-499F-AB28-7595CD0B91FB,7OSLH34U,Mauritius,Aptent bibendum ultrices scelerisque interdum ad ut tempor rhoncus pellentesque mi vulputate velit ligula sem.,7/22/11,837.99 Michael Hudson,brett@getblog.ga,,Iaculis,Consectetuer,Duis,6,7ED1518C-FD51-4535-A0EA-61A317B329B2,BQRCDS5G,Antigua and Barbuda,Lorem egestas malesuada non tellus eu felis et id eget.,10/25/10,898.36 Travis Sullivan,ayala@earlywerk.bo,,Sapien,Et,Ipsum,8,6C770379-4788-4D52-9A22-9C13B5E382C6,00Z8ZH9Q,Montserrat,Quam condimentum imperdiet massa eu cras senectus et elit et pharetra sem donec lectus.,10/7/10,642.34 \ No newline at end of file +Name,Email,Username,Asset Name,Asset Category,Asset Model,Manufacturer,Asset Model Number,Asset Serial,Asset Tag,Location Name,Asset Notes,Purchase Date,Purchase Cost William Dixon,miranda@selfware.ch,,,Malesuada,Et,Nisi,5,4D47A5B7-007D-47F3-B1F2-28C33D3F2C54,58SG1MLI,"Tanzania, United Republic of",Accumsan condimentum sed purus ante mauris tincidunt aliquam libero tempor arcu posuere curabitur sodales imperdiet.,2/16/13,892.46 Debbie Mullins,jesper@madefeed.cf,,,At,Platea,Torquent,9,6DEC0B69-32DB-4801-81FA-07C58E5386CC,FIM4P54T,Isle of Man,Sodales enim duis egestas turpis arcu justo aliquam ipsum erat in cursus iaculis taciti nullam.,4/12/10,961.03 Wolfgang Mitchell,kirk@tagbase.kp,,,Id,Vel,Eu,5,D4017718-D68C-40EC-8669-52745A34B048,SY4NFU7S,Cook Islands,Ac platea nunc nibh in nibh eu arcu eu felis congue nibh aenean morbi quis scelerisque.,4/29/14,771.68 Anne-Marie Wallace,le@tidything.ac,,,Morbi,Sociosqu,Nisl,5,56CC5079-F44B-4D62-BC45-1A4CA4FB8C9F,SK6VTSTG,Uruguay,Nostra ut mauris consectetuer donec scelerisque est per pellentesque nec id urna magna.,8/18/14,325.22 Shane Booker,alain@quitsource.pa,,,Fusce,Fermentum,Sagittis,7,ED248E82-046B-4046-84DA-E4F4A0B55D0E,DBEUH6H2,Cura’_ao,Sed magna inceptos fames ultrices per ut eleifend tellus in class.,10/12/12,951.21 Olivier Walter,margaret@quitbot.tf,,,Malesuada,Et,Nisi,6,FC741D83-3F19-4259-94EC-FFAB3C15C747,40SI9NUR,El Salvador,Orci tortor sed vestibulum nec imperdiet vivamus ridiculus feugiat neque ut pellentesque felis.,8/14/11,368.9 Adrian Montgomery,welch@busybeat.kp,,,Malesuada,Et,Nisi,6,E8E3709B-377E-4FC7-B1B7-1DE0EE60798B,LUXLI88S,Bosnia and Herzegovina,Dapibus scelerisque tempor nisl nascetur dictum vulputate mi.,9/2/13,276.77 Joan Merrill,massey@jetwords.at,,,Malesuada,Et,Nisi,6,3D862DC2-74B5-4744-8D8B-41A757927EB8,ENAZFLV3,Tonga,Malesuada felis accumsan gravida sagittis lacinia pede orci nulla magna litora augue orci.,8/31/14,123.23 Stella Gilmore,wright@quitsource.jp,,,Malesuada,Et,Nisi,5,1E420152-929A-4363-8864-7DE01D38BDE0,8JS4P5P2,Uruguay,Magna in interdum consectetuer consequat tristique dapibus class nulla quis massa dictumst ipsum imperdiet.,4/22/12,333.44 Georgina Wiley,rivera@lowwerk.lv,,,Urna,Et,Integer,10,6E668691-2560-4E3D-89D4-1CDB7404BB8F,J3KHF9EK,Georgia,Consequat non per viverra porta torquent in non et suspendisse bibendum scelerisque sapien mi elit nostra imperdiet.,12/16/14,588.07 Barry Hudson,jane@tagbot.tc,,,Nam,Vivamus,Nibh,5,26825937-9579-4B57-9678-0659A2BB75D7,1V1WQAZA,Poland,Molestie tortor posuere duis lacus feugiat nibh mollis pellentesque nibh mollis tincidunt nisl ut inceptos ac pretium.,4/7/13,839.61 Leigh Stewart,jim.douglas@quitpower.si,,,In,Mauris,Et,9,F5A3666A-951B-46FD-84AF-C0B36BE34243,8PU2UCVH,Uzbekistan,Praesent lectus amet fusce a aliquet pellentesque justo etiam vulputate nec.,3/17/14,724.88 Travis Flynn,nigel.blackburn@gigabase.md,,,Nonummy,Mattis,Justo,7,008A88C0-355D-40F9-B601-7478901147E4,8O77P76Z,Hungary,Massa suscipit porta sapien purus quis metus quis vivamus curae; suspendisse ut imperdiet dapibus.,4/3/12,625.79 Edward Park,sanders@madeclicks.travel,,,Nonummy,Mattis,Justo,9,228F09D4-F8A4-4453-BD7F-6FDB4FCFCE0A,FNKJCPIY,Uzbekistan,Neque eu non a felis enim turpis eget mauris lorem.,6/22/12,122.28 Stig Molina,lester@getdesk.at,,,Nonummy,Mattis,Justo,9,BA720380-E958-4D09-8EF2-D5B6FDF0736C,C4DXBUKJ,Georgia,Mollis ut sapien in id pede gravida ante eu nisl aenean ullamcorper potenti nulla parturient nam quisque.,7/10/13,178.12 Bruce Watts,ali.hobbs@gigawerk.gu,,,Nonummy,Mattis,Justo,7,2AF6BE26-EB5F-4745-8822-D54B3536EF9E,W9PO94OR,Finland,Ante facilisis ullamcorper eleifend enim quam justo vestibulum.,8/26/15,583.97 Lincoln Soto,michelle.daniel@presssource.sk,,,Nonummy,Mattis,Justo,5,913AEF6D-547C-41DD-9128-2A6FEF5E5118,9DOEWENU,Benin,Sociis aptent ipsum leo sodales mattis leo sociosqu at amet ligula.,6/22/11,581.01 Camilla Morrison,charles@chatspace.th,,,Ad,Elit,Ullamcorper,7,2ACA4B3C-A619-48AF-9530-8B581E5F9DBA,2AF7QYGX,Uzbekistan,Molestie quis placerat magna turpis iaculis eget nam massa sit congue erat hac habitant lacinia nibh.,2/28/15,492.81 Josie English,stafford@rollthing.nf,,,Eu,Aliquam,Enim,7,34302A6E-CB8F-4691-9D9B-845887D0F5B2,Q7ALASVU,Botswana,Rhoncus hymenaeos sed torquent vestibulum nec mauris id nulla nibh purus purus donec vel nibh morbi.,7/15/13,441.14 Alia Salazar,johan.cook@pressbit.ai,,,Ipsum,Velit,Magna,9,E429BE64-8E1B-4C8F-BB31-C4B2F2754C3C,HKZ2HG9E,New Caledonia,Sed praesent sed rutrum massa suscipit magna mauris interdum massa.,3/28/13,384.99 Beth Sweeney,coral.le@chatsource.dj,,,Ipsum,Velit,Magna,8,3FC9CF5F-EBCC-4482-8F0D-7F99EE2911A4,UM5HO5SD,Vanuatu,Aliquet porttitor elit sagittis mauris nibh rutrum tristique nunc erat mauris per integer nostra imperdiet.,9/2/15,575.23 Stig Bender,lydia@rollsimple.tp,,,Ipsum,Velit,Magna,9,A39EB068-99C6-4377-AB3F-CACC83E083D1,NHYLZ75J,Burundi,Lobortis morbi massa praesent eu ac ad ut nunc aliquam neque scelerisque est fermentum eget elit aenean.,11/29/09,277.87 Angelique Lindsay,villarreal@selfserv.sg,,,Ipsum,Velit,Magna,6,EA864247-21AF-44C9-96CC-D6900C599740,PZ9MMXYD,Lithuania,Id eu molestie adipiscing phasellus duis imperdiet aliquam conubia ligula eget morbi.,8/14/14,552.75 Guillermo Black,raimonds@gigadesk.bd,,,Id,Class,Laoreet,5,543C547F-91CD-4AFD-AFBF-2E2B68FD514D,M3VRKBBJ,Equatorial Guinea,Egestas pretium sollicitudin suspendisse erat sem massa adipiscing eu tempor libero sollicitudin a curabitur mauris.,1/1/14,582.02 Christof Castaneda,campos@fuelserv.bg,,,Eget,Congue,Nisi,6,CAB3E433-8409-475C-8EA0-2801C22B2C2B,B0CGYUG7,Syrian Arab Republic,Feugiat facilisis consequat sociosqu ac consequat lacinia consectetuer tellus leo.,12/2/14,487.02 Chloe Chen,antony@busybase.eu,,,Quis,Tincidunt,Aliquam,7,E3862315-B49C-4EF6-B465-A93FF320A3EC,BTEBYEBS,Greenland,Et suscipit lectus nec morbi tristique mi in nunc tincidunt.,12/26/09,366.24 Andreas McCann,bjorn@jetwerk.hn,,,Non,Ultrices,Congue,10,6F3B60E9-29B0-4421-8EF1-864C8318D20A,JPV00X2A,Estonia,Quis morbi eu sit mollis ad purus consectetuer consectetuer aliquam.,7/15/15,591.28 Owen Buckley,dragan.graves@quitdesk.cg,,,Aliquam,Lacinia,Phasellus,6,52D97856-9714-4A13-9C64-A7E3028F3D64,HWH8ZXSN,"Saint Helena, Ascension and Tristan Da Cunha",Aliquam semper hac sit suspendisse mollis ligula volutpat sociosqu mi conubia porta lorem velit.,4/11/13,837.92 Damian Serrano,arnold.henderson@earlybeat.cz,,,Aliquam,Lacinia,Phasellus,8,0D2E368D-83D4-4FCC-B583-F4F3750E8594,ICRKS93T,Hong Kong,Aliquet ante dui nec tempus a semper nisi non porttitor nisi magna cursus tellus facilisis cras massa.,11/30/10,856.89 Vicky Petty,tobias@tagbase.hk,,,Accumsan,Lacinia,Enim,9,0A3AF79E-C848-4B7D-9B3E-AAD853908643,MC7RH905,Bahrain,Metus imperdiet suspendisse velit integer consectetuer purus per quisque.,11/19/15,285.9 Reginald Wong,adrian@fuellive.hu,,,Et,In,Non,5,DAC224E4-858F-4824-9AB4-B32F8CAAD4B5,VRNKD7KV,Nicaragua,Class vulputate amet semper duis taciti libero morbi etiam tortor primis.,8/15/12,287.21 Belinda Gillespie,claudio.potts@rollblog.nz,,,A,Consectetuer,Hac,10,699E97C0-9631-4207-9123-51990D860E54,ABWLPV48,Albania,Hac sociosqu ad lacinia bibendum sed rutrum sodales diam nisl mauris et quisque.,2/20/11,141.62 Isidro Kelly,guillermo@madewerk.ca,,,Tristique,Sit,Mollis,10,B2E06E00-E797-4082-878F-0A584B583267,ORVTFDS1,Japan,Quis leo porta dui mi mattis enim ligula lectus tincidunt scelerisque dolor a quis libero venenatis class.,4/2/15,936.24 Kris Carlson,ballard@getserv.nr,,,Elit,Quam,Magna,5,3D3B156A-C8E5-4F44-8271-231E5647234A,WYPZ7TL0,Cuba,Diam eu tellus curabitur augue mollis volutpat dictumst tellus non tempor non ultrices nostra egestas.,1/8/12,945.01 Ivo May,ilia.dunlap@rollsource.af,,,Gravida,Mauris,Vivamus,9,033374F0-E202-4DD4-8909-3A376E94AAE3,AIMB2QVF,Paraguay,Ornare sem purus ad sapien egestas vulputate nec.,11/16/15,735.17 Valery Bailey,jenkins@tagclicks.gt,,,Magna,Ante,Erat,8,8405FCDC-423C-4780-85A2-763B76F8E3E6,MTKQNQQ1,United States,Pellentesque sit curabitur cras felis eu ipsum sapien mattis suspendisse taciti tellus bibendum nulla nec.,9/20/14,871.22 Edna Hunt,huynh@busybase.sh,,,Aliquam,Lacinia,Phasellus,9,CDD32EE0-5C1B-43E0-AD2C-AC70A7E49A5F,6PLCX7HA,Israel,Magna interdum lectus lacus ac pede duis class donec auctor tristique pulvinar aliquam adipiscing.,6/22/13,579.79 Debbie Padilla,anderson@fussbit.do,,,Aliquam,Lacinia,Phasellus,6,1AE18842-F09E-4080-B269-B2222E265A07,L9JOMH1V,Pitcairn,Elementum nibh arcu mauris lacus nisl magnis nibh sollicitudin ligula proin.,4/12/14,821.68 Michael Carlson,russell.blake@tagserv.tt,,,Dui,Justo,Vitae,8,184393AC-818C-411F-9835-382556AF6699,A2I31GTM,Canada,Sollicitudin id massa consectetuer at mauris ipsum amet sapien.,5/23/15,654.99 Jay Marsh,jorgen@putbase.mz,,,Curae,Mollis,Elit,6,869A8F25-968F-4D02-A19F-765FE6AE8C84,0Z95CGIA,"Tanzania, United Republic of",Varius lacinia in nunc sit placerat posuere inceptos nibh.,11/27/15,694.94 Lawrence Golden,clay@jetlive.ms,,,Consequat,Nibh,Nisi,8,178AEFF6-3CC9-4696-A819-2EDFBEF029D4,KL16BDUD,Afghanistan,Lorem a nisi nibh est tempor a etiam gravida neque pellentesque pharetra condimentum metus suspendisse at.,1/16/13,923.12 Jean Paul Mayer,salazar@shutsphere.fo,,,Sit,Aliquam,Nunc,10,6D3F66BE-5AA1-4433-B6A9-340D84EAB6A9,V44K0F6X,Chile,Duis eu aliquam massa lorem aptent ligula eleifend vivamus mollis malesuada ac fusce est massa nostra non.,3/18/12,433.79 Kieran McIntyre,daisy.dunlap@selfware.ca,,,Proin,Cursus,Justo,9,745D1136-623A-4AEE-A884-4689614CD977,4Y0JJQTL,French Southern Territories,Nibh sodales nulla adipiscing congue turpis facilisis eu quis libero cursus.,1/11/15,671.09 Amy Singleton,almir.carson@putunit.gn,,,Litora,Quis,Nulla,10,FA7D5D32-9815-4073-93A3-50F1E82967B5,FLS5TGG8,Trinidad and Tobago,Mus elit in posuere nibh tincidunt sociis aliquet tristique morbi at imperdiet turpis.,11/20/10,794.63 Justine Buck,sharon@tidyware.nf,,,Bibendum,Nunc,Massa,10,963FF749-90F2-4801-AB9C-C3B7D8331175,HKWWK3Z6,Niue,Mauris nibh sed et suspendisse mauris ante vestibulum a ullamcorper elit quis.,5/21/15,398.93 Clifton Watkins,jane.montoya@fuelblog.my,,,Id,Duis,Viverra,5,419B9D22-5C4E-47CF-B390-C42A8BC95C1C,ZF8AA2X0,"Virgin Islands, British",Suscipit nec consequat tortor a nonummy commodo lacus cras nisi.,10/9/10,772.13 Javier Goodman,debbie@rollclicks.in,,,Egestas,Mauris,Accumsan,6,AADE6BB0-0BEE-42FB-B8F7-C882C42830CD,OCT4I7OC,"Bolivia, Plurinational State of",Mi est arcu aliquet feugiat mi torquent magna massa at et vel hymenaeos in accumsan.,1/12/14,238.17 Andreas Cross,sarah@mybit.edu,,,Lacinia,Ullamcorper,Torquent,9,FFD22AD7-3A9C-499F-AB28-7595CD0B91FB,7OSLH34U,Mauritius,Aptent bibendum ultrices scelerisque interdum ad ut tempor rhoncus pellentesque mi vulputate velit ligula sem.,7/22/11,837.99 Michael Hudson,brett@getblog.ga,,,Iaculis,Consectetuer,Duis,6,7ED1518C-FD51-4535-A0EA-61A317B329B2,BQRCDS5G,Antigua and Barbuda,Lorem egestas malesuada non tellus eu felis et id eget.,10/25/10,898.36 Travis Sullivan,ayala@earlywerk.bo,,,Sapien,Et,Ipsum,8,6C770379-4788-4D52-9A22-9C13B5E382C6,00Z8ZH9Q,Montserrat,Quam condimentum imperdiet massa eu cras senectus et elit et pharetra sem donec lectus.,10/7/10,642.34 \ No newline at end of file From af6a3dcccd9c392fe0cb1421aa8548b66bc0c35e Mon Sep 17 00:00:00 2001 From: snipe <snipe@snipe.net> Date: Thu, 22 Oct 2015 01:14:21 -0700 Subject: [PATCH 119/120] Updated sample data --- app/private_uploads/imports/assets/sample.csv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/private_uploads/imports/assets/sample.csv b/app/private_uploads/imports/assets/sample.csv index cb5ac9a7da..ba2752659b 100644 --- a/app/private_uploads/imports/assets/sample.csv +++ b/app/private_uploads/imports/assets/sample.csv @@ -1 +1 @@ -Name,Email,Username,Asset Name,Asset Category,Asset Model,Manufacturer,Asset Model Number,Asset Serial,Asset Tag,Location Name,Asset Notes,Purchase Date,Purchase Cost William Dixon,miranda@selfware.ch,,,Malesuada,Et,Nisi,5,4D47A5B7-007D-47F3-B1F2-28C33D3F2C54,58SG1MLI,"Tanzania, United Republic of",Accumsan condimentum sed purus ante mauris tincidunt aliquam libero tempor arcu posuere curabitur sodales imperdiet.,2/16/13,892.46 Debbie Mullins,jesper@madefeed.cf,,,At,Platea,Torquent,9,6DEC0B69-32DB-4801-81FA-07C58E5386CC,FIM4P54T,Isle of Man,Sodales enim duis egestas turpis arcu justo aliquam ipsum erat in cursus iaculis taciti nullam.,4/12/10,961.03 Wolfgang Mitchell,kirk@tagbase.kp,,,Id,Vel,Eu,5,D4017718-D68C-40EC-8669-52745A34B048,SY4NFU7S,Cook Islands,Ac platea nunc nibh in nibh eu arcu eu felis congue nibh aenean morbi quis scelerisque.,4/29/14,771.68 Anne-Marie Wallace,le@tidything.ac,,,Morbi,Sociosqu,Nisl,5,56CC5079-F44B-4D62-BC45-1A4CA4FB8C9F,SK6VTSTG,Uruguay,Nostra ut mauris consectetuer donec scelerisque est per pellentesque nec id urna magna.,8/18/14,325.22 Shane Booker,alain@quitsource.pa,,,Fusce,Fermentum,Sagittis,7,ED248E82-046B-4046-84DA-E4F4A0B55D0E,DBEUH6H2,Cura’_ao,Sed magna inceptos fames ultrices per ut eleifend tellus in class.,10/12/12,951.21 Olivier Walter,margaret@quitbot.tf,,,Malesuada,Et,Nisi,6,FC741D83-3F19-4259-94EC-FFAB3C15C747,40SI9NUR,El Salvador,Orci tortor sed vestibulum nec imperdiet vivamus ridiculus feugiat neque ut pellentesque felis.,8/14/11,368.9 Adrian Montgomery,welch@busybeat.kp,,,Malesuada,Et,Nisi,6,E8E3709B-377E-4FC7-B1B7-1DE0EE60798B,LUXLI88S,Bosnia and Herzegovina,Dapibus scelerisque tempor nisl nascetur dictum vulputate mi.,9/2/13,276.77 Joan Merrill,massey@jetwords.at,,,Malesuada,Et,Nisi,6,3D862DC2-74B5-4744-8D8B-41A757927EB8,ENAZFLV3,Tonga,Malesuada felis accumsan gravida sagittis lacinia pede orci nulla magna litora augue orci.,8/31/14,123.23 Stella Gilmore,wright@quitsource.jp,,,Malesuada,Et,Nisi,5,1E420152-929A-4363-8864-7DE01D38BDE0,8JS4P5P2,Uruguay,Magna in interdum consectetuer consequat tristique dapibus class nulla quis massa dictumst ipsum imperdiet.,4/22/12,333.44 Georgina Wiley,rivera@lowwerk.lv,,,Urna,Et,Integer,10,6E668691-2560-4E3D-89D4-1CDB7404BB8F,J3KHF9EK,Georgia,Consequat non per viverra porta torquent in non et suspendisse bibendum scelerisque sapien mi elit nostra imperdiet.,12/16/14,588.07 Barry Hudson,jane@tagbot.tc,,,Nam,Vivamus,Nibh,5,26825937-9579-4B57-9678-0659A2BB75D7,1V1WQAZA,Poland,Molestie tortor posuere duis lacus feugiat nibh mollis pellentesque nibh mollis tincidunt nisl ut inceptos ac pretium.,4/7/13,839.61 Leigh Stewart,jim.douglas@quitpower.si,,,In,Mauris,Et,9,F5A3666A-951B-46FD-84AF-C0B36BE34243,8PU2UCVH,Uzbekistan,Praesent lectus amet fusce a aliquet pellentesque justo etiam vulputate nec.,3/17/14,724.88 Travis Flynn,nigel.blackburn@gigabase.md,,,Nonummy,Mattis,Justo,7,008A88C0-355D-40F9-B601-7478901147E4,8O77P76Z,Hungary,Massa suscipit porta sapien purus quis metus quis vivamus curae; suspendisse ut imperdiet dapibus.,4/3/12,625.79 Edward Park,sanders@madeclicks.travel,,,Nonummy,Mattis,Justo,9,228F09D4-F8A4-4453-BD7F-6FDB4FCFCE0A,FNKJCPIY,Uzbekistan,Neque eu non a felis enim turpis eget mauris lorem.,6/22/12,122.28 Stig Molina,lester@getdesk.at,,,Nonummy,Mattis,Justo,9,BA720380-E958-4D09-8EF2-D5B6FDF0736C,C4DXBUKJ,Georgia,Mollis ut sapien in id pede gravida ante eu nisl aenean ullamcorper potenti nulla parturient nam quisque.,7/10/13,178.12 Bruce Watts,ali.hobbs@gigawerk.gu,,,Nonummy,Mattis,Justo,7,2AF6BE26-EB5F-4745-8822-D54B3536EF9E,W9PO94OR,Finland,Ante facilisis ullamcorper eleifend enim quam justo vestibulum.,8/26/15,583.97 Lincoln Soto,michelle.daniel@presssource.sk,,,Nonummy,Mattis,Justo,5,913AEF6D-547C-41DD-9128-2A6FEF5E5118,9DOEWENU,Benin,Sociis aptent ipsum leo sodales mattis leo sociosqu at amet ligula.,6/22/11,581.01 Camilla Morrison,charles@chatspace.th,,,Ad,Elit,Ullamcorper,7,2ACA4B3C-A619-48AF-9530-8B581E5F9DBA,2AF7QYGX,Uzbekistan,Molestie quis placerat magna turpis iaculis eget nam massa sit congue erat hac habitant lacinia nibh.,2/28/15,492.81 Josie English,stafford@rollthing.nf,,,Eu,Aliquam,Enim,7,34302A6E-CB8F-4691-9D9B-845887D0F5B2,Q7ALASVU,Botswana,Rhoncus hymenaeos sed torquent vestibulum nec mauris id nulla nibh purus purus donec vel nibh morbi.,7/15/13,441.14 Alia Salazar,johan.cook@pressbit.ai,,,Ipsum,Velit,Magna,9,E429BE64-8E1B-4C8F-BB31-C4B2F2754C3C,HKZ2HG9E,New Caledonia,Sed praesent sed rutrum massa suscipit magna mauris interdum massa.,3/28/13,384.99 Beth Sweeney,coral.le@chatsource.dj,,,Ipsum,Velit,Magna,8,3FC9CF5F-EBCC-4482-8F0D-7F99EE2911A4,UM5HO5SD,Vanuatu,Aliquet porttitor elit sagittis mauris nibh rutrum tristique nunc erat mauris per integer nostra imperdiet.,9/2/15,575.23 Stig Bender,lydia@rollsimple.tp,,,Ipsum,Velit,Magna,9,A39EB068-99C6-4377-AB3F-CACC83E083D1,NHYLZ75J,Burundi,Lobortis morbi massa praesent eu ac ad ut nunc aliquam neque scelerisque est fermentum eget elit aenean.,11/29/09,277.87 Angelique Lindsay,villarreal@selfserv.sg,,,Ipsum,Velit,Magna,6,EA864247-21AF-44C9-96CC-D6900C599740,PZ9MMXYD,Lithuania,Id eu molestie adipiscing phasellus duis imperdiet aliquam conubia ligula eget morbi.,8/14/14,552.75 Guillermo Black,raimonds@gigadesk.bd,,,Id,Class,Laoreet,5,543C547F-91CD-4AFD-AFBF-2E2B68FD514D,M3VRKBBJ,Equatorial Guinea,Egestas pretium sollicitudin suspendisse erat sem massa adipiscing eu tempor libero sollicitudin a curabitur mauris.,1/1/14,582.02 Christof Castaneda,campos@fuelserv.bg,,,Eget,Congue,Nisi,6,CAB3E433-8409-475C-8EA0-2801C22B2C2B,B0CGYUG7,Syrian Arab Republic,Feugiat facilisis consequat sociosqu ac consequat lacinia consectetuer tellus leo.,12/2/14,487.02 Chloe Chen,antony@busybase.eu,,,Quis,Tincidunt,Aliquam,7,E3862315-B49C-4EF6-B465-A93FF320A3EC,BTEBYEBS,Greenland,Et suscipit lectus nec morbi tristique mi in nunc tincidunt.,12/26/09,366.24 Andreas McCann,bjorn@jetwerk.hn,,,Non,Ultrices,Congue,10,6F3B60E9-29B0-4421-8EF1-864C8318D20A,JPV00X2A,Estonia,Quis morbi eu sit mollis ad purus consectetuer consectetuer aliquam.,7/15/15,591.28 Owen Buckley,dragan.graves@quitdesk.cg,,,Aliquam,Lacinia,Phasellus,6,52D97856-9714-4A13-9C64-A7E3028F3D64,HWH8ZXSN,"Saint Helena, Ascension and Tristan Da Cunha",Aliquam semper hac sit suspendisse mollis ligula volutpat sociosqu mi conubia porta lorem velit.,4/11/13,837.92 Damian Serrano,arnold.henderson@earlybeat.cz,,,Aliquam,Lacinia,Phasellus,8,0D2E368D-83D4-4FCC-B583-F4F3750E8594,ICRKS93T,Hong Kong,Aliquet ante dui nec tempus a semper nisi non porttitor nisi magna cursus tellus facilisis cras massa.,11/30/10,856.89 Vicky Petty,tobias@tagbase.hk,,,Accumsan,Lacinia,Enim,9,0A3AF79E-C848-4B7D-9B3E-AAD853908643,MC7RH905,Bahrain,Metus imperdiet suspendisse velit integer consectetuer purus per quisque.,11/19/15,285.9 Reginald Wong,adrian@fuellive.hu,,,Et,In,Non,5,DAC224E4-858F-4824-9AB4-B32F8CAAD4B5,VRNKD7KV,Nicaragua,Class vulputate amet semper duis taciti libero morbi etiam tortor primis.,8/15/12,287.21 Belinda Gillespie,claudio.potts@rollblog.nz,,,A,Consectetuer,Hac,10,699E97C0-9631-4207-9123-51990D860E54,ABWLPV48,Albania,Hac sociosqu ad lacinia bibendum sed rutrum sodales diam nisl mauris et quisque.,2/20/11,141.62 Isidro Kelly,guillermo@madewerk.ca,,,Tristique,Sit,Mollis,10,B2E06E00-E797-4082-878F-0A584B583267,ORVTFDS1,Japan,Quis leo porta dui mi mattis enim ligula lectus tincidunt scelerisque dolor a quis libero venenatis class.,4/2/15,936.24 Kris Carlson,ballard@getserv.nr,,,Elit,Quam,Magna,5,3D3B156A-C8E5-4F44-8271-231E5647234A,WYPZ7TL0,Cuba,Diam eu tellus curabitur augue mollis volutpat dictumst tellus non tempor non ultrices nostra egestas.,1/8/12,945.01 Ivo May,ilia.dunlap@rollsource.af,,,Gravida,Mauris,Vivamus,9,033374F0-E202-4DD4-8909-3A376E94AAE3,AIMB2QVF,Paraguay,Ornare sem purus ad sapien egestas vulputate nec.,11/16/15,735.17 Valery Bailey,jenkins@tagclicks.gt,,,Magna,Ante,Erat,8,8405FCDC-423C-4780-85A2-763B76F8E3E6,MTKQNQQ1,United States,Pellentesque sit curabitur cras felis eu ipsum sapien mattis suspendisse taciti tellus bibendum nulla nec.,9/20/14,871.22 Edna Hunt,huynh@busybase.sh,,,Aliquam,Lacinia,Phasellus,9,CDD32EE0-5C1B-43E0-AD2C-AC70A7E49A5F,6PLCX7HA,Israel,Magna interdum lectus lacus ac pede duis class donec auctor tristique pulvinar aliquam adipiscing.,6/22/13,579.79 Debbie Padilla,anderson@fussbit.do,,,Aliquam,Lacinia,Phasellus,6,1AE18842-F09E-4080-B269-B2222E265A07,L9JOMH1V,Pitcairn,Elementum nibh arcu mauris lacus nisl magnis nibh sollicitudin ligula proin.,4/12/14,821.68 Michael Carlson,russell.blake@tagserv.tt,,,Dui,Justo,Vitae,8,184393AC-818C-411F-9835-382556AF6699,A2I31GTM,Canada,Sollicitudin id massa consectetuer at mauris ipsum amet sapien.,5/23/15,654.99 Jay Marsh,jorgen@putbase.mz,,,Curae,Mollis,Elit,6,869A8F25-968F-4D02-A19F-765FE6AE8C84,0Z95CGIA,"Tanzania, United Republic of",Varius lacinia in nunc sit placerat posuere inceptos nibh.,11/27/15,694.94 Lawrence Golden,clay@jetlive.ms,,,Consequat,Nibh,Nisi,8,178AEFF6-3CC9-4696-A819-2EDFBEF029D4,KL16BDUD,Afghanistan,Lorem a nisi nibh est tempor a etiam gravida neque pellentesque pharetra condimentum metus suspendisse at.,1/16/13,923.12 Jean Paul Mayer,salazar@shutsphere.fo,,,Sit,Aliquam,Nunc,10,6D3F66BE-5AA1-4433-B6A9-340D84EAB6A9,V44K0F6X,Chile,Duis eu aliquam massa lorem aptent ligula eleifend vivamus mollis malesuada ac fusce est massa nostra non.,3/18/12,433.79 Kieran McIntyre,daisy.dunlap@selfware.ca,,,Proin,Cursus,Justo,9,745D1136-623A-4AEE-A884-4689614CD977,4Y0JJQTL,French Southern Territories,Nibh sodales nulla adipiscing congue turpis facilisis eu quis libero cursus.,1/11/15,671.09 Amy Singleton,almir.carson@putunit.gn,,,Litora,Quis,Nulla,10,FA7D5D32-9815-4073-93A3-50F1E82967B5,FLS5TGG8,Trinidad and Tobago,Mus elit in posuere nibh tincidunt sociis aliquet tristique morbi at imperdiet turpis.,11/20/10,794.63 Justine Buck,sharon@tidyware.nf,,,Bibendum,Nunc,Massa,10,963FF749-90F2-4801-AB9C-C3B7D8331175,HKWWK3Z6,Niue,Mauris nibh sed et suspendisse mauris ante vestibulum a ullamcorper elit quis.,5/21/15,398.93 Clifton Watkins,jane.montoya@fuelblog.my,,,Id,Duis,Viverra,5,419B9D22-5C4E-47CF-B390-C42A8BC95C1C,ZF8AA2X0,"Virgin Islands, British",Suscipit nec consequat tortor a nonummy commodo lacus cras nisi.,10/9/10,772.13 Javier Goodman,debbie@rollclicks.in,,,Egestas,Mauris,Accumsan,6,AADE6BB0-0BEE-42FB-B8F7-C882C42830CD,OCT4I7OC,"Bolivia, Plurinational State of",Mi est arcu aliquet feugiat mi torquent magna massa at et vel hymenaeos in accumsan.,1/12/14,238.17 Andreas Cross,sarah@mybit.edu,,,Lacinia,Ullamcorper,Torquent,9,FFD22AD7-3A9C-499F-AB28-7595CD0B91FB,7OSLH34U,Mauritius,Aptent bibendum ultrices scelerisque interdum ad ut tempor rhoncus pellentesque mi vulputate velit ligula sem.,7/22/11,837.99 Michael Hudson,brett@getblog.ga,,,Iaculis,Consectetuer,Duis,6,7ED1518C-FD51-4535-A0EA-61A317B329B2,BQRCDS5G,Antigua and Barbuda,Lorem egestas malesuada non tellus eu felis et id eget.,10/25/10,898.36 Travis Sullivan,ayala@earlywerk.bo,,,Sapien,Et,Ipsum,8,6C770379-4788-4D52-9A22-9C13B5E382C6,00Z8ZH9Q,Montserrat,Quam condimentum imperdiet massa eu cras senectus et elit et pharetra sem donec lectus.,10/7/10,642.34 \ No newline at end of file +Name,Email,Username,Asset Name,Asset Category,Asset Model,Manufacturer,Asset Model Number,Asset Serial,Asset Tag,Location Name,Asset Notes,Purchase Date,Purchase Cost William Dixon,miranda@selfware.ch,,Bleghjgd,Malesuada,Et,Nisi,5,4D47A5B7-007D-47F3-B1F2-28C33D3F2C54,58SG1MLI,"Tanzania, United Republic of",Accumsan condimentum sed purus ante mauris tincidunt aliquam libero tempor arcu posuere curabitur sodales imperdiet.,2/16/13,892.46 Debbie Mullins,jesper@madefeed.cf,,KJhkjfhk,At,Platea,Torquent,9,6DEC0B69-32DB-4801-81FA-07C58E5386CC,FIM4P54T,Isle of Man,Sodales enim duis egestas turpis arcu justo aliquam ipsum erat in cursus iaculis taciti nullam.,4/12/10,961.03 Wolfgang Mitchell,kirk@tagbase.kp,,,Id,Vel,Eu,5,D4017718-D68C-40EC-8669-52745A34B048,SY4NFU7S,Cook Islands,Ac platea nunc nibh in nibh eu arcu eu felis congue nibh aenean morbi quis scelerisque.,4/29/14,771.68 Anne-Marie Wallace,le@tidything.ac,,,Morbi,Sociosqu,Nisl,5,56CC5079-F44B-4D62-BC45-1A4CA4FB8C9F,SK6VTSTG,Uruguay,Nostra ut mauris consectetuer donec scelerisque est per pellentesque nec id urna magna.,8/18/14,325.22 Shane Booker,alain@quitsource.pa,,,Fusce,Fermentum,Sagittis,7,ED248E82-046B-4046-84DA-E4F4A0B55D0E,DBEUH6H2,Cura’_ao,Sed magna inceptos fames ultrices per ut eleifend tellus in class.,10/12/12,951.21 Olivier Walter,margaret@quitbot.tf,,,Malesuada,Et,Nisi,6,FC741D83-3F19-4259-94EC-FFAB3C15C747,40SI9NUR,El Salvador,Orci tortor sed vestibulum nec imperdiet vivamus ridiculus feugiat neque ut pellentesque felis.,8/14/11,368.9 Adrian Montgomery,welch@busybeat.kp,,,Malesuada,Et,Nisi,6,E8E3709B-377E-4FC7-B1B7-1DE0EE60798B,LUXLI88S,Bosnia and Herzegovina,Dapibus scelerisque tempor nisl nascetur dictum vulputate mi.,9/2/13,276.77 Joan Merrill,massey@jetwords.at,,,Malesuada,Et,Nisi,6,3D862DC2-74B5-4744-8D8B-41A757927EB8,ENAZFLV3,Tonga,Malesuada felis accumsan gravida sagittis lacinia pede orci nulla magna litora augue orci.,8/31/14,123.23 Stella Gilmore,wright@quitsource.jp,,,Malesuada,Et,Nisi,5,1E420152-929A-4363-8864-7DE01D38BDE0,8JS4P5P2,Uruguay,Magna in interdum consectetuer consequat tristique dapibus class nulla quis massa dictumst ipsum imperdiet.,4/22/12,333.44 Georgina Wiley,rivera@lowwerk.lv,,,Urna,Et,Integer,10,6E668691-2560-4E3D-89D4-1CDB7404BB8F,J3KHF9EK,Georgia,Consequat non per viverra porta torquent in non et suspendisse bibendum scelerisque sapien mi elit nostra imperdiet.,12/16/14,588.07 Barry Hudson,jane@tagbot.tc,,,Nam,Vivamus,Nibh,5,26825937-9579-4B57-9678-0659A2BB75D7,1V1WQAZA,Poland,Molestie tortor posuere duis lacus feugiat nibh mollis pellentesque nibh mollis tincidunt nisl ut inceptos ac pretium.,4/7/13,839.61 Leigh Stewart,jim.douglas@quitpower.si,,LKfjlgjlf klj,In,Mauris,Et,9,F5A3666A-951B-46FD-84AF-C0B36BE34243,8PU2UCVH,Uzbekistan,Praesent lectus amet fusce a aliquet pellentesque justo etiam vulputate nec.,3/17/14,724.88 Travis Flynn,nigel.blackburn@gigabase.md,,,Nonummy,Mattis,Justo,7,008A88C0-355D-40F9-B601-7478901147E4,8O77P76Z,Hungary,Massa suscipit porta sapien purus quis metus quis vivamus curae; suspendisse ut imperdiet dapibus.,4/3/12,625.79 Edward Park,sanders@madeclicks.travel,,,Nonummy,Mattis,Justo,9,228F09D4-F8A4-4453-BD7F-6FDB4FCFCE0A,FNKJCPIY,Uzbekistan,Neque eu non a felis enim turpis eget mauris lorem.,6/22/12,122.28 Stig Molina,lester@getdesk.at,,,Nonummy,Mattis,Justo,9,BA720380-E958-4D09-8EF2-D5B6FDF0736C,C4DXBUKJ,Georgia,Mollis ut sapien in id pede gravida ante eu nisl aenean ullamcorper potenti nulla parturient nam quisque.,7/10/13,178.12 Bruce Watts,ali.hobbs@gigawerk.gu,,,Nonummy,Mattis,Justo,7,2AF6BE26-EB5F-4745-8822-D54B3536EF9E,W9PO94OR,Finland,Ante facilisis ullamcorper eleifend enim quam justo vestibulum.,8/26/15,583.97 Lincoln Soto,michelle.daniel@presssource.sk,,,Nonummy,Mattis,Justo,5,913AEF6D-547C-41DD-9128-2A6FEF5E5118,9DOEWENU,Benin,Sociis aptent ipsum leo sodales mattis leo sociosqu at amet ligula.,6/22/11,581.01 Camilla Morrison,charles@chatspace.th,,,Ad,Elit,Ullamcorper,7,2ACA4B3C-A619-48AF-9530-8B581E5F9DBA,2AF7QYGX,Uzbekistan,Molestie quis placerat magna turpis iaculis eget nam massa sit congue erat hac habitant lacinia nibh.,2/28/15,492.81 Josie English,stafford@rollthing.nf,,,Eu,Aliquam,Enim,7,34302A6E-CB8F-4691-9D9B-845887D0F5B2,Q7ALASVU,Botswana,Rhoncus hymenaeos sed torquent vestibulum nec mauris id nulla nibh purus purus donec vel nibh morbi.,7/15/13,441.14 Alia Salazar,johan.cook@pressbit.ai,,,Ipsum,Velit,Magna,9,E429BE64-8E1B-4C8F-BB31-C4B2F2754C3C,HKZ2HG9E,New Caledonia,Sed praesent sed rutrum massa suscipit magna mauris interdum massa.,3/28/13,384.99 Beth Sweeney,coral.le@chatsource.dj,,,Ipsum,Velit,Magna,8,3FC9CF5F-EBCC-4482-8F0D-7F99EE2911A4,UM5HO5SD,Vanuatu,Aliquet porttitor elit sagittis mauris nibh rutrum tristique nunc erat mauris per integer nostra imperdiet.,9/2/15,575.23 Stig Bender,lydia@rollsimple.tp,,,Ipsum,Velit,Magna,9,A39EB068-99C6-4377-AB3F-CACC83E083D1,NHYLZ75J,Burundi,Lobortis morbi massa praesent eu ac ad ut nunc aliquam neque scelerisque est fermentum eget elit aenean.,11/29/09,277.87 Angelique Lindsay,villarreal@selfserv.sg,,,Ipsum,Velit,Magna,6,EA864247-21AF-44C9-96CC-D6900C599740,PZ9MMXYD,Lithuania,Id eu molestie adipiscing phasellus duis imperdiet aliquam conubia ligula eget morbi.,8/14/14,552.75 Guillermo Black,raimonds@gigadesk.bd,,,Id,Class,Laoreet,5,543C547F-91CD-4AFD-AFBF-2E2B68FD514D,M3VRKBBJ,Equatorial Guinea,Egestas pretium sollicitudin suspendisse erat sem massa adipiscing eu tempor libero sollicitudin a curabitur mauris.,1/1/14,582.02 Christof Castaneda,campos@fuelserv.bg,,,Eget,Congue,Nisi,6,CAB3E433-8409-475C-8EA0-2801C22B2C2B,B0CGYUG7,Syrian Arab Republic,Feugiat facilisis consequat sociosqu ac consequat lacinia consectetuer tellus leo.,12/2/14,487.02 Chloe Chen,antony@busybase.eu,,,Quis,Tincidunt,Aliquam,7,E3862315-B49C-4EF6-B465-A93FF320A3EC,BTEBYEBS,Greenland,Et suscipit lectus nec morbi tristique mi in nunc tincidunt.,12/26/09,366.24 Andreas McCann,bjorn@jetwerk.hn,,,Non,Ultrices,Congue,10,6F3B60E9-29B0-4421-8EF1-864C8318D20A,JPV00X2A,Estonia,Quis morbi eu sit mollis ad purus consectetuer consectetuer aliquam.,7/15/15,591.28 Owen Buckley,dragan.graves@quitdesk.cg,,,Aliquam,Lacinia,Phasellus,6,52D97856-9714-4A13-9C64-A7E3028F3D64,HWH8ZXSN,"Saint Helena, Ascension and Tristan Da Cunha",Aliquam semper hac sit suspendisse mollis ligula volutpat sociosqu mi conubia porta lorem velit.,4/11/13,837.92 Damian Serrano,arnold.henderson@earlybeat.cz,,,Aliquam,Lacinia,Phasellus,8,0D2E368D-83D4-4FCC-B583-F4F3750E8594,ICRKS93T,Hong Kong,Aliquet ante dui nec tempus a semper nisi non porttitor nisi magna cursus tellus facilisis cras massa.,11/30/10,856.89 Vicky Petty,tobias@tagbase.hk,,,Accumsan,Lacinia,Enim,9,0A3AF79E-C848-4B7D-9B3E-AAD853908643,MC7RH905,Bahrain,Metus imperdiet suspendisse velit integer consectetuer purus per quisque.,11/19/15,285.9 Reginald Wong,adrian@fuellive.hu,,,Et,In,Non,5,DAC224E4-858F-4824-9AB4-B32F8CAAD4B5,VRNKD7KV,Nicaragua,Class vulputate amet semper duis taciti libero morbi etiam tortor primis.,8/15/12,287.21 Belinda Gillespie,claudio.potts@rollblog.nz,,,A,Consectetuer,Hac,10,699E97C0-9631-4207-9123-51990D860E54,ABWLPV48,Albania,Hac sociosqu ad lacinia bibendum sed rutrum sodales diam nisl mauris et quisque.,2/20/11,141.62 Isidro Kelly,guillermo@madewerk.ca,,,Tristique,Sit,Mollis,10,B2E06E00-E797-4082-878F-0A584B583267,ORVTFDS1,Japan,Quis leo porta dui mi mattis enim ligula lectus tincidunt scelerisque dolor a quis libero venenatis class.,4/2/15,936.24 Kris Carlson,ballard@getserv.nr,,,Elit,Quam,Magna,5,3D3B156A-C8E5-4F44-8271-231E5647234A,WYPZ7TL0,Cuba,Diam eu tellus curabitur augue mollis volutpat dictumst tellus non tempor non ultrices nostra egestas.,1/8/12,945.01 Ivo May,ilia.dunlap@rollsource.af,,,Gravida,Mauris,Vivamus,9,033374F0-E202-4DD4-8909-3A376E94AAE3,AIMB2QVF,Paraguay,Ornare sem purus ad sapien egestas vulputate nec.,11/16/15,735.17 Valery Bailey,jenkins@tagclicks.gt,,,Magna,Ante,Erat,8,8405FCDC-423C-4780-85A2-763B76F8E3E6,MTKQNQQ1,United States,Pellentesque sit curabitur cras felis eu ipsum sapien mattis suspendisse taciti tellus bibendum nulla nec.,9/20/14,871.22 Edna Hunt,huynh@busybase.sh,,,Aliquam,Lacinia,Phasellus,9,CDD32EE0-5C1B-43E0-AD2C-AC70A7E49A5F,6PLCX7HA,Israel,Magna interdum lectus lacus ac pede duis class donec auctor tristique pulvinar aliquam adipiscing.,6/22/13,579.79 Debbie Padilla,anderson@fussbit.do,,,Aliquam,Lacinia,Phasellus,6,1AE18842-F09E-4080-B269-B2222E265A07,L9JOMH1V,Pitcairn,Elementum nibh arcu mauris lacus nisl magnis nibh sollicitudin ligula proin.,4/12/14,821.68 Michael Carlson,russell.blake@tagserv.tt,,,Dui,Justo,Vitae,8,184393AC-818C-411F-9835-382556AF6699,A2I31GTM,Canada,Sollicitudin id massa consectetuer at mauris ipsum amet sapien.,5/23/15,654.99 Jay Marsh,jorgen@putbase.mz,,,Curae,Mollis,Elit,6,869A8F25-968F-4D02-A19F-765FE6AE8C84,0Z95CGIA,"Tanzania, United Republic of",Varius lacinia in nunc sit placerat posuere inceptos nibh.,11/27/15,694.94 Lawrence Golden,clay@jetlive.ms,,,Consequat,Nibh,Nisi,8,178AEFF6-3CC9-4696-A819-2EDFBEF029D4,KL16BDUD,Afghanistan,Lorem a nisi nibh est tempor a etiam gravida neque pellentesque pharetra condimentum metus suspendisse at.,1/16/13,923.12 Jean Paul Mayer,salazar@shutsphere.fo,,,Sit,Aliquam,Nunc,10,6D3F66BE-5AA1-4433-B6A9-340D84EAB6A9,V44K0F6X,Chile,Duis eu aliquam massa lorem aptent ligula eleifend vivamus mollis malesuada ac fusce est massa nostra non.,3/18/12,433.79 Kieran McIntyre,daisy.dunlap@selfware.ca,,,Proin,Cursus,Justo,9,745D1136-623A-4AEE-A884-4689614CD977,4Y0JJQTL,French Southern Territories,Nibh sodales nulla adipiscing congue turpis facilisis eu quis libero cursus.,1/11/15,671.09 Amy Singleton,almir.carson@putunit.gn,,,Litora,Quis,Nulla,10,FA7D5D32-9815-4073-93A3-50F1E82967B5,FLS5TGG8,Trinidad and Tobago,Mus elit in posuere nibh tincidunt sociis aliquet tristique morbi at imperdiet turpis.,11/20/10,794.63 Justine Buck,sharon@tidyware.nf,,,Bibendum,Nunc,Massa,10,963FF749-90F2-4801-AB9C-C3B7D8331175,HKWWK3Z6,Niue,Mauris nibh sed et suspendisse mauris ante vestibulum a ullamcorper elit quis.,5/21/15,398.93 Clifton Watkins,jane.montoya@fuelblog.my,,,Id,Duis,Viverra,5,419B9D22-5C4E-47CF-B390-C42A8BC95C1C,ZF8AA2X0,"Virgin Islands, British",Suscipit nec consequat tortor a nonummy commodo lacus cras nisi.,10/9/10,772.13 Javier Goodman,debbie@rollclicks.in,,,Egestas,Mauris,Accumsan,6,AADE6BB0-0BEE-42FB-B8F7-C882C42830CD,OCT4I7OC,"Bolivia, Plurinational State of",Mi est arcu aliquet feugiat mi torquent magna massa at et vel hymenaeos in accumsan.,1/12/14,238.17 Andreas Cross,sarah@mybit.edu,,,Lacinia,Ullamcorper,Torquent,9,FFD22AD7-3A9C-499F-AB28-7595CD0B91FB,7OSLH34U,Mauritius,Aptent bibendum ultrices scelerisque interdum ad ut tempor rhoncus pellentesque mi vulputate velit ligula sem.,7/22/11,837.99 Michael Hudson,brett@getblog.ga,,,Iaculis,Consectetuer,Duis,6,7ED1518C-FD51-4535-A0EA-61A317B329B2,BQRCDS5G,Antigua and Barbuda,Lorem egestas malesuada non tellus eu felis et id eget.,10/25/10,898.36 Travis Sullivan,ayala@earlywerk.bo,,,Sapien,Et,Ipsum,8,6C770379-4788-4D52-9A22-9C13B5E382C6,00Z8ZH9Q,Montserrat,Quam condimentum imperdiet massa eu cras senectus et elit et pharetra sem donec lectus.,10/7/10,642.34 \ No newline at end of file From a3f5dc331d55afdea0b427b055e95bb4ef379e95 Mon Sep 17 00:00:00 2001 From: snipe <snipe@snipe.net> Date: Thu, 22 Oct 2015 02:11:39 -0700 Subject: [PATCH 120/120] Fixes #1007 and #1053 --- app/controllers/admin/AssetsController.php | 20 ++++++++++++++++--- app/models/Asset.php | 15 +++++++++++++- app/views/backend/hardware/view.blade.php | 23 +++++++++++++++++++++- 3 files changed, 53 insertions(+), 5 deletions(-) diff --git a/app/controllers/admin/AssetsController.php b/app/controllers/admin/AssetsController.php index 224aec8d4f..7479f6cec1 100755 --- a/app/controllers/admin/AssetsController.php +++ b/app/controllers/admin/AssetsController.php @@ -904,9 +904,23 @@ class AssetsController extends AdminController // the asset is valid if (isset($asset->id)) { - $log = Actionlog::find($fileId); - $file = $log->get_src(); - return Response::download($file); + + $log = Actionlog::find($fileId); + $file = $log->get_src(); + + $filetype = Asset::checkUploadIsImage($file); + + if ($filetype) { + + $contents = file_get_contents($file); + $response = Response::make($contents); + $response->header('Content-Type', $filetype); + return $response; + + } else { + return Response::download($file); + } + } else { // Prepare the error message $error = Lang::get('admin/hardware/message.does_not_exist', compact('id')); diff --git a/app/models/Asset.php b/app/models/Asset.php index 40fc44fca0..d08e657a69 100755 --- a/app/models/Asset.php +++ b/app/models/Asset.php @@ -159,6 +159,19 @@ class Asset extends Depreciable ->orderBy( 'created_at', 'desc' ); } + public static function checkUploadIsImage($file) { + // Check if the file is an image, so we can show a preview + $finfo = finfo_open(FILEINFO_MIME_TYPE); // return mime type ala mimetype extension + $filetype = finfo_file($finfo, $file); + finfo_close($finfo); + + if (($filetype=="image/jpeg") || ($filetype=="image/jpg") || ($filetype=="image/gif")) { + return true; + } + + return false; + } + public function assigneduser() { @@ -558,7 +571,7 @@ class Asset extends Depreciable { return $query->whereNotNull('deleted_at'); } - + /** * Query builder scope to search on text * diff --git a/app/views/backend/hardware/view.blade.php b/app/views/backend/hardware/view.blade.php index a2ecca7bfc..791f24b9a8 100755 --- a/app/views/backend/hardware/view.blade.php +++ b/app/views/backend/hardware/view.blade.php @@ -9,6 +9,7 @@ {{-- Page content --}} @section('content') + <div class="row header"> <div class="col-md-12"> <h3 class="name"> @@ -283,7 +284,13 @@ @endif </td> <td> - {{{ $file->filename }}} + @if (Asset::checkUploadIsImage($file->get_src())) + <a class='preview' data-placement="top" data-image-url="showfile/{{{ $file->id }}}" data-container="body" data-toggle="popover" data-placement="top" >{{{ $file->filename }}}</a> + @else + {{{ $file->filename }}} + @endif + + </td> <td> @if ($file->filename) @@ -308,6 +315,8 @@ </table> </div> <div class="col-md-12"> + + <h6>History </h6> <!-- checked out assets table --> <table class="table table-hover table-fixed break-word"> <thead> @@ -375,6 +384,7 @@ <!-- side address column --> <div class="col-md-3 col-xs-12 address pull-right"> + <!-- Asset notes --> @if ($asset->notes) @@ -508,5 +518,16 @@ </div> </div> </div> +@section('moar_scripts') +<script> + $('.preview').popover({ + 'trigger':'hover', + 'html':true, + 'content':function(){ + return "<img src='"+$(this).data('imageUrl')+"' style='max-height: 350px; max-width: 250px;'>"; + } + }); +</script> +@stop @stop