From fbced961ea78c4253ee2454c4cbe4edeadbcdbfa Mon Sep 17 00:00:00 2001 From: Woraprat <73052317+aeworaprat@users.noreply.github.com> Date: Thu, 9 Mar 2023 00:32:35 +0700 Subject: [PATCH] update frontend --- html/exhi/application/controllers/General.php | 71 +- .../application/controllers/Instructor.php | 12 +- html/exhi/application/controllers/Tag.php | 4 +- .../application/models/general/Da_general.php | 12 + .../application/models/general/M_general.php | 7 + .../application/models/member/M_member.php | 8 + .../views/general/v_general_select.php | 256 +++- .../views/template/now-ui-kit/javascript.php | 12 +- html/exhi/assets/plugins/page.css | 1 + html/exhi/assets/plugins/page.js | 1179 +++++++++++++++++ 10 files changed, 1472 insertions(+), 90 deletions(-) create mode 100644 html/exhi/assets/plugins/page.css create mode 100644 html/exhi/assets/plugins/page.js diff --git a/html/exhi/application/controllers/General.php b/html/exhi/application/controllers/General.php index 6b3980e..b2d860c 100644 --- a/html/exhi/application/controllers/General.php +++ b/html/exhi/application/controllers/General.php @@ -235,32 +235,49 @@ class general extends Exhibition_Controller $this->load->view('general/v_search', $data); } - public function show_select($id) - { - $this->load->model('project/M_project', 'project'); - $this->load->model('project_tag/M_project_tag', 'project_tag'); - $this->load->model('detail/M_detail', 'detail'); - $this->load->model('member/M_member', 'member'); - $this->load->model('cluster/M_cluster', 'cluster'); - $this->load->model('team/M_team', 'team'); - $this->load->model('instructor/M_instructor', 'instructor'); - $data['project'] = $this->project->get_project_by_id($id)->row(); - $select = ''; - if ($data['project']->cluster_id != 0) { - $select = $this->cluster->get_cluster_by_id($data['project']->cluster_id)->row(); - } else if ($data['project']->team_id != 0) { - $select = $this->team->get_team_by_id($data['project']->team_id)->row(); - } else { - $select = $this->instructor->get_by_id($data['project']->instructor_id)->row(); - } - $data['project']->select = $select->name; - $data['project_tag'] = $this->project_tag->get_by_id($id)->result(); - $data['detail'] = $this->detail->get_detail_by_project_id($id)->result(); - $data['member'] = $this->member->get_member_by_project_id($id)->result(); - // echo '<pre>'; - // print_r($data); - // echo '</pre>'; + public function show_select($id){ + $this->load->model('project/M_project','project'); + $this->load->model('project_tag/M_project_tag','project_tag'); + $this->load->model('detail/M_detail','detail'); + $this->load->model('member/M_member','member'); + $this->load->model('cluster/M_cluster','cluster'); + $this->load->model('team/M_team','team'); + $this->load->model('instructor/M_instructor','instructor'); + $data['project'] = $this->project->get_project_by_id($id)->row(); + $select = ''; + if($data['project']->cluster_id != 0){ + $select = $this->cluster->get_cluster_by_id($data['project']->cluster_id)->row(); + }else if($data['project']->team_id != 0){ + $select = $this->team->get_team_by_id($data['project']->team_id)->row(); + }else{ + $select = $this->instructor->get_by_id($data['project']->instructor_id)->row(); + } + $data['project']->select = $select->name; + $data['project_tag'] = $this->project_tag->get_by_id($id)->result(); + $data['detail'] = $this->detail->get_detail_by_project_id($id)->result(); + $data['member'] = $this->member->get_member_frontend($id)->result(); + // echo '<pre>'; + // print_r($data); + // echo '</pre>'; + + $this->output_frontend('general/v_general_select', $data); + } - $this->output_frontend('general/v_general_select', $data); - } + public function get_comment() + { + $id = $this->input->post('id'); + $this->load->model('general/M_general', 'general'); + $data['comment'] = $this->general->get_comment_all($id)->result(); + echo json_encode($data); + } + + public function insert_comment(){ + $sender = $this->input->post('sender'); + $detail = $this->input->post('detail'); + $id = $this->input->post('id'); + $this->load->model('general/M_general', 'general'); + $this->general->insert_comment($sender, $detail, date("Y-m-d"), $id); + $data['message'] = true; + echo json_encode($data); + } } diff --git a/html/exhi/application/controllers/Instructor.php b/html/exhi/application/controllers/Instructor.php index 571f738..8078f01 100644 --- a/html/exhi/application/controllers/Instructor.php +++ b/html/exhi/application/controllers/Instructor.php @@ -27,10 +27,18 @@ class Instructor extends Exhibition_Controller { } public function insert_instructor(){ + $data['message'] = true ; $name = $this->input->post('name'); $this->load->model('instructor/M_instructor','instructor'); - $this->instructor->insert_instructor($name); - $data['message'] = true ; + $instructors = $this->instructor->get_all()->result(); + foreach($instructors as $instructor){ + if(strtoupper($instructor->name) == strtoupper($name)){ + $data['message'] = false ; + } + } + if($data['message'] == true){ + $this->instructor->insert_instructor($name); + } echo json_encode($data); } diff --git a/html/exhi/application/controllers/Tag.php b/html/exhi/application/controllers/Tag.php index 7279251..4e5cbf9 100644 --- a/html/exhi/application/controllers/Tag.php +++ b/html/exhi/application/controllers/Tag.php @@ -36,7 +36,9 @@ class Tag extends Exhibition_Controller { $data['message'] = false ; } } - $this->tag->insert_tag($name); + if($data['message'] == true){ + $this->tag->insert_tag($name); + } echo json_encode($data); } diff --git a/html/exhi/application/models/general/Da_general.php b/html/exhi/application/models/general/Da_general.php index 1b0009b..0af0274 100644 --- a/html/exhi/application/models/general/Da_general.php +++ b/html/exhi/application/models/general/Da_general.php @@ -10,4 +10,16 @@ class Da_general extends Exhibition_Model { parent::__construct(); } + + public function insert_comment($sender, $detail, $date, $id){ + $sql = "INSERT INTO {$this->db_name}.comment + ( + sender, + detail, + date, + project_id + ) + VALUES (?,?,?,?);"; + $this->db->query($sql, [$sender, $detail, $date, $id]); + } } diff --git a/html/exhi/application/models/general/M_general.php b/html/exhi/application/models/general/M_general.php index a88dc5e..f8f5017 100644 --- a/html/exhi/application/models/general/M_general.php +++ b/html/exhi/application/models/general/M_general.php @@ -177,4 +177,11 @@ class M_general extends Da_general $query = $this->db->query($sql); return $query; } + + public function get_comment_all($id){ + $sql = "SELECT * FROM {$this->db_name}.comment + Where project_id = $id"; + $query = $this->db->query($sql); + return $query; + } } diff --git a/html/exhi/application/models/member/M_member.php b/html/exhi/application/models/member/M_member.php index 27739bc..8325ac7 100644 --- a/html/exhi/application/models/member/M_member.php +++ b/html/exhi/application/models/member/M_member.php @@ -17,4 +17,12 @@ class M_member extends Da_member $query = $this->db->query($sql); return $query; } + + public function get_member_frontend($id){ + $sql = "SELECT user.user_id, user.student_id, user.prefix, user.first_name, user.last_name, user.email, member.image FROM {$this->db_name}.member + join user on member.user_id = user.user_id + Where project_id = $id"; + $query = $this->db->query($sql); + return $query; + } } diff --git a/html/exhi/application/views/general/v_general_select.php b/html/exhi/application/views/general/v_general_select.php index 9a02977..0e17ea7 100644 --- a/html/exhi/application/views/general/v_general_select.php +++ b/html/exhi/application/views/general/v_general_select.php @@ -3,6 +3,7 @@ <!-- <link rel="stylesheet" href="https://cdn.datatables.net/1.11.4/css/dataTables.bootstrap4.min.css" /> --> <script src="https://cdn.datatables.net/1.11.4/js/jquery.dataTables.min.js"></script> +<link href="<?php echo base_url().'assets/plugins/page.css'?>" rel="stylesheet" /> <style> @@ -63,8 +64,8 @@ body { } .card:hover { - transform: scale(1.02); - box-shadow: 0 10px 20px rgba(0, 0, 0, .12), 0 4px 8px rgba(0, 0, 0, .06); + /* transform: scale(1.02); + box-shadow: 0 10px 20px rgba(0, 0, 0, .12), 0 4px 8px rgba(0, 0, 0, .06); */ } .section { @@ -143,6 +144,23 @@ span{ margin-left: auto; margin-right: auto; } +.text-primary-custom { + color: #007bff !important +} +.form-control:focus { + border: 1px solid #767170; + box-shadow: none; + outline: 0!important; + color: #2c2c2c; +} +.bg-light { + background-color: while !important; +} +.center { + display: block; + margin-left: auto; + margin-right: auto; +} </style> <div class="wrapper"> <div class="container"> @@ -185,14 +203,18 @@ span{ </div> <div class="col-6"> <div class="row"> - <a href="<?php echo base_url().$d->image1 ?>" data-toggle="lightbox" data-gallery="example-gallery"> - <img class="image-detail" src="<?php echo base_url().$d->image1 ?>" alt=""> - </a> + <div class="col-12"> + <a href="<?php echo base_url().$d->image1 ?>" data-toggle="lightbox" data-gallery="example-gallery"> + <img class="image-detail center" src="<?php echo base_url().$d->image1 ?>" alt=""> + </a> + </div> </div> <div class="row"> + <div class="col-12"> <a href="<?php echo base_url().$d->image2 ?>" data-toggle="lightbox" data-gallery="example-gallery"> - <img class="image-detail" src="<?php echo base_url().$d->image2 ?>" alt=""> + <img class="image-detail center" src="<?php echo base_url().$d->image2 ?>" alt=""> </a> + </div> </div> </div> </div> @@ -203,14 +225,18 @@ span{ <div class="row"> <div class="col-6"> <div class="row"> - <a href="<?php echo base_url().$d->image1 ?>" data-toggle="lightbox" data-gallery="example-gallery"> - <img class="image-detail" src="<?php echo base_url().$d->image1 ?>" alt=""> - </a> + <div class="col-12"> + <a href="<?php echo base_url().$d->image1 ?>" data-toggle="lightbox" data-gallery="example-gallery"> + <img class="image-detail center" src="<?php echo base_url().$d->image1 ?>" alt=""> + </a> + </div> </div> <div class="row"> + <div class="col-12"> <a href="<?php echo base_url().$d->image2 ?>" data-toggle="lightbox" data-gallery="example-gallery"> - <img class="image-detail" src="<?php echo base_url().$d->image2 ?>" alt=""> + <img class="image-detail center" src="<?php echo base_url().$d->image2 ?>" alt=""> </a> + </div> </div> </div> <div class="col-6"> @@ -223,45 +249,74 @@ span{ <div class="card-body " style='padding: 20px; margin-left: 5px;'> <div class="row"> <div class="col-6"> - <div class="row"> - <a href="<?php echo base_url().$d->image1 ?>" data-toggle="lightbox" data-gallery="example-gallery"> - <img class="image-detail" src="<?php echo base_url().$d->image1 ?>" alt=""> - </a> - </div> - <div class="row"> - <a href="<?php echo base_url().$d->image2 ?>" data-toggle="lightbox" data-gallery="example-gallery"> - <img class="image-detail" src="<?php echo base_url().$d->image2 ?>" alt=""> - </a> - </div> + <a href="<?php echo base_url().$d->image1 ?>" data-toggle="lightbox" data-gallery="example-gallery"> + <img class="image-detail" src="<?php echo base_url().$d->image1 ?>" alt=""> + </a> + </div> + <div class="col-6"> + <a href="<?php echo base_url().$d->image2 ?>" data-toggle="lightbox" data-gallery="example-gallery"> + <img class="image-detail" src="<?php echo base_url().$d->image2 ?>" alt=""> + </a> </div> </div> - <div class="col-6"> + <div class="col-12"> <?php echo $d->description ?> </div> </div> <?php } ?> <?php if($d->template == 4){ ?> - <div class="card-body " style='padding: 20px; margin-left: 5px;'> + <div class="card-body" style='padding: 20px; margin-left: 5px; text-align: justify;'> <div class="row"> <div class="col-12"> <?php echo $d->description ?> </div> <div class="col-6"> <a href="<?php echo base_url().$d->image1 ?>" data-toggle="lightbox" data-gallery="example-gallery"> - <img class="image-detail" src="<?php echo base_url().$d->image1 ?>" alt=""> + <img class="image-detail" src="<?php echo base_url().$d->image1 ?>" alt=""> </a> </div> <div class="col-6"> - <a href="<?php echo base_url().$d->image2 ?>" data-toggle="lightbox" data-gallery="example-gallery"> - <img class="image-detail" src="<?php echo base_url().$d->image2 ?>" alt=""> - </a> + <a href="<?php echo base_url().$d->image2 ?>" data-toggle="lightbox" data-gallery="example-gallery"> + <img class="image-detail" src="<?php echo base_url().$d->image2 ?>" alt=""> + </a> </div> </div> </div> <?php } ?> <?php } ?> <hr> - </div> + <div class="text-center"> + <h4 class="title" style="margin-top: 0px;">สมาชิก</h4> + </div> + <div class="row"> + <?php foreach($member as $m){ ?> + <div class="col-md-4 article-loop" id=""> + <div class="card"> + <div class="text-center"> + <img class="my-image" src='<?php echo base_url().$m->image ?>'> + </div> + <div class="card-body"> + <h5><?php echo $m->prefix.$m->first_name.' '.$m->last_name ?></h5> + <span><h5><i class="fa fa-envelope icon"></i> : <?php echo $m->email ?></h5</span><br> + </div> + </div> + </div> + <?php } ?> + </div> + <hr> + <div class="text-center"> + <h4 class="title" style="margin-top: 0px;">ความคิดเห็น</h4> + </div> + <div class="bg-light-custom p-2"> + <div class="form-group"> + <input type="text" id="sender" value="" placeholder="ชื่อ-นามสกุล" class="form-control"> + </div> + <textarea class="form-control ml-1 shadow-none textarea" placeholder="เขียนความคิดเห็น..." id="detail"></textarea></div> + <div class="mt-2 text-right"><button class="btn btn-info btn-sm shadow-none" type="button" onclick="insert_comment()">เพิ่มความคิดเห็น</button></div> + </div> + <div class="data-container"></div> + <div id="demo"></div> + </div> </div> </div> </div> @@ -270,47 +325,146 @@ span{ <div class="container" > <div class="row"> <div class="col-md-5" > - <b style="font-size:16px;">CLICKNEXT COMPANY LIMITED</b> <br> - <span>128/323-333 30th FL. Phayathai Plaza Bldg. Phayathai road, Thung Phayathai, Ratchathewi, Bangkok, 10400, Thailand. </span> - </div> - <div class="col-md-3 ml-auto" style="margin-top: 20px;"> - <i class="fa fa-phone icon"></i> <span>02-217-7900</span> <br> - <i class="fa fa-envelope icon"></i> <span>Email : info@clicknext.com </span> + <b style="font-size:16px;">คณะวิทยาการสารสนเทศ</b> <br> + <span>169 ถนนลงหาดบางแสน ตำบลแสนสุข</span><br> + <span>อำเภอเมือง จังหวัดชลบุรี 20131</span> </div> - <div class="col-md-3 ml-auto" style="margin-top: 20px;"> - <a style="color: black;" target="_blank" href="https://www.facebook.com/clicknext/"> - <i class="fa-brands fa-facebook icon"></i> - <span>Clicknext Facebook Fanpage</span> - </a> - <br> - <a style="color: black;" target="_blank" href="https://www.youtube.com/channel/UCm3Qapv2K4lj4h6F4aod1Fw"> - <i class="fa-brands fa-youtube icon"></i> - <span>Youtube Channel</span> - </a> + <div class="col-md-7 ml-auto" style="margin-top: 20px;"> + <i class="fa fa-phone icon"></i> <span>+66 (0)38-103061,+66 (0)38-10309</span> <br> + <i class="fa fa-envelope icon"></i> <span>Email : pr@informatics.buu.ac.th </span> </div> </div> </div> </div> </footer> - <footer class="footer-bar"> - <div class=" container "> - <div class="row justify-content-md-center"> <div class="col-md-12"> - <div style="text-align: left;" data-mce-style="text-align: left;"><span style="font-size: 12px; font-family: Barlow_Regular0, Tahoma; color: rgb(157, 157, 157);" open="" sans="" color:="" rgb="" 157="" data-mce-style="font-size: 16px; font-family: Barlow_Regular0, Tahoma; color: #9d9d9d;">Copyright © ClickNext Co.,Ltd All right reserved.</span></div> + <div style="text-align: left;" data-mce-style="text-align: left;"><span style="font-size: 12px; font-family: Barlow_Regular0, Tahoma; color: rgb(157, 157, 157);" open="" sans="" color:="" rgb="" 157="" data-mce-style="font-size: 16px; font-family: Barlow_Regular0, Tahoma; color: #9d9d9d;">Copyright © 2018-2022 Faculty of Informatics, Burapha University. All rights reserved.</span></div> </div> </div> - </div> - - - </footer> +<script src="<?php echo base_url()?>assets/plugins/page.js"></script> <script> + + $(document).ready(function() { + get_comment() + }); $(document).on('click', '[data-toggle="lightbox"]', function(event) { event.preventDefault(); $(this).ekkoLightbox(); }); + + function get_comment(){ + $.ajax({ + type: 'post', + url: "<?php echo site_url() . '/General/get_comment'; ?>", + data: { + 'id': '<?php echo $project->project_id ?>' + }, + dataType: 'json', + success: function(data) { + create_table(data.comment); + } + }) + } + + function create_table(datas){ + var container = $('#demo'); + $('#demo').pagination({ + dataSource: datas, + pageSize: 5, + callback: function(data, pagination) { + dataHtml = '' + dataHtml += '<div class="headings d-flex justify-content-between align-items-center mb-3">' + dataHtml += '<h6>ความคิดเห็นทั้งหมด ('+datas.length+')</h6>' + dataHtml += '</div>' + $.each(data, function (index, item) { + console.log(item) + dataHtml += '<div class="card p-3 mt-2">'; + dataHtml += '<div class="d-flex justify-content-between align-items-center">'; + dataHtml += '<div class="user d-flex flex-row align-items-center">'; + dataHtml += '<span><div class="font-weight-bold text-primary-custom">'+item.sender+'</div><br> <div>'+item.detail+'</div></span>'; + dataHtml += '</div>'; + dataHtml += ' <small>'+convertDate(item.date)+'</small>'; + dataHtml += '</div>'; + dataHtml += '</div>'; + + }); + container.prev().html(dataHtml); + } + }) + } + + function convertDate(dateString){ + var p = dateString.split(/\D/g) + return [p[2],p[1],p[0] ].join("/") + } + + const Toast = Swal.mixin({ + toast: true, + position: 'bottom-start', + showConfirmButton: false, + timer: 1500, + timerProgressBar: true, + didOpen: (toast) => { + toast.addEventListener('mouseenter', Swal.stopTimer) + toast.addEventListener('mouseleave', Swal.resumeTimer) + } + }) + + function insert_comment(){ + let sender = $('#sender').val() + let detail = $('#detail').val() + if(sender == '' || detail == ''){ + Toast.fire({ + icon: 'error', + title: 'กรุณากรอกข้อมูลให้ครบถ้วน', + }) + }else{ + Swal.fire({ + title: ' คุณยืนยันที่จะเพิ่มความคิดเห็นหรือไม่', + text: "", + icon: 'question', + showCancelButton: true, + confirmButtonColor: '#3177ce', + cancelButtonColor: ' white ', + confirmButtonText: 'ใช่', + cancelButtonText: '<Font color=black> ไม่ <Font>', + reverseButtons: true + }).then((result) => { + if (result.value) { + $.ajax({ + type: 'post', + url: "<?php echo site_url().'/General/insert_comment'; ?>", + data: { + 'sender': sender, + 'detail': detail, + 'id': '<?php echo $project->project_id ?>' + }, + dataType: 'json', + success: function(data) { + if (data['message'] == true) { + Toast.fire({ + icon: 'success', + title: 'เพิ่มข้อมูลสำเร็จ', + }).then((result) => { + get_comment() + }) + }else { + Toast.fire({ + icon: 'error', + title: "เพิ่มข้อมูลไม่สำเร็จ", + }) + } + } + }); + } + }) + $(".swal2-cancel").css("border", "1px solid #A79E9E"); + } + + } </script> diff --git a/html/exhi/application/views/template/now-ui-kit/javascript.php b/html/exhi/application/views/template/now-ui-kit/javascript.php index f1179fc..9c2f83b 100644 --- a/html/exhi/application/views/template/now-ui-kit/javascript.php +++ b/html/exhi/application/views/template/now-ui-kit/javascript.php @@ -1,16 +1,10 @@ + <script src="<?php echo base_url()?>assets/template/now-ui-kit-master/assets/js/core/popper.min.js" ></script> <script src="<?php echo base_url()?>assets/template/now-ui-kit-master/assets/js/core/jquery.min.js" ></script> <script src="<?php echo base_url()?>assets/template/now-ui-kit-master/assets/js/core/bootstrap.min.js" ></script> <script src="<?php echo base_url()?>assets/template/now-ui-kit-master/assets/js/plugins/bootstrap-switch.js" ></script> <script src="<?php echo base_url()?>assets/template/now-ui-kit-master/assets/js/plugins/nouislider.min.js" ></script> -<script src="<?php echo base_url()?>assets/template/now-ui-kit-master/assets/js/now-ui-kit.js" ></script> +<script src="<?php echo base_url()?>assets/template/now-ui-kit-master/assets/js/now-ui-kit.js"></script> <script src="<?php echo base_url()?>assets/plugins/fontawesome/js/all.min.js" ></script> - <script src="https://cdnjs.cloudflare.com/ajax/libs/ekko-lightbox/5.3.0/ekko-lightbox.js"></script> - - - - - - - +<script src="<?php echo base_url()?>assets/template/AdminLTE-3.2.0/plugins/sweetalert2/sweetalert2.all.min.js"></script> diff --git a/html/exhi/assets/plugins/page.css b/html/exhi/assets/plugins/page.css new file mode 100644 index 0000000..b6225cc --- /dev/null +++ b/html/exhi/assets/plugins/page.css @@ -0,0 +1 @@ +.paginationjs{display:flex;line-height:1.6;font-family:Marmelad,"Lucida Grande",Arial,"Hiragino Sans GB",Georgia,sans-serif;font-size:14px;box-sizing:initial}.paginationjs:after{display:table;content:" ";clear:both}.paginationjs .paginationjs-pages{float:left;margin-left:10px}.paginationjs .paginationjs-pages ul{float:left;margin:0;padding:0}.paginationjs .paginationjs-go-button,.paginationjs .paginationjs-go-input,.paginationjs .paginationjs-size-changer{margin-left:10px;float:left;font-size:14px}.paginationjs .paginationjs-pages li{float:left;border:1px solid #aaa;border-right:none;list-style:none}.paginationjs .paginationjs-pages li>a{min-width:30px;height:28px;line-height:28px;display:block;background:#fff;font-size:14px;color:#333;text-decoration:none;text-align:center;cursor:pointer}.paginationjs .paginationjs-pages li>a:hover{background:#eee}.paginationjs .paginationjs-pages li.active{border:none}.paginationjs .paginationjs-pages li.active>a{height:30px;line-height:30px;background:#aaa;color:#fff;cursor:default}.paginationjs .paginationjs-pages li.disabled>a{opacity:.3;cursor:default}.paginationjs .paginationjs-pages li.disabled>a:hover{background:0 0}.paginationjs .paginationjs-pages li:first-child,.paginationjs .paginationjs-pages li:first-child>a{border-radius:3px 0 0 3px}.paginationjs .paginationjs-pages li:last-child{border-right:1px solid #aaa;border-radius:0 3px 3px 0}.paginationjs .paginationjs-pages li:last-child>a{border-radius:0 3px 3px 0}.paginationjs .paginationjs-size-changer>select{height:28px;background:#fff;border-radius:3px;border:1px solid #aaa;padding:0;font-size:14px;text-align:center;vertical-align:baseline;outline:0;box-shadow:none;box-sizing:initial}.paginationjs .paginationjs-go-input>input[type=text]{width:30px;height:28px;background:#fff;border-radius:3px;border:1px solid #aaa;padding:0;font-size:14px;text-align:center;vertical-align:baseline;outline:0;box-shadow:none;box-sizing:initial}.paginationjs .paginationjs-go-button>input[type=button]{min-width:40px;height:30px;line-height:28px;background:#fff;border-radius:3px;border:1px solid #aaa;text-align:center;padding:0 8px;font-size:14px;vertical-align:baseline;outline:0;box-shadow:none;color:#333;cursor:pointer;vertical-align:middle\9}.paginationjs .paginationjs-go-button>input[type=button]:hover{background-color:#f8f8f8}.paginationjs .paginationjs-nav{float:left;height:30px;line-height:30px;font-size:14px}.paginationjs.paginationjs-small{font-size:12px}.paginationjs.paginationjs-small .paginationjs-pages li>a{min-width:26px;height:24px;line-height:24px;font-size:12px}.paginationjs.paginationjs-small .paginationjs-pages li.active>a{height:26px;line-height:26px}.paginationjs.paginationjs-small .paginationjs-size-changer{font-size:12px}.paginationjs.paginationjs-small .paginationjs-size-changer>select{height:24px;font-size:12px}.paginationjs.paginationjs-small .paginationjs-go-input{font-size:12px}.paginationjs.paginationjs-small .paginationjs-go-input>input[type=text]{width:26px;height:24px;font-size:12px}.paginationjs.paginationjs-small .paginationjs-go-button{font-size:12px}.paginationjs.paginationjs-small .paginationjs-go-button>input[type=button]{min-width:30px;height:26px;line-height:24px;padding:0 6px;font-size:12px}.paginationjs.paginationjs-small .paginationjs-nav{height:26px;line-height:26px;font-size:12px}.paginationjs.paginationjs-big{font-size:16px}.paginationjs.paginationjs-big .paginationjs-pages li>a{min-width:36px;height:34px;line-height:34px;font-size:16px}.paginationjs.paginationjs-big .paginationjs-pages li.active>a{height:36px;line-height:36px}.paginationjs.paginationjs-big .paginationjs-size-changer{font-size:16px}.paginationjs.paginationjs-big .paginationjs-size-changer>select{height:34px;font-size:16px}.paginationjs.paginationjs-big .paginationjs-go-input{font-size:16px}.paginationjs.paginationjs-big .paginationjs-go-input>input[type=text]{width:36px;height:34px;font-size:16px}.paginationjs.paginationjs-big .paginationjs-go-button{font-size:16px}.paginationjs.paginationjs-big .paginationjs-go-button>input[type=button]{min-width:50px;height:36px;line-height:34px;padding:0 12px;font-size:16px}.paginationjs.paginationjs-big .paginationjs-nav{height:36px;line-height:36px;font-size:16px}.paginationjs>:first-child{margin-left:0}.paginationjs.paginationjs-theme-blue .paginationjs-pages li{border-color:#289de9}.paginationjs.paginationjs-theme-blue .paginationjs-pages li>a{color:#289de9}.paginationjs.paginationjs-theme-blue .paginationjs-pages li>a:hover{background:#e9f4fc}.paginationjs.paginationjs-theme-blue .paginationjs-pages li.active>a{background:#289de9;color:#fff}.paginationjs.paginationjs-theme-blue .paginationjs-pages li.disabled>a:hover{background:0 0}.paginationjs.paginationjs-theme-blue .paginationjs-go-input>input[type=text],.paginationjs.paginationjs-theme-blue .paginationjs-size-changer>select{border-color:#289de9}.paginationjs.paginationjs-theme-blue .paginationjs-go-button>input[type=button]{background:#289de9;border-color:#289de9;color:#fff}.paginationjs.paginationjs-theme-blue .paginationjs-go-button>input[type=button]:hover{background-color:#3ca5ea}.paginationjs.paginationjs-theme-green .paginationjs-pages li{border-color:#449d44}.paginationjs.paginationjs-theme-green .paginationjs-pages li>a{color:#449d44}.paginationjs.paginationjs-theme-green .paginationjs-pages li>a:hover{background:#ebf4eb}.paginationjs.paginationjs-theme-green .paginationjs-pages li.active>a{background:#449d44;color:#fff}.paginationjs.paginationjs-theme-green .paginationjs-pages li.disabled>a:hover{background:0 0}.paginationjs.paginationjs-theme-green .paginationjs-go-input>input[type=text],.paginationjs.paginationjs-theme-green .paginationjs-size-changer>select{border-color:#449d44}.paginationjs.paginationjs-theme-green .paginationjs-go-button>input[type=button]{background:#449d44;border-color:#449d44;color:#fff}.paginationjs.paginationjs-theme-green .paginationjs-go-button>input[type=button]:hover{background-color:#55a555}.paginationjs.paginationjs-theme-yellow .paginationjs-pages li{border-color:#ec971f}.paginationjs.paginationjs-theme-yellow .paginationjs-pages li>a{color:#ec971f}.paginationjs.paginationjs-theme-yellow .paginationjs-pages li>a:hover{background:#fdf5e9}.paginationjs.paginationjs-theme-yellow .paginationjs-pages li.active>a{background:#ec971f;color:#fff}.paginationjs.paginationjs-theme-yellow .paginationjs-pages li.disabled>a:hover{background:0 0}.paginationjs.paginationjs-theme-yellow .paginationjs-go-input>input[type=text],.paginationjs.paginationjs-theme-yellow .paginationjs-size-changer>select{border-color:#ec971f}.paginationjs.paginationjs-theme-yellow .paginationjs-go-button>input[type=button]{background:#ec971f;border-color:#ec971f;color:#fff}.paginationjs.paginationjs-theme-yellow .paginationjs-go-button>input[type=button]:hover{background-color:#eea135}.paginationjs.paginationjs-theme-red .paginationjs-pages li{border-color:#c9302c}.paginationjs.paginationjs-theme-red .paginationjs-pages li>a{color:#c9302c}.paginationjs.paginationjs-theme-red .paginationjs-pages li>a:hover{background:#faeaea}.paginationjs.paginationjs-theme-red .paginationjs-pages li.active>a{background:#c9302c;color:#fff}.paginationjs.paginationjs-theme-red .paginationjs-pages li.disabled>a:hover{background:0 0}.paginationjs.paginationjs-theme-red .paginationjs-go-input>input[type=text],.paginationjs.paginationjs-theme-red .paginationjs-size-changer>select{border-color:#c9302c}.paginationjs.paginationjs-theme-red .paginationjs-go-button>input[type=button]{background:#c9302c;border-color:#c9302c;color:#fff}.paginationjs.paginationjs-theme-red .paginationjs-go-button>input[type=button]:hover{background-color:#ce4541}.paginationjs .paginationjs-pages li.paginationjs-next{border-right:1px solid #aaa\9}.paginationjs .paginationjs-size-changer{margin-left:5px\9}.paginationjs .paginationjs-size-changer>select{line-height:28px\9;vertical-align:middle\9}.paginationjs .paginationjs-go-input{margin-left:5px\9}.paginationjs .paginationjs-go-input>input[type=text]{line-height:28px\9;vertical-align:middle\9}.paginationjs .paginationjs-go-button{margin-left:5px\9}.paginationjs.paginationjs-big .paginationjs-pages li>a{line-height:36px\9}.paginationjs.paginationjs-big .paginationjs-go-input>input[type=text]{height:36px\9;line-height:36px\9} \ No newline at end of file diff --git a/html/exhi/assets/plugins/page.js b/html/exhi/assets/plugins/page.js new file mode 100644 index 0000000..3b7fefc --- /dev/null +++ b/html/exhi/assets/plugins/page.js @@ -0,0 +1,1179 @@ +/* + * pagination.js 2.5.0 + * A jQuery plugin to provide simple yet fully customisable pagination. + * https://github.com/superRaytin/paginationjs + * + * Homepage: http://pagination.js.org + * + * Copyright 2014-2100, superRaytin + * Released under the MIT license. + */ + +(function(global, $) { + + if (typeof $ === 'undefined') { + throwError('Pagination requires jQuery.'); + } + + var pluginName = 'pagination'; + + var pluginHookMethod = 'addHook'; + + var eventPrefix = '__pagination-'; + + if ($.fn.pagination) { + throwError('plugin conflicted, the name "pagination" has been taken by another jQuery plugin.'); + } + + $.fn[pluginName] = function(options) { + + if (typeof options === 'undefined') { + return this; + } + + var container = $(this); + + var attributes = $.extend({}, $.fn[pluginName].defaults, options); + + var pagination = { + + initialize: function() { + var self = this; + + // Cache data for current instance + if (!container.data('pagination')) { + container.data('pagination', {}); + } + + if (self.callHook('beforeInit') === false) return; + + // Pagination has been initialized, destroy it + if (container.data('pagination').initialized) { + $('.paginationjs', container).remove(); + } + + // Whether to disable Pagination at the initialization + self.disabled = !!attributes.disabled; + + // Model will be passed to the callback function + var model = self.model = { + pageRange: attributes.pageRange, + pageSize: attributes.pageSize + }; + + // Parse dataSource to find available paging data + self.parseDataSource(attributes.dataSource, function(dataSource) { + + // Asynchronous mode + self.isAsync = Helpers.isString(dataSource); + if (Helpers.isArray(dataSource)) { + model.totalNumber = attributes.totalNumber = dataSource.length; + } + + // Asynchronous mode and a 'totalNumberLocator' has been specified + self.isDynamicTotalNumber = self.isAsync && attributes.totalNumberLocator; + + var el = self.render(true); + + // Add extra className to the pagination element + if (attributes.className) { + el.addClass(attributes.className); + } + + model.el = el; + + // Append / prepend pagination element to the container + container[attributes.position === 'bottom' ? 'append' : 'prepend'](el); + + // Bind events + self.observer(); + + // Mark pagination has been initialized + container.data('pagination').initialized = true; + + // Call hook after initialization + self.callHook('afterInit', el); + }); + }, + + render: function(isBoot) { + var self = this; + var model = self.model; + var el = model.el || $('<div class="paginationjs"></div>'); + var isForced = isBoot !== true; + + self.callHook('beforeRender', isForced); + + var currentPage = model.pageNumber || attributes.pageNumber; + var pageRange = attributes.pageRange || 0; + var totalPage = self.getTotalPage(); + + var rangeStart = currentPage - pageRange; + var rangeEnd = currentPage + pageRange; + + if (rangeEnd > totalPage) { + rangeEnd = totalPage; + rangeStart = totalPage - pageRange * 2; + rangeStart = rangeStart < 1 ? 1 : rangeStart; + } + + if (rangeStart <= 1) { + rangeStart = 1; + rangeEnd = Math.min(pageRange * 2 + 1, totalPage); + } + + el.html(self.generateHTML({ + currentPage: currentPage, + pageRange: pageRange, + rangeStart: rangeStart, + rangeEnd: rangeEnd + })); + + // Whether to hide pagination when there is only one page + if (attributes.hideOnlyOnePage) { + el[totalPage <= 1 ? 'hide' : 'show'](); + } + + self.callHook('afterRender', isForced); + + return el; + }, + + getPageLinkTag: function(index) { + var pageLink = attributes.pageLink; + return pageLink ? `<a href="${pageLink}">${index}</a>` : `<a>${index}</a>`; + }, + + // Generate HTML for page numbers + generatePageNumbersHTML: function(args) { + var self = this; + var currentPage = args.currentPage; + var totalPage = self.getTotalPage(); + var getPageLinkTag = self.getPageLinkTag; + var rangeStart = args.rangeStart; + var rangeEnd = args.rangeEnd; + var html = ''; + var i; + + var ellipsisText = attributes.ellipsisText; + + var classPrefix = attributes.classPrefix; + var pageClassName = attributes.pageClassName || ''; + var activeClassName = attributes.activeClassName || ''; + var disableClassName = attributes.disableClassName || ''; + + // Display all page numbers if page range disabled + if (attributes.pageRange === null) { + for (i = 1; i <= totalPage; i++) { + if (i == currentPage) { + html += `<li class="${classPrefix}-page J-paginationjs-page ${pageClassName} ${activeClassName}" data-num="${i}"><a>${i}</a></li>`; + } else { + html += `<li class="${classPrefix}-page J-paginationjs-page ${pageClassName}" data-num="${i}">${getPageLinkTag(i)}</li>`; + } + } + return html; + } + + if (rangeStart <= 3) { + for (i = 1; i < rangeStart; i++) { + if (i == currentPage) { + html += `<li class="${classPrefix}-page J-paginationjs-page ${pageClassName} ${activeClassName}" data-num="${i}"><a>${i}</a></li>`; + } else { + html += `<li class="${classPrefix}-page J-paginationjs-page ${pageClassName}" data-num="${i}">${getPageLinkTag(i)}</li>`; + } + } + } else { + if (!attributes.hideFirstOnEllipsisShow) { + html += `<li class="${classPrefix}-page ${classPrefix}-first J-paginationjs-page ${pageClassName}" data-num="1">${getPageLinkTag(1)}</li>`; + } + html += `<li class="${classPrefix}-ellipsis ${disableClassName}"><a>${ellipsisText}</a></li>`; + } + + for (i = rangeStart; i <= rangeEnd; i++) { + if (i == currentPage) { + html += `<li class="${classPrefix}-page J-paginationjs-page ${pageClassName} ${activeClassName}" data-num="${i}"><a>${i}</a></li>`; + } else { + html += `<li class="${classPrefix}-page J-paginationjs-page ${pageClassName}" data-num="${i}">${getPageLinkTag(i)}</li>`; + } + } + + if (rangeEnd >= totalPage - 2) { + for (i = rangeEnd + 1; i <= totalPage; i++) { + html += `<li class="${classPrefix}-page J-paginationjs-page ${pageClassName}" data-num="${i}">${getPageLinkTag(i)}</li>`; + } + } else { + html += `<li class="${classPrefix}-ellipsis ${disableClassName}"><a>${ellipsisText}</a></li>`; + + if (!attributes.hideLastOnEllipsisShow) { + html += `<li class="${classPrefix}-page ${classPrefix}-last J-paginationjs-page ${pageClassName}" data-num="${totalPage}">${getPageLinkTag(totalPage)}</li>`; + } + } + + return html; + }, + + // Generate HTML content + generateHTML: function(args) { + var self = this; + var currentPage = args.currentPage; + var totalPage = self.getTotalPage(); + var getPageLinkTag = self.getPageLinkTag; + + var totalNumber = self.getTotalNumber(); + + var pageSize = attributes.pageSize; + var showPrevious = attributes.showPrevious; + var showNext = attributes.showNext; + var showPageNumbers = attributes.showPageNumbers; + var showNavigator = attributes.showNavigator; + var showSizeChanger = attributes.showSizeChanger; + var sizeChangerOptions = attributes.sizeChangerOptions; + var showGoInput = attributes.showGoInput; + var showGoButton = attributes.showGoButton; + + var prevText = attributes.prevText; + var nextText = attributes.nextText; + var goButtonText = attributes.goButtonText; + + var classPrefix = attributes.classPrefix; + var disableClassName = attributes.disableClassName || ''; + var ulClassName = attributes.ulClassName || ''; + var prevClassName = attributes.prevClassName || ''; + var nextClassName = attributes.nextClassName || ''; + + var html = ''; + var sizeSelect = `<select class="J-paginationjs-size-select">`; + var goInput = '<input type="text" class="J-paginationjs-go-pagenumber">'; + var goButton = `<input type="button" class="J-paginationjs-go-button" value="${goButtonText}">`; + var formattedString; + + var formatSizeChanger = typeof attributes.formatSizeChanger === 'function' ? attributes.formatSizeChanger(currentPage, totalPage, totalNumber) : attributes.formatSizeChanger; + var formatNavigator = typeof attributes.formatNavigator === 'function' ? attributes.formatNavigator(currentPage, totalPage, totalNumber) : attributes.formatNavigator; + var formatGoInput = typeof attributes.formatGoInput === 'function' ? attributes.formatGoInput(goInput, currentPage, totalPage, totalNumber) : attributes.formatGoInput; + var formatGoButton = typeof attributes.formatGoButton === 'function' ? attributes.formatGoButton(goButton, currentPage, totalPage, totalNumber) : attributes.formatGoButton; + + var autoHidePrevious = typeof attributes.autoHidePrevious === 'function' ? attributes.autoHidePrevious() : attributes.autoHidePrevious; + var autoHideNext = typeof attributes.autoHideNext === 'function' ? attributes.autoHideNext() : attributes.autoHideNext; + + var header = typeof attributes.header === 'function' ? attributes.header(currentPage, totalPage, totalNumber) : attributes.header; + var footer = typeof attributes.footer === 'function' ? attributes.footer(currentPage, totalPage, totalNumber) : attributes.footer; + + // Prepend extra contents to the pagination buttons + if (header) { + formattedString = self.replaceVariables(header, { + currentPage: currentPage, + totalPage: totalPage, + totalNumber: totalNumber + }); + html += formattedString; + } + + // Whether to display navigator + if (showNavigator) { + if (formatNavigator) { + formattedString = self.replaceVariables(formatNavigator, { + currentPage: currentPage, + totalPage: totalPage, + totalNumber: totalNumber, + rangeStart: (currentPage - 1) * pageSize + 1, + rangeEnd: Math.min(currentPage * pageSize, totalNumber) + }); + html += `<div class="${classPrefix}-nav J-paginationjs-nav">${formattedString}</div>`; + } + } + + if (showPrevious || showPageNumbers || showNext) { + html += '<div class="paginationjs-pages">'; + + if (ulClassName) { + html += `<ul class="${ulClassName}">`; + } else { + html += '<ul>'; + } + + // Whether to display Previous button + if (showPrevious) { + if (currentPage <= 1) { + if (!autoHidePrevious) { + html += `<li class="${classPrefix}-prev ${disableClassName} ${prevClassName}"><a>${prevText}</a></li>`; + } + } else { + html += `<li class="${classPrefix}-prev J-paginationjs-previous ${prevClassName}" data-num="${currentPage - 1}" title="Previous page">${getPageLinkTag(prevText)}</li>`; + } + } + + // Whether to display page numbers + if (showPageNumbers) { + html += self.generatePageNumbersHTML(args); + } + + // Whether to display Next button + if (showNext) { + if (currentPage >= totalPage) { + if (!autoHideNext) { + html += `<li class="${classPrefix}-next ${disableClassName} ${nextClassName}"><a>${nextText}</a></li>`; + } + } else { + html += `<li class="${classPrefix}-next J-paginationjs-next ${nextClassName}" data-num="${currentPage + 1}" title="Next page">${getPageLinkTag(nextText)}</li>`; + } + } + html += `</ul></div>`; + } + + if (showSizeChanger) { + if (Helpers.isArray(sizeChangerOptions)) { + if (sizeChangerOptions.indexOf(pageSize) === -1) { + sizeChangerOptions.unshift(pageSize); + sizeChangerOptions.sort((a, b) => a - b); + } + for (let i = 0; i < sizeChangerOptions.length; i++) { + sizeSelect += `<option value="${sizeChangerOptions[i]}"${(sizeChangerOptions[i] === pageSize ? ' selected' : '')}>${sizeChangerOptions[i]} / page</option>`; + } + sizeSelect += `</select>`; + formattedString = sizeSelect; + + if (formatSizeChanger) { + formattedString = self.replaceVariables(formatSizeChanger, { + length: sizeSelect, + total: totalNumber + }); + } + html += `<div class="paginationjs-size-changer">${formattedString}</div>`; + } + } + + // Whether to display Go input + if (showGoInput) { + if (formatGoInput) { + formattedString = self.replaceVariables(formatGoInput, { + currentPage: currentPage, + totalPage: totalPage, + totalNumber: totalNumber, + input: goInput + }); + html += `<div class="${classPrefix}-go-input">${formattedString}</div>`; + } + } + + // Whether to display Go button + if (showGoButton) { + if (formatGoButton) { + formattedString = self.replaceVariables(formatGoButton, { + currentPage: currentPage, + totalPage: totalPage, + totalNumber: totalNumber, + button: goButton + }); + html += `<div class="${classPrefix}-go-button">${formattedString}</div>`; + } + } + + // Append extra contents to the pagination buttons + if (footer) { + formattedString = self.replaceVariables(footer, { + currentPage: currentPage, + totalPage: totalPage, + totalNumber: totalNumber + }); + html += formattedString; + } + + return html; + }, + + // dataSource is a request URL and a 'totalNumberLocator' function specified + // execute it to find out 'totalNumber' from the response + findTotalNumberFromRemoteResponse: function(response) { + var self = this; + self.model.totalNumber = attributes.totalNumberLocator(response); + }, + + // Go to the specified page + go: function(number, callback) { + var self = this; + var model = self.model; + + if (self.disabled) return; + + var pageNumber = number; + pageNumber = parseInt(pageNumber); + + if (!pageNumber || pageNumber < 1) return; + + var pageSize = attributes.pageSize; + var totalNumber = self.getTotalNumber(); + var totalPage = self.getTotalPage(); + + if (totalNumber > 0 && pageNumber > totalPage) return; + + // Pick paging data in synchronous mode + if (!self.isAsync) { + render(self.getPagingData(pageNumber)); + return; + } + + var postData = {}; + var alias = attributes.alias || {}; + var pageSizeName = alias.pageSize ? alias.pageSize : 'pageSize'; + var pageNumberName = alias.pageNumber ? alias.pageNumber : 'pageNumber'; + postData[pageSizeName] = pageSize; + postData[pageNumberName] = pageNumber; + + var ajaxParams = typeof attributes.ajax === 'function' ? attributes.ajax() : attributes.ajax; + + // If the pageNumber's value starts with 0 via Ajax + if (ajaxParams && ajaxParams.pageNumberStartWithZero) { + postData[pageNumberName] = pageNumber - 1; + delete ajaxParams.pageNumberStartWithZero; + } + + var formatAjaxParams = { + type: 'get', + cache: false, + data: {}, + contentType: 'application/x-www-form-urlencoded; charset=UTF-8', + dataType: 'json', + async: true + }; + + $.extend(true, formatAjaxParams, ajaxParams); + $.extend(formatAjaxParams.data, postData); + + formatAjaxParams.url = attributes.dataSource; + formatAjaxParams.success = function(response) { + self.model.originalResponse = response; + if (self.isDynamicTotalNumber) { + self.findTotalNumberFromRemoteResponse(response); + } else { + self.model.totalNumber = attributes.totalNumber; + } + + var finalData = self.filterDataWithLocator(response); + render(finalData); + }; + formatAjaxParams.error = function(jqXHR, textStatus, errorThrown) { + attributes.formatAjaxError && attributes.formatAjaxError(jqXHR, textStatus, errorThrown); + self.enable(); + }; + + self.disable(); + + if (attributes.ajaxFunction) { + attributes.ajaxFunction(formatAjaxParams); + } else { + $.ajax(formatAjaxParams); + } + + function render(data) { + if (self.callHook('beforePaging', pageNumber) === false) return false; + + // Pagination direction + model.direction = typeof model.pageNumber === 'undefined' ? 0 : (pageNumber > model.pageNumber ? 1 : -1); + + model.pageNumber = pageNumber; + + self.render(); + + if (self.disabled && self.isAsync) { + // enable pagination + self.enable(); + } + + // cache model data + container.data('pagination').model = model; + + // format result data before callback invoked + if (attributes.formatResult) { + var cloneData = $.extend(true, [], data); + if (!Helpers.isArray(data = attributes.formatResult(cloneData))) { + data = cloneData; + } + } + + container.data('pagination').currentPageData = data; + + self.doCallback(data, callback); + + self.callHook('afterPaging', pageNumber); + + if (pageNumber == 1) { + self.callHook('afterIsFirstPage'); + } else if (pageNumber == self.getTotalPage()) { + self.callHook('afterIsLastPage'); + } + } + }, + + doCallback: function(data, customCallback) { + var self = this; + var model = self.model; + + if (typeof customCallback === 'function') { + customCallback(data, model); + } else if (typeof attributes.callback === 'function') { + attributes.callback(data, model); + } + }, + + destroy: function() { + if (this.callHook('beforeDestroy') === false) return; + + this.model.el.remove(); + container.off(); + + // Remove style element + $('#paginationjs-style').remove(); + + this.callHook('afterDestroy'); + }, + + previous: function(callback) { + this.go(this.model.pageNumber - 1, callback); + }, + + next: function(callback) { + this.go(this.model.pageNumber + 1, callback); + }, + + disable: function() { + var self = this; + var source = self.isAsync ? 'async' : 'sync'; + + if (self.callHook('beforeDisable', source) === false) return; + + self.disabled = true; + self.model.disabled = true; + + self.callHook('afterDisable', source); + }, + + enable: function() { + var self = this; + var source = self.isAsync ? 'async' : 'sync'; + + if (self.callHook('beforeEnable', source) === false) return; + + self.disabled = false; + self.model.disabled = false; + + self.callHook('afterEnable', source); + }, + + refresh: function(callback) { + this.go(this.model.pageNumber, callback); + }, + + show: function() { + var self = this; + + if (self.model.el.is(':visible')) return; + + self.model.el.show(); + }, + + hide: function() { + var self = this; + + if (!self.model.el.is(':visible')) return; + + self.model.el.hide(); + }, + + // Replace variables for template string + replaceVariables: function(template, variables) { + var formattedString; + + for (var key in variables) { + var value = variables[key]; + var regexp = new RegExp('<%=\\s*' + key + '\\s*%>', 'img'); + + formattedString = (formattedString || template).replace(regexp, value); + } + + return formattedString; + }, + + getPagingData: function(number) { + var pageSize = attributes.pageSize; + var dataSource = attributes.dataSource; + var totalNumber = this.getTotalNumber(); + + var start = pageSize * (number - 1) + 1; + var end = Math.min(number * pageSize, totalNumber); + + return dataSource.slice(start - 1, end); + }, + + getTotalNumber: function() { + return this.model.totalNumber || attributes.totalNumber || 0; + }, + + getTotalPage: function() { + return Math.ceil(this.getTotalNumber() / attributes.pageSize); + }, + + getLocator: function(locator) { + var result; + + if (typeof locator === 'string') { + result = locator; + } else if (typeof locator === 'function') { + result = locator(); + } else { + throwError('"locator" is incorrect. Expect string or function type.'); + } + + return result; + }, + + // Filter data with "locator" + filterDataWithLocator: function(dataSource) { + var locator = this.getLocator(attributes.locator); + var filteredData; + + // Datasource is an Object, use "locator" to locate available data + if (Helpers.isObject(dataSource)) { + try { + $.each(locator.split('.'), function(index, item) { + filteredData = (filteredData ? filteredData : dataSource)[item]; + }); + } + catch (e) { + // ignore + } + + if (!filteredData) { + throwError('dataSource.' + locator + ' is undefined.'); + } else if (!Helpers.isArray(filteredData)) { + throwError('dataSource.' + locator + ' should be an Array.'); + } + } + + return filteredData || dataSource; + }, + + parseDataSource: function(dataSource, callback) { + var self = this; + + if (Helpers.isObject(dataSource)) { + callback(attributes.dataSource = self.filterDataWithLocator(dataSource)); + } else if (Helpers.isArray(dataSource)) { + callback(attributes.dataSource = dataSource); + } else if (typeof dataSource === 'function') { + attributes.dataSource(function(data) { + if (!Helpers.isArray(data)) { + throwError('The parameter of "done" Function should be an Array.'); + } + self.parseDataSource.call(self, data, callback); + }); + } else if (typeof dataSource === 'string') { + if (/^https?|file:/.test(dataSource)) { + attributes.ajaxDataType = 'jsonp'; + } + callback(dataSource); + } else { + throwError('Unexpected dataSource type'); + } + }, + + callHook: function(hook) { + var paginationData = container.data('pagination') || {}; + var result; + + var args = Array.prototype.slice.apply(arguments); + args.shift(); + + if (attributes[hook] && typeof attributes[hook] === 'function') { + if (attributes[hook].apply(global, args) === false) { + result = false; + } + } + + if (paginationData.hooks && paginationData.hooks[hook]) { + $.each(paginationData.hooks[hook], function(index, item) { + if (item.apply(global, args) === false) { + result = false; + } + }); + } + + return result !== false; + }, + + observer: function() { + var self = this; + var el = self.model.el; + + // Go to specified page number + container.on(eventPrefix + 'go', function(event, pageNumber, done) { + if (typeof pageNumber === 'string') { + pageNumber = parseInt(pageNumber.trim()); + } + + if (!pageNumber) return; + + if (typeof pageNumber !== 'number') { + throwError('"pageNumber" is incorrect. (Number)'); + } + + self.go(pageNumber, done); + }); + + // Page number button click listener + el.on('click', '.J-paginationjs-page', function(event) { + var current = $(event.currentTarget); + var pageNumber = current.attr('data-num').trim(); + + if (!pageNumber || current.hasClass(attributes.disableClassName) || current.hasClass(attributes.activeClassName)) return; + + if (self.callHook('beforePageOnClick', event, pageNumber) === false) return false; + + self.go(pageNumber); + + self.callHook('afterPageOnClick', event, pageNumber); + + if (!attributes.pageLink) return false; + }); + + // Previous button click listener + el.on('click', '.J-paginationjs-previous', function(event) { + var current = $(event.currentTarget); + var pageNumber = current.attr('data-num').trim(); + + if (!pageNumber || current.hasClass(attributes.disableClassName)) return; + + if (self.callHook('beforePreviousOnClick', event, pageNumber) === false) return false; + + self.go(pageNumber); + + self.callHook('afterPreviousOnClick', event, pageNumber); + + if (!attributes.pageLink) return false; + }); + + // Next button click listener + el.on('click', '.J-paginationjs-next', function(event) { + var current = $(event.currentTarget); + var pageNumber = current.attr('data-num').trim(); + + if (!pageNumber || current.hasClass(attributes.disableClassName)) return; + + if (self.callHook('beforeNextOnClick', event, pageNumber) === false) return false; + + self.go(pageNumber); + + self.callHook('afterNextOnClick', event, pageNumber); + + if (!attributes.pageLink) return false; + }); + + // Go button click listener + el.on('click', '.J-paginationjs-go-button', function(event) { + var pageNumber = $('.J-paginationjs-go-pagenumber', el).val(); + + if (self.callHook('beforeGoButtonOnClick', event, pageNumber) === false) return false; + + container.trigger(eventPrefix + 'go', pageNumber); + + self.callHook('afterGoButtonOnClick', event, pageNumber); + }); + + // go input enter keyup listener + el.on('keyup', '.J-paginationjs-go-pagenumber', function(event) { + if (event.which === 13) { + var pageNumber = $(event.currentTarget).val(); + + if (self.callHook('beforeGoInputOnEnter', event, pageNumber) === false) return false; + + container.trigger(eventPrefix + 'go', pageNumber); + + // Maintain the cursor + $('.J-paginationjs-go-pagenumber', el).focus(); + + self.callHook('afterGoInputOnEnter', event, pageNumber); + } + }); + + el.on('change', '.J-paginationjs-size-select', function(event) { + var current = $(event.currentTarget); + var size = parseInt(current.val()); + var currentPage = self.model.pageNumber || attributes.pageNumber; + + if (typeof size !== 'number') return; + + if (self.callHook('beforeSizeSelectorChange', event, size) === false) return false; + + attributes.pageSize = size; + self.model.pageSize = size; + self.model.totalPage = self.getTotalPage(); + if (currentPage > self.model.totalPage) { + currentPage = self.model.totalPage; + } + self.go(currentPage); + + self.callHook('afterSizeSelectorChange', event, size); + + if (!attributes.pageLink) return false; + }); + + // Previous page + container.on(eventPrefix + 'previous', function(event, done) { + self.previous(done); + }); + + // Next page + container.on(eventPrefix + 'next', function(event, done) { + self.next(done); + }); + + // Disable + container.on(eventPrefix + 'disable', function() { + self.disable(); + }); + + // Enable + container.on(eventPrefix + 'enable', function() { + self.enable(); + }); + + // Refresh + container.on(eventPrefix + 'refresh', function(event, done) { + self.refresh(done); + }); + + // Show + container.on(eventPrefix + 'show', function() { + self.show(); + }); + + // Hide + container.on(eventPrefix + 'hide', function() { + self.hide(); + }); + + // Destroy + container.on(eventPrefix + 'destroy', function() { + self.destroy(); + }); + + // Whether to load the default page + var validTotalPage = Math.max(self.getTotalPage(), 1) + var defaultPageNumber = attributes.pageNumber; + + // Default pageNumber should be 1 when totalNumber is dynamic + if (self.isDynamicTotalNumber) { + if (attributes.resetPageNumberOnInit) defaultPageNumber = 1; + } + + if (attributes.triggerPagingOnInit) { + container.trigger(eventPrefix + 'go', Math.min(defaultPageNumber, validTotalPage)); + } + } + }; + + // Pagination has been initialized + if (container.data('pagination') && container.data('pagination').initialized === true) { + // Handle events + if (isNumeric(options)) { + // eg: container.pagination(5) + container.trigger.call(this, eventPrefix + 'go', options, arguments[1]); + return this; + } else if (typeof options === 'string') { + var args = Array.prototype.slice.apply(arguments); + args[0] = eventPrefix + args[0]; + + switch (options) { + case 'previous': + case 'next': + case 'go': + case 'disable': + case 'enable': + case 'refresh': + case 'show': + case 'hide': + case 'destroy': + container.trigger.apply(this, args); + break; + case 'getSelectedPageNum': + case 'getCurrentPageNum': + if (container.data('pagination').model) { + return container.data('pagination').model.pageNumber; + } else { + return container.data('pagination').attributes.pageNumber; + } + case 'getTotalPage': + return Math.ceil(container.data('pagination').model.totalNumber / container.data('pagination').model.pageSize); + case 'getSelectedPageData': + case 'getCurrentPageData': + return container.data('pagination').currentPageData; + // Whether pagination has been disabled + case 'isDisabled': + return container.data('pagination').model.disabled === true; + default: + throwError('Unknown action: ' + options); + } + return this; + } else { + // Uninstall the old instance before initializing a new one + uninstallPlugin(container); + } + } else { + if (!Helpers.isObject(options)) throwError('Illegal options'); + } + + // Check parameters + parameterChecker(attributes); + + pagination.initialize(); + + return this; + }; + + // Instance defaults + $.fn[pluginName].defaults = { + + // Data source + // Array | String | Function | Object + //dataSource: '', + + // String | Function + //locator: 'data', + + // Function + //totalNumberLocator: function() {}, + + // Total number of data items + totalNumber: 0, + + // Default page number + pageNumber: 1, + + // Number of data items per page + pageSize: 10, + + // Page range (pages around current page) + pageRange: 2, + + // Whether to display the 'Previous' button + showPrevious: true, + + // Whether to display the 'Next' button + showNext: true, + + // Whether to display the page buttons + showPageNumbers: true, + + showNavigator: false, + + // Whether to display the 'Go' input + showGoInput: false, + + // Whether to display the 'Go' button + showGoButton: false, + + showSizeChanger: false, + + sizeChangerOptions: [10, 20, 50, 100], + + // Page link + pageLink: '', + + // 'Previous' text + prevText: '‹', + + // 'Next' text + nextText: '›', + + // Ellipsis text + ellipsisText: '...', + + // 'Go' button text + goButtonText: 'Go', + + // Additional class name(s) for the Pagination container + //className: '', + + classPrefix: 'paginationjs', + + activeClassName: 'active', + + // class name when disabled + disableClassName: 'disabled', + + //ulClassName: '', + + //pageClassName: '', + + //prevClassName: '', + + //nextClassName: '', + + formatNavigator: 'Total <%= totalNumber %> items', + + formatGoInput: '<%= input %>', + + formatGoButton: '<%= button %>', + + // position in the container + position: 'bottom', + + // Auto hide previous button when current page is the first + autoHidePrevious: false, + + // Auto hide next button when current page is the last + autoHideNext: false, + + //header: '', + + //footer: '', + + //alias: {}, + + // Whether to trigger pagination at initialization + triggerPagingOnInit: true, + + // Whether to reset page number at initialization, it works only if dataSource is a URL and totalNumberLocator is specified + resetPageNumberOnInit: true, + + // Whether to hide pagination when less than one page + hideOnlyOnePage: false, + + hideFirstOnEllipsisShow: false, + + hideLastOnEllipsisShow: false, + + // Customize item's innerHTML + callback: function() {} + }; + + // Hook register + $.fn[pluginHookMethod] = function(hook, callback) { + if (arguments.length < 2) { + throwError('Expect 2 arguments at least.'); + } + + if (typeof callback !== 'function') { + throwError('callback should be a function.'); + } + + var container = $(this); + var paginationData = container.data('pagination'); + + if (!paginationData) { + container.data('pagination', {}); + paginationData = container.data('pagination'); + } + + !paginationData.hooks && (paginationData.hooks = {}); + + //paginationData.hooks[hook] = callback; + paginationData.hooks[hook] = paginationData.hooks[hook] || []; + paginationData.hooks[hook].push(callback); + + }; + + // Static method + $[pluginName] = function(selector, options) { + if (arguments.length < 2) { + throwError('Requires two parameters.'); + } + + var container; + + // 'selector' is a jQuery object + if (typeof selector !== 'string' && selector instanceof jQuery) { + container = selector; + } else { + container = $(selector); + } + + if (!container.length) return; + + container.pagination(options); + + return container; + }; + + // ============================================================ + // helpers + // ============================================================ + + var Helpers = {}; + + // Throw error + function throwError(content) { + throw new Error('Pagination: ' + content); + } + + // Check parameters + function parameterChecker(args) { + if (!args.dataSource) { + throwError('"dataSource" is required.'); + } + + if (typeof args.dataSource === 'string') { + if (args.totalNumberLocator === undefined) { + if (args.totalNumber === undefined) { + throwError('"totalNumber" is required.'); + } else if (!isNumeric(args.totalNumber)) { + throwError('"totalNumber" is incorrect. Expect numberic type'); + } + } else { + if (typeof args.totalNumberLocator !== 'function') { + throwError('"totalNumberLocator" should be a Function.'); + } + } + } else if (Helpers.isObject(args.dataSource)) { + if (typeof args.locator === 'undefined') { + throwError('"dataSource" is an Object, please specify a "locator".'); + } else if (typeof args.locator !== 'string' && typeof args.locator !== 'function') { + throwError('' + args.locator + ' is incorrect. Expect string or function type'); + } + } + + if (args.formatResult !== undefined && typeof args.formatResult !== 'function') { + throwError('"formatResult" should be a Function.'); + } + } + + // uninstall plugin + function uninstallPlugin(target) { + var events = ['go', 'previous', 'next', 'disable', 'enable', 'refresh', 'show', 'hide', 'destroy']; + + // off all events + $.each(events, function(index, value) { + target.off(eventPrefix + value); + }); + + // reset pagination data + target.data('pagination', {}); + + // remove pagination element + $('.paginationjs', target).remove(); + } + + // Object type detection + function getObjectType(object, tmp) { + return ( (tmp = typeof(object)) == "object" ? object == null && "null" || Object.prototype.toString.call(object).slice(8, -1) : tmp ).toLowerCase(); + } + + function isNumeric(n) { + return !isNaN(parseFloat(n)) && isFinite(n); + } + + $.each(['Object', 'Array', 'String'], function(index, name) { + Helpers['is' + name] = function(object) { + return getObjectType(object) === name.toLowerCase(); + }; + }); + + /* + * export via AMD or CommonJS + * */ + if (typeof define === 'function' && define.amd) { + define(function() { + return $; + }); + } + +})(this, window.jQuery); -- GitLab