| $this->office = $office; | $this->office = $office; | ||||
| $this->job_table = $job_table; | $this->job_table = $job_table; | ||||
| add_shortcode( 'bts_jobv1_item', array($this, 'bts_jobv1_item')); | add_shortcode( 'bts_jobv1_item', array($this, 'bts_jobv1_item')); | ||||
| add_shortcode( 'bb_timesheet_canvas_v1', array($this, 'bb_timesheet_canvas_v1')); | |||||
| add_shortcode( 'bts_jobv1_editor', array($this, 'bts_jobv1_editor')); | |||||
| add_action('wp_ajax_list_jobv1', array($this,'list_job' )); | add_action('wp_ajax_list_jobv1', array($this,'list_job' )); | ||||
| add_action('wp_ajax_delete_jobv1', array($this,'delete_jobv1' )); | |||||
| } | } | ||||
| return $html; | return $html; | ||||
| } | } | ||||
| public function bts_jobv1_editor($attr){ | |||||
| $html =$this->template('jobv1_editor', 'jobv1_editor.html'); | |||||
| $html = do_shortcode($html); | |||||
| return $html; | |||||
| } | |||||
| public function bb_timesheet_canvas_v1($attr) | |||||
| { | |||||
| return file_get_contents(plugin_dir_path(__FILE__) . "/html/timesheet_canvas_v1.html"); | |||||
| } | |||||
| //generate template based on html file | //generate template based on html file | ||||
| private function template($id, $file) | private function template($id, $file) | ||||
| { | { | ||||
| ); | ); | ||||
| $sql = "SELECT * FROM $this->job_table WHERE start>='%s' and start <='%s' order by start ASC ,staff ASC"; | $sql = "SELECT * FROM $this->job_table WHERE start>='%s' and start <='%s' order by start ASC ,staff ASC"; | ||||
| $sql = "SELECT * FROM $this->job_table order by start ASC ,staff ASC"; | |||||
| //$sql = "SELECT * FROM $this->job_table order by start ASC ,staff ASC"; | |||||
| $query = $wpdb->prepare ($sql, array($start, $finish)); | $query = $wpdb->prepare ($sql, array($start, $finish)); | ||||
| $response['sql'] = $query; | $response['sql'] = $query; | ||||
| $jobs = $wpdb->get_results($query); | $jobs = $wpdb->get_results($query); | ||||
| } | } | ||||
| wp_send_json($response); | wp_send_json($response); | ||||
| } | } | ||||
| //ajax delete jobs | |||||
| function delete_jobv1(){ | |||||
| check_ajax_referer('acaresydney'); | |||||
| $id = $_POST['jobid']; | |||||
| $jobs = $_POST['jobs']; | |||||
| if ($id != ''){ | |||||
| $this->ajax_delete_single_job($id); | |||||
| }else if (!empty($jobs)) { | |||||
| $this->ajax_delete_multiple_jobs($jobs); | |||||
| } | |||||
| wp_die(); | |||||
| } | |||||
| private function ajax_delete_single_job($id) | |||||
| { | |||||
| global $wpdb; | |||||
| //delete single job; | |||||
| $result = $wpdb->delete($this->job_table, array('id'=> $id)); | |||||
| $response=array( | |||||
| 'status' => 'success', | |||||
| 'id' => $id, | |||||
| 'action'=> 'delete', | |||||
| 'error' => $wpdb->last_error, | |||||
| ); | |||||
| if ($result == 1){ | |||||
| wp_send_json($response); | |||||
| }else{ | |||||
| $response['status'] = 'error'; | |||||
| $response['error'] = $this->db->last_error; | |||||
| wp_send_json($response); | |||||
| } | |||||
| wp_die(); | |||||
| } | |||||
| private function ajax_delete_multiple_jobs($job_ids) | |||||
| { | |||||
| global $wpdb; | |||||
| $ids = implode( ',', array_map( 'absint', $job_ids ) ); | |||||
| $sql = "DELETE FROM $this->job_table WHERE ID IN($ids)" ; | |||||
| $result = $wpdb->query( "DELETE FROM $this->job_table WHERE ID IN($ids)" ); | |||||
| $response=array( | |||||
| 'status' => 'success', | |||||
| 'ids' => $job_ids, | |||||
| 'action'=> 'delete', | |||||
| 'deleted' => $result, | |||||
| 'error' => $wpdb->last_error, | |||||
| ); | |||||
| if ($this->db->last_error == "" ){ | |||||
| wp_send_json($response); | |||||
| }else{ | |||||
| $response['status'] = 'error'; | |||||
| $response['error'] = $this->db->last_error; | |||||
| wp_send_json($response); | |||||
| } | |||||
| wp_die(); | |||||
| } | |||||
| } | } |
| } | } | ||||
| @keyframes blinker { | @keyframes blinker { | ||||
| 50% { | |||||
| opacity: 0; | |||||
| } | |||||
| 50% { opacity: 0; } | |||||
| } | } | ||||
| @keyframes swing { | |||||
| 0% { padding-left:0px; background-color:yellow;} | |||||
| 50% { padding-left:10px; background-color: lightyellow;} | |||||
| 100% { padding-left:0px; background-color:yellow;} | |||||
| @keyframes flash { | |||||
| 0% { padding-top:0px; background-color:yellow;} | |||||
| 50% { padding-top:5px; color:red; background-color: lightyellow;} | |||||
| 100% { padding-top:0px; background-color:yellow;} | |||||
| } | } | ||||
| .titlebar_gradient { | .titlebar_gradient { | ||||
| } | } | ||||
| .divTable.blueTable .divTableBody .divTableCell { | .divTable.blueTable .divTableBody .divTableCell { | ||||
| font-size: 15px; | |||||
| /* font-size: 15px; */ | |||||
| border-bottom: 1px lightgrey solid; | border-bottom: 1px lightgrey solid; | ||||
| border-right: 1px lightgrey dotted; | border-right: 1px lightgrey dotted; | ||||
| vertical-align: middle; | vertical-align: middle; | ||||
| .divTable.blueTable .divTableHeading .divTableHead { | .divTable.blueTable .divTableHeading .divTableHead { | ||||
| font-size: 15px; | font-size: 15px; | ||||
| font-weight: bold; | font-weight: bold; | ||||
| color: #FFFFFF; | |||||
| color: #FFFFFF !important; | |||||
| border-left: 2px solid #D0E4F5; | border-left: 2px solid #D0E4F5; | ||||
| } | } | ||||
| background-color: lightyellow !important; | background-color: lightyellow !important; | ||||
| } | } | ||||
| .jobTable.Editing{ | |||||
| box-shadow: 0px 0px 10px green; | |||||
| animation: flash 1s linear infinite; | |||||
| } | |||||
| .Editor{ | |||||
| box-shadow: 0px 0px 10px green; | |||||
| } | |||||
| .Editor select{ | |||||
| color:black !important; | |||||
| } | |||||
| .jobTable.Editing div, | |||||
| .Editor div { | |||||
| font-weight:900; | |||||
| background-color: lightyellow !important; | |||||
| } | |||||
| .divTable.invalidjob.highlight { | .divTable.invalidjob.highlight { | ||||
| box-shadow: 1px 1px 10px #f50202; | box-shadow: 1px 1px 10px #f50202; | ||||
| } | } | ||||
| div.bstaff, | div.bstaff, | ||||
| div.bclient, | div.bclient, | ||||
| div.bconfirmed, | div.bconfirmed, | ||||
| div.bedit, | |||||
| div.bsave, | div.bsave, | ||||
| div.brating, | div.brating, | ||||
| div.bdelete { | div.bdelete { | ||||
| width: 10%; | |||||
| width: 5%; | |||||
| height: 30px; | height: 30px; | ||||
| position:relative; | |||||
| } | } | ||||
| div.btos { | div.btos { | ||||
| width: 20%; | |||||
| width: 15%; | |||||
| } | } | ||||
| div.bstart, | div.bstart, | ||||
| div.bfinish { | div.bfinish { | ||||
| width: 11%; | |||||
| width: 10%; | |||||
| } | |||||
| div.bstaff, | |||||
| div.bclient{ | |||||
| width: 10%; | |||||
| } | } | ||||
| div.brate { | div.brate { | ||||
| width: 10%; | width: 10%; | ||||
| max-width: 20px; | max-width: 20px; | ||||
| } | } | ||||
| div.btos.error, | |||||
| div.brate.error{ | div.brate.error{ | ||||
| position:relative; | position:relative; | ||||
| background-color: red !important; | background-color: red !important; | ||||
| animation: swing 1s linear infinite; | |||||
| animation: flash 1s linear infinite; | |||||
| } | } | ||||
| div.error::after{ | div.error::after{ | ||||
| position:absolute; | position:absolute; | ||||
| } | } | ||||
| div.bdelete, | div.bdelete, | ||||
| div.bedit, | |||||
| div.bsave, | div.bsave, | ||||
| div.bconfirmed { | div.bconfirmed { | ||||
| text-align: center; | text-align: center; | ||||
| width: 5%; | |||||
| width: 3%; | |||||
| } | } | ||||
| div.brating { | div.brating { | ||||
| width: 3%; | |||||
| text-align: center; | text-align: center; | ||||
| cursor: pointer; | cursor: pointer; | ||||
| } | } | ||||
| .brating { | |||||
| unicode-bidi: bidi-override; | |||||
| direction: rtl; | |||||
| div.Editor div.brating{ | |||||
| min-width:110px; | |||||
| } | } | ||||
| div.workspace .brating > span:hover:before, | |||||
| div.workspace .brating > span:hover ~ span:before { | |||||
| content: "\2605"; | |||||
| position: absolute; | |||||
| div.bedit{ | |||||
| text-align:center; | |||||
| cursor: pointer; | |||||
| } | } | ||||
| div.bsave span.ticon-copy { | div.bsave span.ticon-copy { | ||||
| display: none; | display: none; | ||||
| } | } | ||||
| div.divTableHeading div.bsave span.ticon, | |||||
| div.jobTable.saved div.bsave span.ticon-copy { | div.jobTable.saved div.bsave span.ticon-copy { | ||||
| display: inline-block; | display: inline-block; | ||||
| border: 3px solid orange; | border: 3px solid orange; | ||||
| animation-name: blinker; | animation-name: blinker; | ||||
| } | } | ||||
| div.bdelete span.ticon-trash { | |||||
| div.bdelete span.ticon-trash, | |||||
| div.bedit span.ticon-edit { | |||||
| display: inline-block; | display: inline-block; | ||||
| border: 3px solid lightgrey; | border: 3px solid lightgrey; | ||||
| padding: 5px; | padding: 5px; | ||||
| color: red; | color: red; | ||||
| cursor: pointer; | cursor: pointer; | ||||
| } | } | ||||
| div.bedit span.ticon-edit{ | |||||
| color:blue; | |||||
| } | |||||
| div.workspace div > span:hover { | div.workspace div > span:hover { | ||||
| box-shadow: 0px 0px 10px black; | box-shadow: 0px 0px 10px black; | ||||
| } | } | ||||
| div.jobTable.to_be_deleted_duplicate{ | |||||
| color: red; | |||||
| } | |||||
| div.jobTable.to_be_deleted_duplicate span.ticon-trash | |||||
| { | |||||
| animation: blinker 0.3s linear infinite; | |||||
| } | |||||
| div.jobTable.to_be_deleted_duplicate span.ticon-copy, | |||||
| div.jobTable.to_be_deleted_duplicate span.ticon-edit{ | |||||
| display:none !important; | |||||
| } | |||||
| div.divTableHeading div > span:hover { | div.divTableHeading div > span:hover { | ||||
| cursor: pointer; | cursor: pointer; | ||||
| animation: blinker 0.3s linear infinite; | animation: blinker 0.3s linear infinite; | ||||
| .bts_message .ult_modal-body .span { | .bts_message .ult_modal-body .span { | ||||
| font-weight: 900; | font-weight: 900; | ||||
| } | |||||
| } | |||||
| .xdsoft_datetimepicker{ | |||||
| z-index: 16777272; /* above the modal box */ | |||||
| } |
| data-id="{{id}}" data-tos="{{tos}}" data-rate="{{rate}}" data-staff="{{staff}}" data-client="{{client}}"> | data-id="{{id}}" data-tos="{{tos}}" data-rate="{{rate}}" data-staff="{{staff}}" data-client="{{client}}"> | ||||
| <div class="divTableBody"> | <div class="divTableBody"> | ||||
| <div class="divTableRow"> | <div class="divTableRow"> | ||||
| <div class="divTableCell btos"> | |||||
| <div class="divTableCell btos {{#tos_err}}error{{/tos_err}}" title="{{tos_err}}"> | |||||
| {{tos_name}} | {{tos_name}} | ||||
| </div> | </div> | ||||
| <div class="divTableCell bstart">{{start}}</div> | <div class="divTableCell bstart">{{start}}</div> | ||||
| <div class="divTableCell bfinish">{{finish}}</div> | <div class="divTableCell bfinish">{{finish}}</div> | ||||
| <div class="divTableCell brate {{#non_hour}} error {{/non_hour}}" {{#non_hour}} title="{{brate_err}}" {{/non_hour}} >{{rate_name}}</div> | |||||
| <div class="divTableCell bstaff">{{staff_name}}</div> | |||||
| <div class="divTableCell brate {{#rate_non_hour}} error {{/rate_non_hour}}" {{#non_hour}} title="{{rate_err}}" {{/non_hour}} >{{rate_name}}</div> | |||||
| <div class="divTableCell bstaff {{#staff_err}} error {{/staff_err}}" title="{{staff_err}}">{{staff_name}}</div> | |||||
| <div class="divTableCell bclient {{#is_week1}}week1color{{/is_week1}} {{#is_week2}}week2color{{/is_week2}}">{{client_name}}</div> | <div class="divTableCell bclient {{#is_week1}}week1color{{/is_week1}} {{#is_week2}}week2color{{/is_week2}}">{{client_name}}</div> | ||||
| <div class="divTableCell bconfirmed"><input name="ack" type=checkbox {{#is_confirmed}}checked{{/is_confirmed}} onclick="return false;"></div> | <div class="divTableCell bconfirmed"><input name="ack" type=checkbox {{#is_confirmed}}checked{{/is_confirmed}} onclick="return false;"></div> | ||||
| <div class="divTableCell brating">{{rating}}</div> | <div class="divTableCell brating">{{rating}}</div> | ||||
| <div class="divTableCell bedit"> | |||||
| <span class="ticon ticon-edit"></span> | |||||
| </div> | |||||
| <div class="divTableCell bdelete"> | <div class="divTableCell bdelete"> | ||||
| <span class="ticon ticon-trash"></span> | <span class="ticon ticon-trash"></span> | ||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| <div class="divTableRow errmsg"> | <div class="divTableRow errmsg"> | ||||
| <div class="divTableCell btos_err"></div> | |||||
| <div class="divTableCell bstart_err"></div> | |||||
| <div class="divTableCell bfinish_err"></div> | |||||
| <div class="divTableCell brate_err"></div> | |||||
| <div class="divTableCell bstaff_err"></div> | |||||
| <div class="divTableCell bclient_err"></div> | |||||
| <div class="divTableCell bconfirmed_err"></div> | |||||
| <div class="divTableCell brating_err"></div> | |||||
| <div class="divTableCell bdelete_err"></div> | |||||
| <div class="divTableCell bsave_err"></div> | |||||
| <div class="divTableCell btos_err">{{tos_err}}</div> | |||||
| <div class="divTableCell bstart_err">{{start_err}}</div> | |||||
| <div class="divTableCell bfinish_err">{{finish_err}}</div> | |||||
| <div class="divTableCell brate_err">{{rate_err}}</div> | |||||
| <div class="divTableCell bstaff_err">{{staff_err}}</div> | |||||
| <div class="divTableCell bclient_err">{{client_err}}</div> | |||||
| <div class="divTableCell bconfirmed_err">{{ack_err}}</div> | |||||
| <div class="divTableCell brating_err">{{rating_err}}</div> | |||||
| <div class="divTableCell "></div> | |||||
| <div class="divTableCell bdelete_err">{{delete_err}}</div> | |||||
| <div class="divTableCell bsave_err">{{save_err}}</div> | |||||
| </div> | </div> | ||||
| </div> | </div> |
| <div class="divTable Editor blueTable" id='editor_{{editorid}}' data-id="{{id}}"> | |||||
| <div class="divTableBody"> | |||||
| <div class="divTableRow"> | |||||
| <div class="divTableCell btos">Type of Service </div> | |||||
| <div class="divTableCell bstart">Start</div> | |||||
| <div class="divTableCell bfinish">Finish</div> | |||||
| <div class="divTableCell brate">Hourly Rate</div> | |||||
| <div class="divTableCell bstaff">Staff</div> | |||||
| <div class="divTableCell bclient">Client</div> | |||||
| <div class="divTableCell bconfirmed">Ack</div> | |||||
| <div class="divTableCell brating"> | |||||
| <span class="ticon ticon-star"></span> | |||||
| <span class="ticon ticon-star"></span> | |||||
| <span class="ticon ticon-star"></span> | |||||
| <span class="ticon ticon-star"></span> | |||||
| <span class="ticon ticon-star"></span> | |||||
| </div> | |||||
| <div class="divTableCell bdelete"> | |||||
| </div> | |||||
| <div class="divTableCell bsave "> | |||||
| </div> | |||||
| </div> | |||||
| <div class="divTableRow"> | |||||
| <div class="divTableCell btos"> | |||||
| [bts_type_of_service] | |||||
| </div> | |||||
| <div class="divTableCell bstart"><input class="datepicker" placeholder="2019-07-10 01:00" value=""></input></div> | |||||
| <div class="divTableCell bfinish"><input class="datepicker" placeholder="2019-07-10 01:00" value=""></input></div> | |||||
| <div class="divTableCell brate">[bts_rate_options]</div> | |||||
| <div class="divTableCell bstaff">[bts_select_staff]</div> | |||||
| <div class="divTableCell bclient">[bts_select_client]</div> | |||||
| <div class="divTableCell bconfirmed"><input type=checkbox ></div> | |||||
| <div class="divTableCell brating"> | |||||
| <select> | |||||
| <option value="5">5-Best</option> | |||||
| <option value="4">4-Good</option> | |||||
| <option value="3">3-Standard</option> | |||||
| <option value="2">2-Bad</option> | |||||
| <option value="1">1-Worst</option> | |||||
| <option value="0">0-No Feedback</option> | |||||
| </select> | |||||
| </div> | |||||
| <div class="divTableCell bdelete"> | |||||
| <span class="ticon ticon-plus"></span> | |||||
| </div> | |||||
| <div class="divTableCell bsave "> | |||||
| <span class="ticon ticon-save"></span> | |||||
| </div> | |||||
| </div> | |||||
| <div class="divTableRow errmsg"> | |||||
| <div class="divTableCell btos_err"> e tos | |||||
| </div> | |||||
| <div class="divTableCell bstart_err">es</div> | |||||
| <div class="divTableCell bfinish_err">ef</div> | |||||
| <div class="divTableCell brate_err">er</div> | |||||
| <div class="divTableCell bstaff_err">estaf</div> | |||||
| <div class="divTableCell bclient_err">ecli</div> | |||||
| <div class="divTableCell bconfirmed_err">econfirm</div> | |||||
| <div class="divTableCell brating_err">erat</div> | |||||
| <div class="divTableCell bdelete_err">edel</div> | |||||
| <div class="divTableCell bsave_err">eeave</div> | |||||
| </div> | |||||
| </div> | |||||
| </div> |
| <div class='peoplebar left'> | |||||
| <div class='b_search titlebar_gradient'> | |||||
| <span class="ticon ticon-search"></span> | |||||
| <input type="text" placeholder="staff"> | |||||
| <span class="ticon ticon-times-circle-o"></span> | |||||
| </div> | |||||
| <button class='peoplelist' name='up'> | |||||
| <span class="ticon ticon-angle-double-up"></span> | |||||
| </button> | |||||
| <div class="stafflist userlist"> | |||||
| <img> | |||||
| </div> | |||||
| <button class='peoplelist' name='down'> | |||||
| <span class="ticon ticon-angle-double-down"></span> | |||||
| </button> | |||||
| </div> | |||||
| <div class='peoplebar right'> | |||||
| <div class='b_search titlebar_gradient'> | |||||
| <span class="ticon ticon-search"></span> | |||||
| <input type="text" placeholder="client"> | |||||
| <span class="ticon ticon-times-circle-o"></span> | |||||
| </div> | |||||
| <button class='peoplelist' name='up'> | |||||
| <span class="ticon ticon-angle-double-up"></span> | |||||
| </button> | |||||
| <div class="clientlist userlist"> | |||||
| <img> | |||||
| </div> | |||||
| <button class='peoplelist' name='down'> | |||||
| <span class="ticon ticon-angle-double-down"></span> | |||||
| </button> | |||||
| </div> | |||||
| <div class='timesheets'> | |||||
| <div class='sheettitle titlebar_gradient'> | |||||
| <h1>Web Office - Today:<span name='today'> Today </span> </h1> | |||||
| </div> | |||||
| <div class='sheetsheader'> | |||||
| <div class='weekly'> | |||||
| <div class='weekname prev'> | |||||
| <input id='week1b' type=text class='boundary_datepicker' value="2019-07-01" placeholder="2019-07-01">Week | |||||
| <span name='week1'>10</span> | |||||
| <i class="ticon ticon-caret-right"></i> | |||||
| </div> | |||||
| <div class='copyprogress'> | |||||
| <div name='copyschedule'> | |||||
| Add a Job | |||||
| <span class='ticon ticon-plus'></span> | |||||
| </div> | |||||
| </div> | |||||
| <div class='weekname next'> | |||||
| <i class="ticon ticon-caret-left"></i> | |||||
| Week | |||||
| <span name='week2'>11</span> | |||||
| <input id='week2b' type=text class='boundary_datepicker' value="2019-07-01" placeholder="2019-07-01"> | |||||
| </div> | |||||
| <div class="weekdays"> | |||||
| <div class='week1'> | |||||
| <div class='week1color'> | |||||
| <span name='w1n1'>Mon</span> | |||||
| <br> | |||||
| <span class="weekday" name='w1d1'>12</span> | |||||
| </div> | |||||
| <div class='week1color'> | |||||
| <span name='w1n2'>Tue</span> | |||||
| <br> | |||||
| <span class="weekday" name='w1d2'>12</span> | |||||
| </div> | |||||
| <div class='week1color'> | |||||
| <span name='w1n3'>Wed</span> | |||||
| <br> | |||||
| <span class="weekday" name='w1d3'>12</span> | |||||
| </div> | |||||
| <div class='week1color'> | |||||
| <span name='w1n4'>Thu</span> | |||||
| <br> | |||||
| <span class="weekday" name='w1d4'>12</span> | |||||
| </div> | |||||
| <div class='week1color'> | |||||
| <span name='w1n5'>Fri</span> | |||||
| <br> | |||||
| <span class="weekday" name='w1d5'>12</span> | |||||
| </div> | |||||
| <div class='week1color'> | |||||
| <span name='w1n6'>Sat</span> | |||||
| <br> | |||||
| <span class="weekday" name='w1d6'>12</span> | |||||
| </div> | |||||
| <div class='week1color'> | |||||
| <span name='w1n7'>Sun</span> | |||||
| <br> | |||||
| <span class="weekday" name='w1d7'>12</span> | |||||
| </div> | |||||
| </div> | |||||
| <div class='week2'> | |||||
| <div class='week2color'> | |||||
| <span name='w2n1'>Mon</span> | |||||
| <br> | |||||
| <span class="weekday" name='w2d1'>12</span> | |||||
| </div> | |||||
| <div class='week2color'> | |||||
| <span name='w2n2'>Tue</span> | |||||
| <br> | |||||
| <span class="weekday" name='w2d2'>12</span> | |||||
| </div> | |||||
| <div class='week2color'> | |||||
| <span name='w2n3'>Wed</span> | |||||
| <br> | |||||
| <span class="weekday" name='w2d3'>12</span> | |||||
| </div> | |||||
| <div class='week2color'> | |||||
| <span name='w2n4'>Thu</span> | |||||
| <br> | |||||
| <span class="weekday" name='w2d4'>12</span> | |||||
| </div> | |||||
| <div class='week2color'> | |||||
| <span name='w2n5'>Fri</span> | |||||
| <br> | |||||
| <span class="weekday" name='w2d5'>12</span> | |||||
| </div> | |||||
| <div class='week2color'> | |||||
| <span name='w2n6'>Sat</span> | |||||
| <br> | |||||
| <span class="weekday" name='w2d6'>12</span> | |||||
| </div> | |||||
| <div class='week2color'> | |||||
| <span name='w2n7'>Sun</span> | |||||
| <br> | |||||
| <span class="weekday" name='w2d7'>12</span> | |||||
| </div> | |||||
| </div> | |||||
| </div> | |||||
| </div> | |||||
| <div class='prevweek left'> | |||||
| <span class="ticon ticon-arrow-circle-left"></span> | |||||
| </div> | |||||
| <div class='nextweek right'> | |||||
| <span class="ticon ticon-arrow-circle-right"></span> | |||||
| </div> | |||||
| <div class="sheettableheader"> | |||||
| <div class="divTable blueTable"> | |||||
| <div class="divTableHeading"> | |||||
| <div class="divTableRow"> | |||||
| <div class="divTableHead btos">Type of Service</div> | |||||
| <div class="divTableHead bstart">Start</div> | |||||
| <div class="divTableHead bfinish">Finish</div> | |||||
| <div class="divTableHead brate">Hourly Rate</div> | |||||
| <div class="divTableHead bstaff">Staff</div> | |||||
| <div class="divTableHead bclient">Client</div> | |||||
| <div class="divTableHead bconfirmed">Ack</div> | |||||
| <div class="divTableHead brating"> | |||||
| <span class="ticon ticon-star"></span> | |||||
| </div> | |||||
| <div class="divTableHead bedit"> | |||||
| <span class="ticon ticon-edit"></span> | |||||
| </div> | |||||
| <div class="divTableHead bdelete"> | |||||
| <span class="ticon ticon-trash"></span> | |||||
| </div> | |||||
| <div class="divTableHead bsave"> | |||||
| <span class="ticon ticon-search"></span> | |||||
| </div> | |||||
| </div> | |||||
| </div> | |||||
| </div> | |||||
| </div> | |||||
| </div> | |||||
| <div class='workspace'> | |||||
| <img src="#"> | |||||
| </div> | |||||
| <div class='statusbar titlebar_gradient'> | |||||
| <a id='xeroc' href="/xeroc/" target="_blank"> | |||||
| <div class='xero'> | |||||
| <i class="ticon ticon-times"></i> | |||||
| </div> | |||||
| </a> | |||||
| <div class='wifi'> | |||||
| <i class="ticon ticon-times"></i> | |||||
| </div> | |||||
| <a id='ndiscsv' href="/ndiscsv/" target="_blank"> | |||||
| <div class='csv'> | |||||
| <i class="ticon ticon-times"></i> | |||||
| </div> | |||||
| </a> | |||||
| <div class='wages'> | |||||
| $ | |||||
| <div name='number'> | |||||
| 3214 | |||||
| </div> | |||||
| </div> | |||||
| <div class='workinghours'> | |||||
| <label for='woh'> Total Hours</label> | |||||
| <input id="woh" type="text" value="1553.5" readonly> | |||||
| </div> | |||||
| <button name='confirmschedule'> | |||||
| Confirm_Schedule | |||||
| </button> | |||||
| </div> | |||||
| </div> |
| return selector; | return selector; | ||||
| } | } | ||||
| $(document).on('click', 'div.jobTable div.brate.error', function(){ | |||||
| var msg = $(this).attr('title'); | |||||
| if (msg != "") | |||||
| alert(msg); | |||||
| }); | |||||
| $(document).on('click', 'div.divTableHead.bdelete', function(){ | |||||
| add_new_empty_job(); | |||||
| $(document).on('click', 'div.workspace div.bedit span.ticon-edit', function(){ | |||||
| var el = $(this).closest('div.jobTable'); | |||||
| el.addClass('Editing'); | |||||
| var id = el.attr('data-id'); | |||||
| do_edit_job(id); | |||||
| }); | |||||
| $(document).on('click', 'div.bts_editor div.ult-overlay-close', function(){ | |||||
| $('.Editing').addClass('blink_me'); | |||||
| setTimeout(function(){ | |||||
| $(".Editing").removeClass('Editing blink_me'); | |||||
| }, 1000); | |||||
| }); | |||||
| $(document).on('click', 'div.bts_editor div.bsave span.ticon-save', function(){ | |||||
| close_editor(); | |||||
| }); | |||||
| function close_editor(){ | |||||
| $('div.bts_editor div.ult-overlay-close').trigger('click'); | |||||
| } | |||||
| $(document).on('jobEditor:close', 'div.divTable.Editor', function(e,job){ | |||||
| console.log('close_editor event %o', job); | |||||
| }); | |||||
| $(document).on('click', 'div.divTableHead.bdelete span.ticon-trash', function(){ | |||||
| var len = $('div.jobTable.to_be_deleted_duplicate').length; | |||||
| if (len <= 0){ | |||||
| if (confirm("No duplicates to delete, trying to find duplicates?")){ | |||||
| check_duplicate(); | |||||
| } | |||||
| return; | |||||
| }else{ | |||||
| if (!confirm("Delete " + len + " duplicates? ")) | |||||
| return; | |||||
| } | |||||
| var ids = []; | |||||
| $('div.jobTable.to_be_deleted_duplicate').each(function(){ | |||||
| var id = $(this).attr('data-id'); | |||||
| ids.push(id); | |||||
| }); | |||||
| $.post(bts().ajax_url, { // POST request | |||||
| _ajax_nonce: bts().nonce, // nonce | |||||
| action: "delete_jobv1", // action | |||||
| jobs: ids, //delete multiple ids | |||||
| }, function(response, status, xhr){ | |||||
| if (response.status=='success'){ | |||||
| $('div.jobTable.to_be_deleted_duplicate').each(function(){ | |||||
| var id = $(this).attr('data-id'); | |||||
| delete bts().job_map[id]; | |||||
| $(this).get(0).scrollIntoView(); | |||||
| fade_and_delete(this); | |||||
| }); | |||||
| debounced_calculate(); | |||||
| }else{ | |||||
| alert( 'error deleting duplicates:\n\nError:\n\n' + response.error + "\n\n"); | |||||
| } | |||||
| }); | |||||
| }); | }); | ||||
| function fade_and_delete(el) | |||||
| { | |||||
| $(el).fadeOut(300); | |||||
| setTimeout(function(){ | |||||
| $(el).remove(); | |||||
| },300); | |||||
| } | |||||
| function add_new_empty_job(){ | function add_new_empty_job(){ | ||||
| var o = new Job({empty:true}); | var o = new Job({empty:true}); | ||||
| $('div.workspace').append(o.el); | $('div.workspace').append(o.el); | ||||
| newj.mark_highlight_me(1000);//for 1 second; | newj.mark_highlight_me(1000);//for 1 second; | ||||
| dtp_init(); | dtp_init(); | ||||
| }); | }); | ||||
| class Job{ //save data for the record, and display it as GUI | |||||
| class Job{}; | |||||
| class JobEditor{ //save data for the record, and display it as GUI | |||||
| constructor(selector, data){ | constructor(selector, data){ | ||||
| this.el = $(selector); | this.el = $(selector); | ||||
| //this.load_data(data); | |||||
| //this.init_start_rating(); | |||||
| } | |||||
| init_start_rating(){ | |||||
| var self = this; | |||||
| this.el.find("div.brating span").click(function(){ | |||||
| var r = $(this).attr('data-rating'); | |||||
| self.mark_dirty(); | |||||
| self.set_rating(r); | |||||
| }) | |||||
| this.el.find("div.brating").mouseenter(function(){ | |||||
| //change to all hollow star | |||||
| $(this).find('span').html('☆'); | |||||
| }); | |||||
| this.el.find("div.brating").mouseleave(function(){ | |||||
| self.set_rating(self.data.rating); | |||||
| }); | |||||
| this.load_data(data); | |||||
| this.init_event_handler(); | |||||
| } | } | ||||
| load_data(data) | load_data(data) | ||||
| this.mark_week_color(); | this.mark_week_color(); | ||||
| this.validate(); //also triggers mark errors | this.validate(); //also triggers mark errors | ||||
| } | } | ||||
| init_event_handler(){ | |||||
| var self = this; | |||||
| this.el.find("div.btos select").change(function(){ | |||||
| if ( self.validate_tos() ) { | |||||
| self.data.tos = self.get_tos(); | |||||
| } | |||||
| }); | |||||
| this.el.find("div.bstart input").change(function(){ | |||||
| if (self.validate_start()){ | |||||
| self.data.start = self.get_start(); | |||||
| } | |||||
| }); | |||||
| this.el.find("div.bfinish input").change(function(){ | |||||
| if (self.validate_finish()){ | |||||
| self.data.finish = self.get_finish(); | |||||
| } | |||||
| }); | |||||
| this.el.find("div.bstaff select").change(function(){ | |||||
| if (self.validate_staff()){ | |||||
| self.data.staff = self.get_staff(); | |||||
| } | |||||
| }); | |||||
| this.el.find("div.bclient select").change(function(){ | |||||
| if (self.validate_client()){ | |||||
| self.data.client = self.get_client(); | |||||
| } | |||||
| }); | |||||
| this.el.find("div.brate select").change(function(){ | |||||
| if (self.validate_rate()){ | |||||
| self.data.rate = self.get_rate(); | |||||
| } | |||||
| }); | |||||
| this.el.find("div.bconfirmed input").change(function(){ | |||||
| if(self.validate_ack()){ | |||||
| self.data.ack = self.get_ack(); | |||||
| } | |||||
| }); | |||||
| this.el.find("div.brating select").change(function(){ | |||||
| if( self.validate_rating()){ | |||||
| self.data.rating =self.get_rating(); | |||||
| } | |||||
| }); | |||||
| this.el.find("div.bsave span.ticon-save").click(function(e){ | |||||
| if ( self.validate() ){ | |||||
| job_derive_attr(self.data); | |||||
| self.el.trigger('jobEditor:close', self.data); | |||||
| } | |||||
| }); | |||||
| } | |||||
| get_job_id(){ | get_job_id(){ | ||||
| return this.el.find('input[name="id"]').attr('value'); | |||||
| return this.el.attr('data-id'); | |||||
| } | } | ||||
| set_job_id(val){ | set_job_id(val){ | ||||
| if (typeof val == 'undefined' || val == '') | if (typeof val == 'undefined' || val == '') | ||||
| } | } | ||||
| get_tos() | get_tos() | ||||
| { | { | ||||
| this.el.find('div.btos select').children("option:selected").val(); | |||||
| return this.el.find('div.btos select').children("option:selected").val(); | |||||
| } | } | ||||
| set_tos(val) | set_tos(val) | ||||
| { | { | ||||
| if (typeof(val) =="undefined") | if (typeof(val) =="undefined") | ||||
| return; | return; | ||||
| this.el.find('input.tos_name').attr('value', bts().tos[val].tos_full_str); | |||||
| this.el.find('div.btos select option[value="'+val+'"]').prop('selected',true); | |||||
| if ( this.get_tos() != val ){ | |||||
| var o = new Option("(missing:" + this.data.tos +")", this.data.tos); | |||||
| this.el.find('div.btos select').prepend(o); | |||||
| this.el.find('div.btos select option[value="'+this.data.tos+'"]').prop('selected',true); | |||||
| } | |||||
| } | } | ||||
| get_start(){ | get_start(){ | ||||
| return this.el.find('div.bstart').html(); | |||||
| return this.el.find('div.bstart input').attr('value'); | |||||
| } | } | ||||
| set_start(val) | set_start(val) | ||||
| { | { | ||||
| this.el.find('div.bstart').html(val); | |||||
| if (typeof(val) =="undefined") | |||||
| return; | |||||
| this.el.find('div.bstart input').attr('value', val); | |||||
| } | } | ||||
| get_finish() | get_finish() | ||||
| { | { | ||||
| return this.el.find('div.bfinish').html(); | |||||
| return this.el.find('div.bfinish input').attr('value'); | |||||
| } | } | ||||
| set_finish(val) | set_finish(val) | ||||
| { | { | ||||
| if (typeof(val) == "undefined") | if (typeof(val) == "undefined") | ||||
| return; | return; | ||||
| this.el.find('div.bfinish').html(val); | |||||
| if (typeof(val) == "undefined") | |||||
| return; | |||||
| this.el.find('div.bfinish input').attr('value', val); | |||||
| } | } | ||||
| get_rate() | get_rate() | ||||
| { | { | ||||
| return this.el.find('div.brate').children("option:selected").val(); | |||||
| return this.el.find('div.brate select').children("option:selected").val(); | |||||
| } | } | ||||
| set_rate(val) | set_rate(val) | ||||
| { | { | ||||
| if (typeof(val) =="undefined") | if (typeof(val) =="undefined") | ||||
| return; | return; | ||||
| this.el.find('div.bstaff select option[value="'+val+'"]').prop('selected',true); | this.el.find('div.bstaff select option[value="'+val+'"]').prop('selected',true); | ||||
| if ( this.get_staff() != val ){ | |||||
| var o = new Option("(missing:" + this.data.staff +")", this.data.staff); | |||||
| this.el.find('div.bstaff select').prepend(o); | |||||
| this.set_err_msg_tos('missing' + this.data.staff); | |||||
| this.el.find('div.bstaff select option[value="'+this.data.staff+'"]').prop('selected',true); | |||||
| } | |||||
| } | } | ||||
| get_client() | get_client() | ||||
| { | { | ||||
| } | } | ||||
| get_ack() | get_ack() | ||||
| { | { | ||||
| return this.el.find('div.bconfirmed input:checked').length > 0; | |||||
| return this.el.find('div.bconfirmed input:checked').length > 0? 1:0; | |||||
| } | } | ||||
| set_ack(val) | set_ack(val) | ||||
| { | { | ||||
| return this.el.find('div.bconfirmed input').prop('checked', val!=0); | return this.el.find('div.bconfirmed input').prop('checked', val!=0); | ||||
| } | } | ||||
| get_rating(){ | get_rating(){ | ||||
| var count =0; | |||||
| this.el.find('div.brating span').each(function(i,e){ | |||||
| if ($(e).html()=='★') | |||||
| count +=1; | |||||
| }); | |||||
| return count; | |||||
| return this.el.find('div.brating select').children("option:selected").val(); | |||||
| } | } | ||||
| set_rating(num){ | set_rating(num){ | ||||
| if (!(1 <= num && num <=5)) | |||||
| if (!(0 <= num && num <=5)) | |||||
| return; | return; | ||||
| this.el.find('div.brating span').each(function(i,e){ | |||||
| var rating = $(e).attr('data-rating'); | |||||
| var rating = parseInt(rating); | |||||
| if (rating <= num) | |||||
| $(e).html('★'); | |||||
| else | |||||
| $(e).html('☆'); | |||||
| }); | |||||
| this.el.find('div.brating select option[value="'+num+'"]').prop('selected',true); | |||||
| } | } | ||||
| get_record_from_ui(){ | get_record_from_ui(){ | ||||
| validate() | validate() | ||||
| { | { | ||||
| var ok_time = this.validate_start() && | |||||
| this.validate_finish(); //finish might not be executed, if start is wrong | |||||
| var ok_tos = this.validate_tos(); //make sure this validate is executed; | |||||
| var ok_tos = this.validate_tos(); | |||||
| var ok_time = this.validate_start() && this.validate_finish(); //finish might not be executed, if start is wrong | |||||
| var ok_staff = this.validate_staff(); | |||||
| var ok_client = this.validate_client(); | |||||
| var ok_rate = this.validate_rate() ; //make sure this validate is executed | var ok_rate = this.validate_rate() ; //make sure this validate is executed | ||||
| var ok = ok_time && ok_tos && ok_rate; | |||||
| var ok = ok_tos && ok_time && ok_staff && ok_client && ok_rate; | |||||
| if (ok){ | if (ok){ | ||||
| this.el.removeClass('invalidjob'); | this.el.removeClass('invalidjob'); | ||||
| }else{ | }else{ | ||||
| } | } | ||||
| validate_tos(){ | validate_tos(){ | ||||
| // if (this.get_tos() != this.data.tos){ | |||||
| // this.set_err_msg_tos('require NDIS ' + this.data.tos); | |||||
| // this.mark_tos_invalid(); | |||||
| // this.mark_dirty(); | |||||
| // console.log('tos mark dirty'); | |||||
| // return false; | |||||
| // } | |||||
| this.set_err_msg_tos(''); | |||||
| this.mark_tos_valid(); | |||||
| if ( typeof bts().tos[this.get_tos()] == 'undefined') { | |||||
| this.set_err_msg_tos('missing ' + this.get_tos()); | |||||
| return false; | |||||
| }else{ | |||||
| this.set_err_msg_tos(''); | |||||
| return true; | |||||
| } | |||||
| } | |||||
| validate_staff(){ | |||||
| if ( typeof bts().staff_map[this.get_staff()] == 'undefined') { | |||||
| this.set_err_msg_staff('missing ' + this.get_staff()); | |||||
| return false; | |||||
| }else{ | |||||
| this.set_err_msg_staff(''); | |||||
| return true; | |||||
| } | |||||
| } | |||||
| validate_client(){ | |||||
| return true; | |||||
| } | |||||
| validate_rating(){ | |||||
| return true; | return true; | ||||
| } | } | ||||
| { | { | ||||
| this.el.find('div.bfinish_err').html(str); | this.el.find('div.bfinish_err').html(str); | ||||
| } | } | ||||
| set_err_msg_staff(str) | |||||
| { | |||||
| this.el.find('div.bstaff_err').html(str); | |||||
| } | |||||
| set_err_msg_client(str) | |||||
| { | |||||
| this.el.find('div.bclient_err').html(str); | |||||
| } | |||||
| set_err_msg_rate(str) | set_err_msg_rate(str) | ||||
| { | { | ||||
| this.el.find('div.brate_err').html(str); | this.el.find('div.brate_err').html(str); | ||||
| $(s).trigger('click'); | $(s).trigger('click'); | ||||
| } | } | ||||
| function set_modal_data(selector, data){ | |||||
| var s = 'div.bts_'+ selector; | |||||
| $(s).data(data); | |||||
| } | |||||
| function get_modal_data(selector, data){ | |||||
| var s = 'div.bts_'+ selector; | |||||
| $(s).data(); | |||||
| } | |||||
| // setTimeout(function(){ | // setTimeout(function(){ | ||||
| // set_modal_title('warning', 'suck title'); | // set_modal_title('warning', 'suck title'); | ||||
| // set_modal_content('warning', 'fucking details'); | // set_modal_content('warning', 'fucking details'); | ||||
| function job_derive_attr(e) | function job_derive_attr(e) | ||||
| { | { | ||||
| clear_non_derive_attr(e); | |||||
| e.saved = true; | e.saved = true; | ||||
| e.tos_name = bts().tos[e.tos].tos_full_str; | |||||
| e.staff_name = bts().staff_map[e.staff].display_name; | |||||
| if (typeof bts().tos[e.tos] != 'undefined'){ | |||||
| e.tos_name = bts().tos[e.tos].tos_full_str; | |||||
| }else{ | |||||
| e.tos_name = "(deleted) "; | |||||
| e.tos_err="Missing: " + e.tos; | |||||
| } | |||||
| if (typeof bts().staff_map[e.staff] != 'undefined'){ | |||||
| e.staff_name = bts().staff_map[e.staff].display_name; | |||||
| }else{ | |||||
| e.staff_name = "(deleted) "; | |||||
| e.staff_err="Missing: " + e.staff; | |||||
| } | |||||
| e.client_name = bts().client_map[e.client].display_name; | e.client_name = bts().client_map[e.client].display_name; | ||||
| e.rate_name = bts().earnings_rate[e.rate].RatePerUnit + "-" + bts().earnings_rate[e.rate].Name; | e.rate_name = bts().earnings_rate[e.rate].RatePerUnit + "-" + bts().earnings_rate[e.rate].Name; | ||||
| if (! has_txt_hour( bts().earnings_rate[e.rate].TypeOfUnits )){ | if (! has_txt_hour( bts().earnings_rate[e.rate].TypeOfUnits )){ | ||||
| e.non_hour = true; | |||||
| e.brate_err = "Rate type is not Hours - Not allowed"; | |||||
| e.rate_non_hour = true; | |||||
| e.rate_err = `Rate unit must be ⟦ Hours ⟧ | |||||
| Possible solution: | |||||
| 1. Change it in Xero | |||||
| 2. Delete this job`; | |||||
| } | } | ||||
| if (job_is_week1(e.start)){ | if (job_is_week1(e.start)){ | ||||
| e.is_confirmed = true; | e.is_confirmed = true; | ||||
| } | } | ||||
| } | } | ||||
| function clear_non_derive_attr(e) | |||||
| { | |||||
| delete e.saved; | |||||
| delete e.tos_name; | |||||
| delete e.tos_err; | |||||
| delete e.staff_name; | |||||
| delete e.staff_err; | |||||
| delete e.client_name; | |||||
| delete e.client_err; | |||||
| delete e.rate_name; | |||||
| delete e.rate_err; | |||||
| delete e.rate_non_hour; | |||||
| delete e.is_week1; | |||||
| delete e.is_week2; | |||||
| delete e.is_confirmed; | |||||
| } | |||||
| function has_txt_hour(str){ | function has_txt_hour(str){ | ||||
| var s = str.toLowerCase(); | var s = str.toLowerCase(); | ||||
| function check_duplicate() | function check_duplicate() | ||||
| { | { | ||||
| var count= 0; | |||||
| var to_be_delete=[]; | |||||
| var to_be_deleted=[]; | |||||
| //loop through jobs | //loop through jobs | ||||
| for(var id1 in bts().job_map){ | for(var id1 in bts().job_map){ | ||||
| var job1 = bts().job_map[id1]; | var job1 = bts().job_map[id1]; | ||||
| if (is_same_job(job1,job2)){ | if (is_same_job(job1,job2)){ | ||||
| job2.parent = job1.id; | job2.parent = job1.id; | ||||
| job1.duplicates[id2] = job2; | job1.duplicates[id2] = job2; | ||||
| console.warn("found: %s = %s", job1.id, job2.id); | |||||
| count++; | |||||
| to_be_delete.push(id2); | |||||
| //console.warn("found: %s = %s", job1.id, job2.id); | |||||
| to_be_deleted.push(id2); | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| console.log('all-done, found %d duplicates: %o', count, to_be_delete); | |||||
| if (to_be_deleted.length == 0){ | |||||
| alert("No duplicate found!"); | |||||
| return; | |||||
| } | |||||
| bts().to_be_deleted_duplicate = to_be_deleted; | |||||
| //console.log('all-done, found %d duplicates: %o', to_be_deleted.length, to_be_deleted); | |||||
| mark_duplicate(to_be_deleted); | |||||
| } | } | ||||
| $('div.wages').click(check_duplicate); | |||||
| function is_same_job(job1, job2) | function is_same_job(job1, job2) | ||||
| { | { | ||||
| if ( (job1.tos == job2.tos) && | if ( (job1.tos == job2.tos) && | ||||
| } | } | ||||
| return false; | return false; | ||||
| } | } | ||||
| function mark_duplicate(ids) | |||||
| { | |||||
| ids.forEach(function(id){ | |||||
| var selector = '#job_' +id; | |||||
| $(selector).get(0).scrollIntoView(); | |||||
| $(selector).addClass('to_be_deleted_duplicate'); | |||||
| }); | |||||
| } | |||||
| function do_edit_job(id) | |||||
| { | |||||
| open_modal('editor'); | |||||
| set_modal_title('editor', "Editing Job: " + id); | |||||
| //make a copy of the job | |||||
| var job_copy = $.extend({}, bts().job_map[id]); | |||||
| job_copy.editorid = Math.floor(Math.random() * Math.floor(99999)); // a random number; | |||||
| //set_modal_data('editor', {jobid: id, job_copy:job_copy}); | |||||
| var html = $('#jobv1_editor').html(); | |||||
| html = Mustache.render(html, job_copy); | |||||
| set_modal_content('editor', html); | |||||
| //update GUI | |||||
| dtp_init(); | |||||
| //init editor | |||||
| new JobEditor('#editor_' + job_copy.editorid, job_copy); | |||||
| } | |||||
| $( ".boundary_datepicker" ).datepicker(); | $( ".boundary_datepicker" ).datepicker(); | ||||
| $( ".boundary_datepicker" ).datepicker("option", "dateFormat", "yy-mm-dd"); | $( ".boundary_datepicker" ).datepicker("option", "dateFormat", "yy-mm-dd"); | ||||
| init_ts(); | init_ts(); | ||||
| $('div.divTableHeading div.bsave span.ticon-search').click(do_test); | |||||
| function do_test(){ | |||||
| open_modal('editor'); | |||||
| set_modal_title('editor', "title"); | |||||
| set_modal_content('editor', $('div.workspace').html()); | |||||
| } | |||||
| /*________________________________________________________________________*/ | /*________________________________________________________________________*/ | ||||
| }); | }); | ||||
| jQuery('button.peoplelist[name="up"]').mousedown(function(){ | jQuery('button.peoplelist[name="up"]').mousedown(function(){ | ||||
| var button = this; | var button = this; | ||||
| timeoutid = setInterval(function(){ | timeoutid = setInterval(function(){ | ||||
| //console.log("up scrotop %d ", jQuery(button).parent().find(".userlist").get(0).scrollTop ); | |||||
| //console.log("up scrotop %d ",jQuery(button).parent().find(".userlist").get(0).scrollTop ); | |||||
| jQuery(button).parent().find(".userlist").get(0).scrollTop -=240; | jQuery(button).parent().find(".userlist").get(0).scrollTop -=240; | ||||
| }, 100); | }, 100); | ||||
| }).on('mouseup mouseleave', function(){ | }).on('mouseup mouseleave', function(){ |