1// cache: 2026-10-05 04:14:54 2 3if (typeof moment !== 'undefined') { 4 moment.defaultFormat = "YYYY-MM-DD HH:mm:ss"; 5 moment.locale('th'); 6} 7if (typeof Vue !== 'undefined') { 8 Vue.filter('num', v=>intToNum(v)); 9 Vue.filter('money', v=>intToMoney(v)); 10 Vue.directive('select2', { 11 twoWay: true, 12 bind: function(el, binding, vnode) { 13 let attr = vnode.data.attrs; 14 Vue.nextTick(()=>{ 15 $(el) 16 .select2(attr.options) 17 .on('select2:select', e=> { 18 let data = e.params.data.id; 19 vueDirectiveModel(vnode, data); 20 _.set(vnode.model) 21 attr.model = data; 22 }) 23 .on('select2:unselecting', e=> { 24 vueDirectiveModel(vnode, ''); 25 }).trigger('change') 26 ; 27 }); 28 }, 29 update: function(el, binding, vnode) { 30 Vue.nextTick(()=> { 31 $(el).trigger('change'); 32 }); 33 }, 34 unbind: function(el) { 35 $(el).off().select2('destroy'); 36 } 37 }); 38} 39_.move = function (array, from, to) { 40 return array.splice(to, 0, array.splice(from, 1)[0]); 41}; 42 43 44function intToMoney(num) { 45 if(num === null || isNaN(num) || (!num && num != 0)) return 'รà¸à¸à¸£à¸±à¸à¸¢à¸à¸' + '...'; 46 return Number(num).toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 }) 47} 48function intToNum(num) { 49 if(num === null || isNaN(num) || (!num && num != 0)) return 'à¸à¸³à¸¥à¸±à¸à¹à¸«à¸¥à¸' + '...'; 50 return Number(num).toLocaleString(); 51} 52function swapPositive(num) { 53 return num == 0 ? num : -num; 54} 55function pad0(num, toString = true) { 56 return num<0?'00':num<10?'0'+num:(toString?num.toString():num); 57} 58 59async function post(url, data) { 60 let r = await fetch(url, {method: 'POST', headers: {'content-type': 'application/json'}, body: JSON.stringify(data)}); 61 try { 62 return r.json(); 63 } catch (e) { 64 return {success: false, code: e.code, data: e.message}; 65 } 66} 67 68async function _get(url) { 69 let r = await fetch(url, {method: 'GET', headers: {'content-type': 'application/json'}}); 70 let contentType = r.headers.get('content-type'); 71 if (contentType && contentType.includes('application/json')) { 72 try { 73 return await r.json(); 74 } catch (e) { 75 return {success: false, code: e.code, data: e.message}; 76 } 77 } else { 78 // à¸à¸£à¸à¸µà¸à¸µà¹à¹à¸¡à¹à¹à¸à¹à¸£à¸±à¸ JSON à¸à¸¥à¸±à¸à¸¡à¸² 79 let text = await r.text(); // รัà¸à¸à¹à¸à¸¡à¸¹à¸¥à¹à¸à¹à¸à¸à¹à¸à¸à¸§à¸²à¸¡ 80 // console.error('Received non-JSON response:', text); 81 // return {success: false, code: 'INVALID_JSON', data: text}; 82 } 83} 84 85function sleep(ms) { 86 return new Promise(resolve => setTimeout(resolve, ms)); 87} 88 89function bytesToSize(bytes) { 90 var sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB']; 91 if (bytes == 0) return '0 Byte'; 92 var i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024))); 93 return Math.round(bytes / Math.pow(1024, i), 2) + ' ' + sizes[i]; 94} 95function fileToBase64(file) { 96 return new Promise((resolve) => { 97 const reader = new FileReader(); 98 try { 99 reader.readAsDataURL(file); 100 reader.onload = () => resolve(reader.result); 101 reader.onerror = error => resolve(false); 102 } catch (e) { 103 resolve(false) 104 } 105 }); 106} 107window.modal = { 108 info(msg, title = 'à¹à¸à¹à¸à¹à¸à¸·à¸à¸') { 109 return Swal.fire({title, html: msg, icon: 'info', allowOutsideClick: false}); 110 }, 111 message(msg, title) { 112 return Swal.fire({title, html: msg, allowOutsideClick: false}); 113 }, 114 success(msg, title = 'สำà¹à¸£à¹à¸', opt = {}) { 115 let op = _.merge({title, html: msg, icon: 'success', allowOutsideClick: false}, opt); 116 return Swal.fire(op); 117 }, 118 error(msg, title = 'à¸à¸´à¸à¸à¸¥à¸²à¸') { 119 return Swal.fire({title, html: msg, icon: 'error', allowOutsideClick: false}); 120 }, 121 confirm(msg, title = 'ยืà¸à¸¢à¸±à¸', option) { 122 let opt = { 123 title, 124 html: msg, 125 icon: 'warning', 126 showCancelButton: true, 127 allowOutsideClick: false, 128 reverseButtons: true // สลัà¸à¸à¸³à¹à¸«à¸à¹à¸à¸à¸à¸à¸à¸¸à¹à¸¡ 129 }; 130 131 return new Promise(resolve => { 132 Swal.fire(_.merge(opt, option)).then(r=>{ 133 resolve(r.isConfirmed ? (r.value ?? true) : false); 134 }) 135 }); 136 137 }, 138 confirmLoading(msg, title = 'ยืà¸à¸¢à¸±à¸', option) { 139 let opt = { 140 title, 141 html: msg, 142 icon: 'warning', 143 showCancelButton: true, 144 allowOutsideClick: false, 145 showLoaderOnConfirm: true, 146 }; 147 148 return new Promise(resolve => { 149 Swal.fire(_.merge(opt, option)).then(r=>{ 150 resolve(r.isConfirmed ? (r.value ?? true) : false); 151 }) 152 }); 153 }, 154 preConfirmLoading(msg, title = 'ยืà¸à¸¢à¸±à¸', option = {}){ 155 const base = { 156 title, html: msg, icon: 'warning', 157 showCancelButton: true, 158 allowOutsideClick: () => !Swal.isLoading(), 159 showLoaderOnConfirm: true, 160 preConfirm: option.preConfirm || (async () => true) 161 }; 162 163 return Swal.fire(_.merge(base, _.omit(option, ['preConfirm']))).then(r => r.isConfirmed); 164 } 165}; 166function nl2br(str, is_xhtml) { 167 if (typeof str === 'undefined' || str === null) { 168 return ''; 169 } 170 var breakTag = (is_xhtml || typeof is_xhtml === 'undefined') ? '<br/>' : '<br>'; 171 return (str + '').replace(/([^>\r\n]?)(\r\n|\n\r|\r|\n)/g, '$1' + breakTag + '$2'); 172} 173window.humantime = { 174 full_th: function (datetime, with_weekday, format = false) { 175 var mm = moment(datetime, format || 'YYYY-MM-DD HH:mm:ss'); 176 return mm.locale('th').format((with_weekday?'dddd ':'')+'D MMMM')+' '+(parseInt(moment(datetime, format || 'YYYY-MM-DD HH:mm:ss').locale('th').format('YYYY'))+543); 177 }, 178 timeago: function (datetime, bracket, format) { 179 var mm = moment(datetime, format || 'YYYY-MM-DD HH:mm:ss'); 180 return (bracket ? '(':'') +mm.fromNow() + (bracket ? ')':''); 181 }, 182 time_with_ago: function (datetime, time_ago = true, format) { 183 var mm = moment(datetime, format || 'YYYY-MM-DD HH:mm:ss'); 184 return mm.format('DD/MM/YYYY HH:mm:ss') + (time_ago ? ' ('+mm.fromNow()+')' : ''); 185 }, 186 weekday: function () { 187 188 }, 189 clock: function (datetime, with_second, format) { 190 var mm = moment(datetime, format || 'YYYY-MM-DD HH:mm:ss'); 191 return mm.format('HH:mm'+(with_second?':ss':'')); 192 }, 193 isToday: function (datetime, format) { 194 var mm = moment(datetime, format || 'YYYY-MM-DD HH:mm:ss'); 195 return mm.isSame(moment(), 'day'); 196 }, 197 getTimeRemaining(endtime, string = true){ 198 const total = Date.parse(endtime) - Date.parse(new Date()); 199 const s = Math.floor( (total/1000) % 60 ); 200 const m = Math.floor( (total/1000/60) % 60 ); 201 const h = Math.floor( (total/(1000*60*60)) % 24 ); 202 const d = Math.floor( total/(1000*60*60*24) ); 203 204 return { 205 total, 206 day: d || 0, 207 hour: (h < 10 ? '0' : '') + h || 0, 208 minute: (m < 10 ? '0' : '') + m || 0, 209 second: (s < 10 ? '0' : '') + s || 0, 210 }; 211 } 212}; 213 214window.func = { 215 genPaginate({el = '#pagination', list } = {}, cb) { 216 $.jqPaginator(el, { 217 wrapper: '', 218 first: '<li class="first page-item"><a class="page-link" href="javascript:;">«</a></li>', 219 prev: '<li class="prev page-item"><a class="page-link" href="javascript:;"><</a></li>', 220 next: '<li class="next page-item"><a class="page-link" href="javascript:;">></a></li>', 221 last: '<li class="last page-item"><a class="page-link" href="javascript:;">»</a></li>', 222 page: '<li class="page page-item"><a class="page-link" href="javascript:;">{{page}}</a></li>', 223 totalPages: +list.totalPages || Math.floor(+list.totalRecords / +list.length) || 0, 224 totalCounts: +list.totalRecords || +list.recordsTotal || 0, 225 pageSize: +list.length, 226 currentPage: +list.page, 227 visiblePages: 7, 228 onPageChange: (page, type)=> { 229 if (type !== 'change') return; //prevent loop 230 //$this.paging.page = page; 231 if (typeof cb === 'function') cb(page); 232 } 233 }); 234 }, 235}; 236function vueDirectiveModel(vnode, setVal) { 237 let model = vnode.data.directives.find(o => o.name === 'model'); 238 if (!model) return null; 239 return _.set(vnode.context, model.expression, setVal); 240} 241 242window.toast = { 243 secondary(msg, title = 'à¹à¸à¹à¸à¹à¸à¸·à¸à¸', opt) { 244 iziToast.show(_.merge({ 245 title, message: msg, 246 icon: 'fa fa-info-circle' 247 }, opt)); 248 }, 249 info(msg, title = 'à¹à¸à¹à¸', opt) { 250 iziToast.show(_.merge({ 251 color: 'blue', 252 layout: 2, 253 position: 'topRight', 254 title, message: msg, 255 icon: 'fa fa-info-circle' 256 }, opt)); 257 }, 258 success(msg, title = 'สำà¹à¸£à¹à¸', opt) { 259 iziToast.show(_.merge({ 260 color: 'green', 261 layout: 2, 262 position: 'topRight', 263 title, message: msg, 264 icon: 'fa fa-check-circle' 265 }, opt)); 266 }, 267 warning(msg, title = 'à¹à¸à¹à¸à¹à¸à¸·à¸à¸', opt) { 268 iziToast.show(_.merge({ 269 color: 'yellow', 270 layout: 2, 271 position: 'topRight', 272 title, message: msg, 273 icon: 'fa fa-exclamation-circle' 274 }, opt)); 275 }, 276 error(msg, title = 'à¸à¸´à¸à¸à¸¥à¸²à¸', opt) { 277 iziToast.show(_.merge({ 278 color: 'red', 279 layout: 2, 280 position: 'topRight', 281 resetOnHover: true, 282 title, message: msg, 283 icon: 'fa fa-times-circle' 284 }, opt)); 285 }, 286 chat(msg, title = 'à¹à¸à¸', opt = {}) { 287 iziToast.show(_.merge({ 288 color: 'blue', 289 layout: 2, 290 // icon: 'fa fa-comment', 291 image: 'https://image.flaticon.com/icons/png/512/149/149071.png', 292 position: 'topCenter', 293 closeOnClick: true, 294 // buttons: [ 295 // ['<button>à¸à¸à¸</button>', function (instance, toast) { 296 // alert("Hello world!"); 297 // }, true] 298 // ], 299 balloon: true, 300 resetOnHover: true, 301 title, message: msg 302 }, opt)); 303 }, 304 primary(msg, from, image = null, color = 'yellow', btnSets = null) { 305 iziToast.show({ 306 color, 307 layout: 2, 308 // icon: 'fa fa-comment', 309 image: image || 'https://image.flaticon.com/icons/png/512/149/149071.png', 310 position: 'topRight', 311 buttons: btnSets, 312 resetOnHover: true, 313 title: from, message: msg 314 }); 315 }, 316}; 317 318let component_option = { 319 datepicker_option: { 320 default: { 321 opens: 'left', 322 showDropdowns: true, 323 timePicker: true, 324 timePicker24Hour: true, 325 alwaysShowCalendars: true, 326 locale: {}, 327 maxYear: moment(), 328 endDate: moment(), 329 ranges: { 330 'วัà¸à¸à¸µà¹': [moment().startOf('day'), moment().endOf('day')], 331 'à¹à¸¡à¸·à¹à¸à¸§à¸²à¸': [moment().subtract(1, 'days').startOf('day'), moment().subtract(1, 'days').endOf('day')], 332 'à¸à¸²à¸à¸´à¸à¸¢à¹à¸à¸µà¹ (à¸à¸².-ส.)': [moment().startOf('week'), moment().endOf('week')], 333 '7 วัà¸à¸¥à¹à¸²à¸ªà¸¸à¸': [moment().subtract(6, 'days').startOf('day'), moment().endOf('day')], 334 '30 วัà¸à¸¥à¹à¸²à¸ªà¸¸à¸': [moment().subtract(29, 'days').startOf('day'), moment().endOf('day')], 335 'à¹à¸à¸·à¸à¸à¸à¸µà¹': [moment().startOf('month').startOf('day'), moment().endOf('month').endOf('day')], 336 'à¹à¸à¸·à¸à¸à¸à¹à¸à¸': [moment().subtract(1, 'month').startOf('month').startOf('day'), moment().subtract(1, 'month').endOf('month').endOf('day')] 337 }, 338 // showCustomRangeLabel: 'à¸à¸³à¸«à¸à¸à¹à¸à¸', 339 }, 340 single_date: { 341 singleDatePicker: true, 342 showDropdowns: true, 343 // minYear: 1901, 344 // maxYear: parseInt(moment().format('YYYY'),10), 345 locale: { 346 format: 'YYYY-MM-DD' 347 }, 348 autoUpdateInput: false, 349 }, 350 range_no_time: { 351 opens: 'left', 352 showDropdowns: true, 353 timePicker: false, 354 alwaysShowCalendars: true, 355 locale: { 356 format: 'YYYY-MM-DD' 357 }, 358 maxYear: moment(), 359 endDate: moment(), 360 ranges: { 361 'วัà¸à¸à¸µà¹': [moment().startOf('day'), moment().endOf('day')], 362 'à¹à¸¡à¸·à¹à¸à¸§à¸²à¸': [moment().subtract(1, 'days').startOf('day'), moment().subtract(1, 'days').endOf('day')], 363 'à¸à¸²à¸à¸´à¸à¸¢à¹à¸à¸µà¹ (à¸à¸².-ส.)': [moment().startOf('week'), moment().endOf('week')], 364 '7 วัà¸à¸¥à¹à¸²à¸ªà¸¸à¸': [moment().subtract(6, 'days').startOf('day'), moment().endOf('day')], 365 '30 วัà¸à¸¥à¹à¸²à¸ªà¸¸à¸': [moment().subtract(29, 'days').startOf('day'), moment().endOf('day')], 366 'à¹à¸à¸·à¸à¸à¸à¸µà¹': [moment().startOf('month').startOf('day'), moment().endOf('month').endOf('day')], 367 'à¹à¸à¸·à¸à¸à¸à¹à¸à¸': [moment().subtract(1, 'month').startOf('month').startOf('day'), moment().subtract(1, 'month').endOf('month').endOf('day')] 368 }, 369 // showCustomRangeLabel: 'à¸à¸³à¸«à¸à¸à¹à¸à¸', 370 } 371 }, 372};
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.