diff --git a/assets/css/bootstrap/bootstrap.css b/assets/css/bootstrap/bootstrap.css index 2ad3f05..aad7e82 100644 --- a/assets/css/bootstrap/bootstrap.css +++ b/assets/css/bootstrap/bootstrap.css @@ -1882,7 +1882,7 @@ progress { .table > :not(caption) > * > * { padding: 0.5rem 0.5rem; color: var(--bs-table-color-state, var(--bs-table-color-type, var(--bs-table-color))); - background-color: var(--bs-table-bg); + /*background-color: var(--bs-table-bg);*/ border-bottom-width: var(--bs-border-width); box-shadow: inset 0 0 0 9999px var(--bs-table-bg-state, var(--bs-table-bg-type, var(--bs-table-accent-bg))); } diff --git a/assets/css/datatables/stateRestore.bootstrap5.css b/assets/css/datatables/_stateRestore.bootstrap5.css similarity index 100% rename from assets/css/datatables/stateRestore.bootstrap5.css rename to assets/css/datatables/_stateRestore.bootstrap5.css diff --git a/assets/css/default.css b/assets/css/default.css index 39f3682..341ae53 100644 --- a/assets/css/default.css +++ b/assets/css/default.css @@ -4,7 +4,7 @@ Desc. : CSS Default Configuration Created By : Siau Pheng (siaupheng@3fonia.com). Created Date : December 20th, 2007. - Last Modified : February 7th, 2026. + Last Modified : September 27th, 2026. (c) 3FONIA Software; WWW.3FONIA.COM. @@ -343,6 +343,14 @@ ul.dtr-details li.hidden { visibility: hidden !important; display: none !importa cursor: pointer; } +.bootstrap-autocomplete.dropdown-menu .dropdown-item.active .text-primary { + color: #93f6c5 !important; +} + +.bootstrap-autocomplete.dropdown-menu .dropdown-item.active .text-danger { + color: #f4c8d2 !important; +} + /******************************** text field ********************************/ input.double, input.integer, input.number { diff --git a/assets/js/bootstrap/bootstrap.autocomplete.js b/assets/js/bootstrap/bootstrap.autocomplete.js index 22ef21f..6c8114f 100644 --- a/assets/js/bootstrap/bootstrap.autocomplete.js +++ b/assets/js/bootstrap/bootstrap.autocomplete.js @@ -39,7 +39,7 @@ var AjaxResolver = (function (_super) { url: '', method: 'post', queryKey: 'Auto_Query', - extraData: {}, + param: [], timeout: 0, requestThrottling: 500 }; @@ -51,7 +51,7 @@ var AjaxResolver = (function (_super) { } var data = {}; data[this._settings.queryKey] = q; - $.extend(data, this._settings.extraData); + if (this._settings.param.length > 0) $.extend(data, FoniaJS.RequestParam(this._settings.param)); if (this.requestTID) { window.clearTimeout(this.requestTID); } @@ -97,13 +97,12 @@ var DropdownV5 = (function () { DropdownV5.prototype.init = function () { var _this = this; var pos = this.getElPos(); + var fontsize = _this._$el.css('font-size'); this._dd = $('
'); this._dd.addClass('bootstrap-autocomplete dropdown-menu'); this._dd.insertAfter(this._$el); - this._dd.css({ top: pos.top + this._$el.outerHeight(), left: pos.left, width: this._$el.outerWidth() }); + this._dd.css({ top: pos.top + this._$el.outerHeight(), left: pos.left, width: this._$el.outerWidth(), 'font-size': fontsize }); this._dd.on('click', '.dropdown-item', function (evt) { - //console.log('clicked', evt.currentTarget); - //console.log($(evt.currentTarget)); var item = $(evt.currentTarget).data('item'); _this.itemSelectedLaunchEvent(item); evt.preventDefault(); @@ -239,8 +238,7 @@ var DropdownV5 = (function () { itemText = _this.showMatchedText(itemFormatted.text, _this.searchText); if (itemFormatted.html !== undefined) { itemHtml = itemFormatted.html; - } - else { + } else { itemHtml = itemText; } var disabledItem = itemFormatted.disabled; diff --git a/assets/js/export.js b/assets/js/export.js index d2a104a..7a5ed35 100644 --- a/assets/js/export.js +++ b/assets/js/export.js @@ -38,7 +38,7 @@ var cEXPORT = function(url, options){ return false; } var _pro = (window.location.protocol=='https:') ? 'https://' : 'http://'; - var _src = _pro+FoniaJS.WEB_HOST + _options.url + '?' + (FoniaJS.RequestParam(_params)).join('&'); + var _src = _pro+FoniaJS.WEB_HOST + _options.url + '?' + $.param(FoniaJS.RequestParam(_params)); try { const response = await fetch(_src) diff --git a/assets/js/fonia3.js b/assets/js/fonia3.js index 7ef166f..43992de 100644 --- a/assets/js/fonia3.js +++ b/assets/js/fonia3.js @@ -4,7 +4,7 @@ Desc. : JS - Fonia Custom Class v3 Created By : Siau Pheng (siaupheng@3fonia.com). Created Date : June 19th, 2009. - Last Modified : September 4th, 2026. + Last Modified : September 28th, 2026. (c) 3FONIA Software; WWW.3FONIA.COM. @@ -157,7 +157,7 @@ var FoniaJS = { var _buover = (buserover == null) ? false : buserover; var _tsid = parseInt(Math.random() * 99999999); var _ceksuper = null; - var _isi = new String('
Username
Password

'+this.locale("Fonia.auth_wait_msg")+'


'); + var _isi = new String('
Username
Password

'+this.locale("Fonia.auth_wait_msg")+'


'); this.winSAuth = this.showWindow('SAuth', ((this.AUTH_LEVEL < 9 && _bsuper == true) ? this.locale("Fonia.auth_super") : this.locale("Fonia.auth_user")), _isi, 200, '', () => { $('#butSOK').click(() => { $('#butSOK').prop('disabled', true); @@ -242,10 +242,10 @@ var FoniaJS = { if (!menu) return ''; var smenu = ''; if (typeof menu === 'object'){ - var ma = ' me-sm-2'; smenu = '
'; + var ma = ' me-sm-2'; smenu = '
'; $(menu).each((i, atom) => { if (Object.keys(atom).length === 0) { - smenu += '
'; + smenu += '
'; ma = ' ms-sm-2'; } else { if (atom.i == 'butTutup') { atom.v='Tutup', atom.c='danger', atom.d='' }; @@ -286,18 +286,29 @@ var FoniaJS = { FormDecorated: function() { $('input.form-control[class*=integer], input.form-control[class*=angka]').each((i, el) => { const elm = $(el); - elm.on('keypress keyup blur paste', (e) => { + if ((elm.attr('o3') ?? '') !== '') return; + elm.attr('o3', '1'); + elm.on('keypress keyup paste', (e) => { elm.val(elm.val().replace(/[^\d].+/, "")); if ((e.which < 48 || e.which > 57)) e.preventDefault(); }); }); $('input.form-control[class*=double]').each((i, el) => { const elm = $(el); - elm.on('keypress keyup blur paste', (e) => { - elm.val(elm.val().replace(/[^0-9\.]/g,'')); - if (e.type === 'blur') elm.val( FoniaJS.FloatToStr(elm.val(), 2) ); - if ((e.which != 46 || elm.val().indexOf('.') != -1) && (e.which < 48 || e.which > 57)) e.preventDefault(); + if ((elm.attr('o3') ?? '') !== '') return; + elm.attr('o3', '1'); + elm.on('keypress keyup input', (e) => { + if (e.type === 'keypress') { + if ((e.which != 45 || elm.val().indexOf('-') != -1) && (e.which != 46 || elm.val().indexOf('.') != -1) && (e.which < 48 || e.which > 57)) e.preventDefault(); + } else { + var _val = elm.val().replace(/[^0-9.-]/g, ''); + if (_val.indexOf('-') > 0) _val = _val.charAt(0) + _val.slice(1).replace(/-/g, ''); + var _parts = _val.split('.'); + if (_parts.length > 2) _val = _parts[0] + '.' + _parts.slice(1).join(''); + elm.val(_val); + } }); + elm.on('blur', () => elm.val( FoniaJS.FloatToStr(elm.val(), 2) )); elm.on('focus', (e) => { elm.val( FoniaJS.StrToFloat(elm.val()) ); elm.select(); @@ -306,9 +317,18 @@ var FoniaJS = { }); $('input.form-control[type=number]').each((i, el) => { const elm = $(el); - elm.on('keypress keyup blur paste', (e) => { - elm.val(elm.val().replace(/[^0-9]/g,'')); - if ((e.which != 46 || elm.val().indexOf('.') != -1) && (e.which < 48 || e.which > 57)) e.preventDefault(); + if ((elm.attr('o3') ?? '') !== '') return; + elm.attr('o3', '1'); + elm.on('keypress keyup input', (e) => { + if (e.type === 'keypress') { + if ((e.which != 45 || elm.val().indexOf('-') != -1) && (e.which != 46 || elm.val().indexOf('.') != -1) && (e.which < 48 || e.which > 57)) e.preventDefault(); + } else { + var _val = elm.val().replace(/[^0-9.-]/g, ''); + if (_val.indexOf('-') > 0) _val = _val.charAt(0) + _val.slice(1).replace(/-/g, ''); + var _parts = _val.split('.'); + if (_parts.length > 2) _val = _parts[0] + '.' + _parts.slice(1).join(''); + elm.val(_val); + } }); }); $('input.form-control, textarea.form-control, select.form-select').each((i, el) => { @@ -316,6 +336,8 @@ var FoniaJS = { const okyup = elm.attr('okyup') ?? ''; const oblur = elm.attr('oblur') ?? ''; const ochan = elm.attr('ochan') ?? ''; + if ((elm.attr('o3') ?? '') !== '') return; + elm.attr('o3', '1'); elm.on('keyup blur change', (e) => { if (e.type === 'keyup' && okyup) { var fnc = okyup.split('.'); @@ -340,6 +362,8 @@ var FoniaJS = { }); $('input.form-check-input[type=radio]').each((i, el) => { const elm = $(el); + if ((elm.attr('o3') ?? '') !== '') return; + elm.attr('o3', '1'); elm.on('click', () => { const oclic = elm.attr('ochan') ?? ''; const elp = $('#'+elm.attr('name')); @@ -354,6 +378,8 @@ var FoniaJS = { }); $('input.form-check-input[type=checkbox]').each((i, el) => { const elm = $(el); + if ((elm.attr('o3') ?? '') !== '') return; + elm.attr('o3', '1'); elm.on('change', () => { const odata = JSON.parse(elm.attr('odata') ?? '[]'); const ochan = elm.attr('ochan') ?? ''; @@ -393,49 +419,47 @@ var FoniaJS = { } if ('function' == typeof autosize) autosize($('textarea')); }, - RequestParam: function(aparam) { - var tmp_hasil = []; - var tmp_array = aparam; - var tmp_cblist = {}; + var _cblist = {}; + var _ohasil = {}; $('tbody input[id*="cbox"][type="checkbox"]:checked').map((i, b) => { const arr = b.id.split('_'); - if (!tmp_cblist[arr[0]]) tmp_cblist[arr[0]] = []; - tmp_cblist[arr[0]].push(arr[2]); - // for compatible only - tmp_array.push(b.id + '=' + b.value); + if (!_cblist[arr[0]]) _cblist[arr[0]] = []; + _cblist[arr[0]].push(arr[2]); }); - $.each(tmp_cblist, (i, b) => { - tmp_array.push('List_CB_' + i + '=' + b.join()); + $.each(_cblist, (i, b) => { + _ohasil['List_CB_' + i] = b.join(); }); - tmp_array.map(nilai => { - if (typeof nilai === "string") { - var tmp_value = ""; - if (nilai.indexOf("=") == -1) { - if ($('#'+nilai).length) { - tmp_value = $('#'+nilai).val(); - if (typeof tmp_value === 'undefined') { - tmp_value = ($('#'+nilai).is('.integer, .number, .double')) ? '0' : ''; + if (typeof aparam === 'object') { + aparam.map(_par => { + if (typeof _par !== "string") this.return; + var _key = _par, _val = ""; + const _ind = _par.indexOf('='); + if (_ind !== -1) { + _key = _par.slice(0, _ind); + _val = _par.slice(_ind + 1); + } else { + if ($('#'+_par).length) { + _val = $('#'+_par).val(); + if (typeof _val === 'undefined') { + _val = ($('#'+_par).is('.integer, .number, .double')) ? 0 : ''; } else { - tmp_value = ($('#'+nilai).is('.integer, .number, .double')) ? this.StrToFloat(tmp_value) : encodeURIComponent(tmp_value); + _val = ($('#'+_par).is('.integer, .number, .double')) ? this.StrToFloat(_val) : encodeURIComponent(_val); } } - tmp_value = nilai + "=" + tmp_value; - } else { - tmp_value = nilai; } - tmp_hasil.push(tmp_value); - } - }); - tmp_hasil.push('SID=' + parseInt(Math.random() * 99999999)); - return tmp_hasil; + _ohasil[_key] = _val; + }); + } + _ohasil['SID'] = parseInt(Math.random() * 99999999); + return _ohasil; }, StrToFloat: function(str_val) { var nstr = str_val + ""; var hasil = ""; var fkali = 1; - if (nstr.substr(0, 3) == "Rp.") { - nstr = nstr.substr(3); + if (nstr.slice(0, 4) == "Rp.") { + nstr = nstr.slice(4); } for (var i = 0; i < nstr.length; i++) { if ((parseFloat(nstr.charAt(i))) || (nstr.charAt(i) == "0") || (nstr.charAt(i) == ".")) { @@ -604,13 +628,12 @@ var FoniaJS = { } }, AutoComplete: function(elm, turl, aparam, func_comp, func_key){ - var arrData = [], objComp = {}; - if ('string' !== typeof aparam) arrData = this.RequestParam(aparam); + var objComp = {}; objComp = { preventEnter: true, resolverSettings: { url: turl, - extraData: arrData.reduce(function(o, val) { var t = val.split('='); o[t[0]] = t[1]; return o; }, {}) + param: (typeof aparam === 'object') ? aparam : [] } }; if ('object' === typeof func_comp){ @@ -652,11 +675,11 @@ class _Request { console.log(this.options.sendParam + ", cek url php!"); return false; } - this.options.data = FoniaJS.RequestParam(this.options.sendParam); + this.options.data = $.extend(this.options.data, FoniaJS.RequestParam(this.options.sendParam)); $.ajax({ type: 'POST', url: this.options.url, - data: (this.options.data).join('&'), + data: this.options.data, success: (typeof this.options.onSuccess === "function") ? this.options.onSuccess : () => {}, error: (typeof this.options.onFailure === "function") ? this.options.onFailure : () => {}, complete: FoniaJS.FormDecorated, @@ -800,20 +823,17 @@ class _Request_JSONF extends _Request { var opsi = { responsive: true, columnDefs: [{responsivePriority:1,targets:0},{responsivePriority:2,targets:1},{responsivePriority:0,targets:-1}], lengthMenu: [], dom: '<"row"<"col-sm-12"tr>><"row"<"col-sm-12 col-lg-auto"<"toolbar">><"col-sm-3 col-lg-auto ms-lg-auto"l><"col-sm-9 col-lg-auto"p>>', autoWidth: false, processing: true, searching: false, columns: aSortCol, order: [[iCol, (ini.config.sort_dir=='A'?'asc':'desc')]], pageLength: ini.config.row_count, stateSave: true, stateSaveCallback: function(sett,data){localStorage.setItem(ini.id,JSON.stringify(data));}, stateLoadCallback: function(sett){try{var data=JSON.parse(localStorage.getItem(ini.id))??{};data.length=ini.config.row_count;return data;}catch(e){console.log(e)}} }; /** start live db **/ if (ini.config.live){ - var post_data = {}; - $(this.options.data).map((key, item) => { - var keyval = item.split("="); - if (keyval[0] == 'SID') keyval[1] = parseInt(Math.random() * 99999999); + $(this.options.data).map((key, val) => { + if (key === 'SID') val = parseInt(Math.random() * 99999999); // fixed bug for duplicate saving - if (keyval[0] == 'mode_detail') keyval[1] = 'live-data'; - if ((''+keyval[1]).indexOf('%') != -1) keyval[1] = decodeURIComponent(keyval[1]); - return post_data[keyval[0]] = keyval[1]; + if (key === 'mode_detail') val = 'live-data'; + //if ((''+val).indexOf('%') != -1) val = decodeURIComponent(val); }); opsi.serverSide = true; opsi.ajax = { url: this.options.url, type: 'POST', - data: post_data, + data: this.options.data, dataFilter: (data) => { var json = {}, jsono = {'draw':0,'recordsTotal':0,'recordsFiltered':0,'data':[]}; try { @@ -931,7 +951,10 @@ class _Request_JSONF extends _Request { // apply select function if (ini.config.func_select){ $('#'+ini.id+'Tabel tbody').on('click', 'tr', (e) => { - var dta = otabel.row(e.currentTarget).data(); + var elm = $(e.currentTarget); + if ((elm.attr('o3') ?? '') !== '') return; + elm.attr('o3', '1'); + var dta = otabel.row(elm).data(); var fnc = ini.config.func_select.split('.'); if (typeof window[fnc[0]][fnc[1]] === 'function') { window[fnc[0]][fnc[1]](dta); } else console.warn('fungsi '+ini.config.func_select+' tidak ada !'); @@ -945,16 +968,19 @@ class _Request_JSONF extends _Request { $(ini.option).map((key, val) => { if (val.type == 'checkbox'){ $('#'+ini.id+'Tabel thead input[type=checkbox][id*=_cbhead_]').on('change', (e) => { - var _chek = e.currentTarget.is(':checked'); - e.currentTarget.val(e.currentTarget.is(':checked') ? val.avalue[0] : val.avalue[1]); + var _etarg = $(e.currentTarget); + var _chek = _etarg.is(':checked'); + _etarg.val(_chek ? val.avalue[0] : val.avalue[1]); $('#'+ini.id+'Tabel tbody input[type=checkbox][id*='+val.field+'_cbox_]').each((i, el) => { - el.prop('checked', _chek); - el.val(el.is(':checked') ? val.avalue[0] : val.avalue[1]); + var _el = $(el); + _el.prop('checked', _chek); + _el.val(_el.is(':checked') ? val.avalue[0] : val.avalue[1]); }); }); $('#'+ini.id+'Tabel tbody input[type=checkbox][id*=_cbox_]').on('change', (e) => { - e.currentTarget.val(e.currentTarget.val() == val.avalue[1] ? val.avalue[0] : val.avalue[1]); - e.currentTarget.prop('checked', e.currentTarget.val() == val.avalue[0]); + var _ctarg = $(e.currentTarget); + _ctarg.val(_ctarg.val() == val.avalue[1] ? val.avalue[0] : val.avalue[1]); + _ctarg.prop('checked', _ctarg.val() == val.avalue[0]); }); } else if (val.type == 'button'){ $('#'+ini.id+'Tabel tbody').on('click', '.'+val.icon, (e) => { diff --git a/assets/js/pdf.js b/assets/js/pdf.js index 4e1afaf..e52c2b4 100644 --- a/assets/js/pdf.js +++ b/assets/js/pdf.js @@ -35,11 +35,10 @@ var cPDF = function(url, options){ console.warn(vars.param + ", cek url php!"); return false; } - vars.data = FoniaJS.RequestParam(vars.param); $.ajax({ type: 'POST', url: vars.url, - data: (vars.data).join('&'), + data: FoniaJS.RequestParam(vars.param), success: (typeof vars.onSuccess === "function") ? vars.onSuccess : null, error: (typeof vars.onFailure === "function") ? vars.onFailure : null, }).always(FoniaJS.FormDecorated); @@ -47,7 +46,7 @@ var cPDF = function(url, options){ }; this.showPDF = function(){ var _proto = window.location.protocol + '//'; - var _src = _proto + FoniaJS.WEB_HOST + vars.url + '?' + (FoniaJS.RequestParam(vars.param)).join('&') + '#zoom='+vars.zoom+',0,0&page=1'; + var _src = _proto + FoniaJS.WEB_HOST + vars.url + '?' + $.param(FoniaJS.RequestParam(vars.param)) + '#zoom='+vars.zoom+',0,0&page=1'; var _wtxt = '