(function() { // global uind object window.ctp = {}; // utils object window.ctp.utils = {}; // date format window.ctp.utils.dateFormat = 'm/d/yy'; // month names const monthNames = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"]; // datatable default config window.ctp.dataTableDefaultConfig = { pageLength: 100, searching: true, lengthChange: false, processing: true, fixedHeader: true, dom: ` <'row'<'col-sm-5'B><'col-sm-7'f>> <'row'<'col-sm-12't>> <'row'<'col-sm-5'i><'col-sm-7'p>>`, buttons: [{ extend: 'excel', text: '', className: 'bi bi-file-earmark-spreadsheet btn-sm' }] }; // image compressor default config window.ctp.compressor = { quality: 0.8, maxWidth: 2000, maxHeight: 2000 }; // tinymce window.ctp.getTinyMceDefaultConfig = function( selector ) { return { selector: selector, skin: 'oxide', statusbar: false, plugins: [ 'advlist','autolink','lists','link','image','charmap', 'fullscreen','insertdatetime','media','table','help','wordcount', 'preview','anchor','searchreplace','visualblocks','textcolor' ], toolbar: 'undo redo | a11ycheck casechange blocks | bold italic backcolor forecolor | alignleft aligncenter alignright alignjustify | bullist numlist checklist outdent indent | removeformat | code table help' }; } // initialize datatable window.ctp.utils.initializeDataTable = function( $el, customConfig ) { customConfig = ( typeof customConfig === 'undefined' ) ? {} : customConfig; let config = Object.assign( window.ctp.dataTableDefaultConfig, customConfig ); return $el.DataTable( config ); }; // util function: populate options in a select tag window.ctp.utils.populateOptions = function( $select, optionArr, addMinusOption = false, addFirstOption = false ) { const emptyOptionStr = ''; let htmlStr = ''; if ( addFirstOption ) { htmlStr += emptyOptionStr; } for ( let i = 0; i < optionArr.length; i++ ) { htmlStr += ``; } if ( addMinusOption ) { htmlStr += ''; } $select.html( htmlStr ); }; window.ctp.utils.populateMachineOptions = function( $select, optionArr,addFirstOption = false ) { const emptyOptionStr = ''; let htmlStr = ''; if ( addFirstOption ) { htmlStr += emptyOptionStr; } for ( let i = 0; i < optionArr.length; i++ ) { htmlStr += ``; } $select.html( htmlStr ); }; // populate system users window.ctp.utils.populateUserOptions = function( $select, optionArr, addFirstOption = false ) { const emptyOptionStr = ''; let htmlStr = ''; if ( addFirstOption ) { htmlStr += emptyOptionStr; } for ( let i = 0; i < optionArr.length; i++ ) { htmlStr += ``; } $select.html( htmlStr ); }; // populate location options window.ctp.utils.populateLocationOptions = function( $select, optionArr, addFirstOption = false ) { const emptyOptionStr = ''; let htmlStr = ''; if ( addFirstOption ) { htmlStr += emptyOptionStr; } for ( let i = 0; i < optionArr.length; i++ ) { // data attributes let dataAttributes = ""; // check for unit id if ( optionArr[i].hasOwnProperty( 'unitId' ) ) { dataAttributes += `data-unit-id=${optionArr[i]['unitId']} `; } // check for floor id if ( optionArr[i].hasOwnProperty( 'floorId' ) ) { dataAttributes += `data-floor-id=${optionArr[i]['floorId']} `; } // check for store id if ( optionArr[i].hasOwnProperty( 'storeId' ) ) { dataAttributes += `data-store-id=${optionArr[i]['storeId']} `; } htmlStr += ``; } $select.html( htmlStr ); }; window.ctp.utils.populateTypeOptions = function( $select, optionArr, addMinusOption = false, addFirstOption = false ) { const emptyOptionStr = ''; let htmlStr = ''; if ( addFirstOption ) { htmlStr += emptyOptionStr; } for ( let i = 0; i < optionArr.length; i++ ) { htmlStr += ``; } if ( addMinusOption ) { htmlStr += ''; } $select.html( htmlStr ); }; // function to convert image to blob window.ctp.utils.fileToBase64 = function( file ) { return new Promise(function( resolve, reject ) { const reader= new FileReader(); reader.readAsDataURL( file ); reader.onload = function() { resolve( reader.result ); }; reader.onerror = function( err ) { reject( err ); } }); }; // debounce function window.ctp.utils.debounce = async function( func, interval ) { let lastCall = -1; return async function() { clearTimeout( lastCall ); let args = arguments; let self = this; lastCall = setTimeout(function() { func.apply( self, args ); }, interval ); }; }; // check duplicates window.ctp.utils.hasDuplicates = function( $selector, $otherSelectors, value ) { let hasDuplicate = false; $otherSelectors.not( $selector ).each(function() { if ( $( this ).val() === value ) { hasDuplicate = true; } }); return hasDuplicate; }; // number with commas window.ctp.utils.numberWithCommas = function( number ) { let floatNumber = parseFloat( number ).toFixed( 2 ); return floatNumber.toString().replace( /\B(?=(\d{3})+(?!\d))/g, "," ); }; // number with commas without fixed decimal places window.ctp.utils.numberWithCommasWithoutFixedDecimals = function( number ) { let floatNumber = parseFloat( number ); return floatNumber.toString().replace( /\B(?=(\d{3})+(?!\d))/g, "," ); }; // format currency window.ctp.utils.formatCurrency = function( number, language, location, currency ) { let locale = language + '-' + location; return new Intl.NumberFormat( locale, { style: 'currency', currency: currency }).format( number ); }; // format currency pkr window.ctp.utils.formatCurrencyPKR = function( number ) { let locale = 'en-PK'; return new Intl.NumberFormat( locale, { style: 'currency', currency: 'PKR' }).format( number ); }; window.ctp.utils.formatCurrencyPKRWithoutDecimal = function( number ) { return ( window.ctp.utils.formatCurrencyPKR( number ) ).split( '.' )[0]; }; //format decimal places of given decimal number upto given decimal places window.ctp.utils.formatDecimalPlaces = function( num, decimalPlaces ) { const strNum = num.toString(); const decimalIndex = strNum.indexOf('.'); if( decimalIndex === -1 ) { return num; } const endIndex = decimalIndex + decimalPlaces; const strFormattedNumber = strNum.slice( 0, endIndex + 1 ); return parseFloat( strFormattedNumber ); }; // number to american system window.ctp.utils.numberToAmericanSystemWords = function( number ) { number = Math.ceil( number ); const ones = ['', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine']; const tens = ['', '', 'twenty', 'thirty', 'forty', 'fifty', 'sixty', 'seventy', 'eighty', 'ninety']; const teens = ['ten', 'eleven', 'twelve', 'thirteen', 'fourteen', 'fifteen', 'sixteen', 'seventeen', 'eighteen', 'nineteen']; function convert_millions( num ) { if ( num >= 1000000 ) { return convert_millions( Math.floor( num / 1000000 ) ) + " million " + convert_thousands( num % 1000000 ); } else { return convert_thousands( num ); } } function convert_thousands( num ) { if ( num >= 1000 ) { return convert_hundreds( Math.floor( num / 1000 ) ) + " thousand " + convert_hundreds( num % 1000 ); } else { return convert_hundreds( num ); } } function convert_hundreds( num ) { if ( num > 99 ) { return ones[Math.floor( num / 100 )] + " hundred " + convert_tens( num % 100 ); } else { return convert_tens( num ); } } function convert_tens( num ) { if ( num < 10 ) return ones[num]; else if ( num >= 10 && num < 20 ) return teens[num - 10]; else { return tens[Math.floor( num / 10 )] + " " + ones[num % 10]; } } function convert( num ) { if ( num == 0 ) return "zero"; else return convert_millions( num ); } let result = convert( number ); if ( typeof result === 'undefined' ) { return zero; } return result.trim(); }; // number to south asian system window.ctp.utils.numberToSouthAsianSystemWords = function( number ) { const a = ['', 'one ', 'two ', 'three ', 'four ', 'five ', 'six ', 'seven ', 'eight ', 'nine ', 'ten ', 'eleven ', 'twelve ', 'thirteen ', 'fourteen ', 'fifteen ', 'sixteen ', 'seventeen ', 'eighteen ', 'nineteen ']; const b = ['', '', 'twenty', 'thirty', 'forty', 'fifty', 'sixty', 'seventy', 'eighty', 'ninety']; const regex = /^(\d{2})(\d{2})(\d{2})(\d{1})(\d{2})$/; const getLT20 = ( n ) => a[Number( n )]; const get20Plus = ( n ) => b[n[0]] + ' ' + a[n[1]]; function convert ( input ) { const num = Number( input ); if ( isNaN( num ) ) return ''; if ( num === 0 ) return 'zero'; const numStr = num.toString(); if ( numStr.length > 9 ) { throw new Error( 'overflow' ) // Does not support converting more than 9 digits yet } const [, n1, n2, n3, n4, n5] = ( '000000000' + numStr ).substr( -9 ).match( regex ) // left pad zeros let str = ''; str += n1 != 0 ? ( getLT20( n1 ) || get20Plus( n1 ) ) + 'crore ' : ''; str += n2 != 0 ? ( getLT20( n2 ) || get20Plus( n2 ) ) + 'lakh ' : ''; str += n3 != 0 ? ( getLT20( n3 ) || get20Plus( n3 ) ) + 'thousand ' : ''; str += n4 != 0 ? getLT20( n4 ) + 'hundred ' : ''; str += n5 != 0 && str != '' ? 'and ' : ''; str += n5 != 0 ? ( getLT20( n5 ) || get20Plus( n5 ) ) : ''; return str.trim(); } return convert( number ); }; /** * sleep method */ window.ctp.utils.sleep = async function( ms ) { return new Promise( resolve => setTimeout( resolve, ms ) ); }; // number to words window.ctp.utils.numberToWords = function( number, currencySymbol ) { let words = window.ctp.utils.numberToAmericanSystemWords( number ); return words + ' only.'; }; // format grades window.ctp.utils.formatGrades = function( grades ) { let gradesArr = []; for ( let grade of grades ) { let gradeFormatted = {}; gradeFormatted['id'] = grade.id; gradeFormatted['title'] = grade.type + '-' + grade.level + " (" + grade.description + ")"; gradesArr.push( gradeFormatted ); } return gradesArr; }; // format companies window.ctp.utils.formatCompanies = function( companies ) { let companyArr = []; for ( let company of companies ) { let companyFormatted = {}; companyFormatted['id'] = company.id; companyFormatted['title'] = company.title; companyArr.push( companyFormatted ); } return companyArr; }; // format raw expense data into pie chart data window.ctp.utils.formatExpenseDataForPieChart = function( expenses ) { let formattedData = []; for ( let expense of expenses ) { let formattedExpense = {}; formattedExpense['name'] = expense.title; formattedExpense['y'] = expense.cost; formattedData.push( formattedExpense ); } return formattedData; }; // bind cost center search window.ctp.utils.bindItemNewCostCenterSearchAutoComplete = function( $selector ) { $selector.autocomplete({ source: '/uind/rest/accounts-finance/cost-centers/search?departmentId=0', minLength: 1, select: async function (e, ui) { e.preventDefault(); //format string let splitStr = ui.item.heirarchicalString.split(">"); let hierarchyStr = `${splitStr[3]} > ${splitStr[2]} > ${splitStr[1]} > ${splitStr[0]}` let $container = $selector.closest( '[data-cost-center-search-container]' ); $container.find( '[data-cost-center-one-search-id]' ).val( ui.item.oneId ); $container.find( '[data-cost-center-two-search-id]' ).val( ui.item.twoId ); $container.find( '[data-cost-center-three-search-id]' ).val( ui.item.threeId ); $container.find( '[data-cost-center-four-search-id]' ).val( ui.item.fourId ); $selector.val( hierarchyStr ); }, focus: function ( e, ui ) { $selector.val( '' ); } }).data( 'ui-autocomplete' )._renderItem = function ( ul, ui ) { let splitStr = ui.heirarchicalString.split(">"); let hierarchyStr = `${splitStr[3]} > ${splitStr[2]} > ${splitStr[1]} > ${splitStr[0]}` return $( '
  • ' ) .attr( "data-value", ui.costCenterOneId ) .append( `
    ${hierarchyStr}
    ` ) .appendTo( ul ); }; }; // bind cost center search window.ctp.utils.bindItemCostCenterSearchAutoComplete = function( $selector ) { $selector.autocomplete({ source: '/uind/rest/uic/cost-centers/search', minLength: 1, select: async function (e, ui) { e.preventDefault(); let $container = $selector.closest( '[data-cost-center-search-container]' ); $container.find( '[data-cost-center-one-search-id]' ).val( ui.item.costCenterOneId ); $container.find( '[data-cost-center-two-search-id]' ).val( ui.item.costCenterTwoId ); $container.find( '[data-cost-center-three-search-id]' ).val( ui.item.costCenterThreeId ); $container.find( '[data-cost-center-four-search-id]' ).val( ui.item.costCenterFourId ); $selector.val( ui.item.hierarchyString ); }, focus: function ( e, ui ) { $selector.val( '' ); } }).data( 'ui-autocomplete' )._renderItem = function ( ul, ui ) { return $( '
  • ' ) .attr( "data-value", ui.costCenterOneId ) .append( `
    ${ui.hierarchyString}
    ` ) .appendTo( ul ); }; }; // bind item brand search window.ctp.utils.bindItemBrandSearchAutoComplete = function( $selector ) { $selector.autocomplete({ source: '/uind/rest/admin/item-brands/search', minLength: 1, select: async function (e, ui) { e.preventDefault(); let $container = $selector.closest( '[data-item-brand-search-container]' ); $container.find( '[data-item-brand-search-id]' ).val( ui.item.id ); $selector.val( ui.item.title ); }, focus: function ( e, ui ) { $selector.val( '' ); $selector.closest( '[data-item-brand-search-container]' ).find( '[data-item-brand-search-id]' ).removeAttr( 'value' ); } }).data( 'ui-autocomplete' )._renderItem = function ( ul, ui ) { return $( '
  • ' ) .attr( "data-value", ui.id ) .append( `
    ${ui.title}
    ` ) .appendTo( ul ); }; }; // bind item config search window.ctp.utils.bindItemConfigSearchAutoComplete = function( $selector ) { $selector.autocomplete({ source: '/uind/rest/admin/item-brands/search', minLength: 1, select: async function (e, ui) { e.preventDefault(); let $container = $selector.closest( '[data-item-config-search-container]' ); $container.find( '[data-item-config-search-id]' ).val( ui.item.id ); $selector.val( ui.item.title ); }, focus: function ( e, ui ) { $selector.val( '' ); $selector.closest( '[data-item-config-search-container]' ).find( '[data-item-config-search-id]' ).removeAttr( 'value' ); } }).data( 'ui-autocomplete' )._renderItem = function ( ul, ui ) { return $( '
  • ' ) .attr( "data-value", ui.id ) .append( `
    ${ui.title}
    ` ) .appendTo( ul ); }; }; // format events data window.ctp.utils.formatLogbackEventsDataTimeSeries = function( events ) { let formattedData = []; for ( let event of events ) { let eventData = []; eventData.push( event.timestmp ); eventData.push( 1 ); formattedData.push( eventData ); } return formattedData; }; // get formatted date from date string // e.g. accept '2020-10-15' and return 'October 15, 2020' window.ctp.utils.getFormattedDateStringFromDateString = function( dateString ) { let date = new Date( Date.parse( dateString ) ); return `${monthNames[date.getMonth()]} ${date.getDate()}, ${date.getFullYear()}`; }; // get formatted datetime from datetime string // e.g. accept '2021-01-25T12:38:02' and return '1/25/21 12:38 PM' window.ctp.utils.getFormattedDateTimeStringFromDateTimeString = function( dateString ) { if ( ! dateString ) { return null; } let date = new Date( Date.parse( dateString ) ); let day = date.getDate(); let month = date.getMonth(); let year = date.getFullYear().toString().substr( -2 ); let hour = ( date.getHours() > 12 ) ? ( date.getHours() - 12 ) : date.getHours(); hour = ( hour > 9 ) ? hour : ( '0' + hour ); let minute = date.getMinutes(); minute = ( minute > 9 ) ? minute : ( '0' + minute ); let ampm = ( hour >= 12 ) ? 'PM' : 'AM'; return `${month + 1}/${day}/${year} ${hour}:${minute} ${ampm}`; }; // get formatted datetime from datetime string // e.g. accept '2021-01-25T12:38:02' and return '1/25/21 12:38 PM' window.ctp.utils.getFormatted24HrsDateTimeStringFromDateTimeString = function( dateString ) { if ( ! dateString ) { return null; } let date = new Date( Date.parse( dateString ) ); let day = date.getDate(); day = ( day > 9 ) ? day : ( '0' + day ); let month = date.getMonth(); month = ( month > 9 ) ? month : ( '0' + month ); let year = date.getFullYear(); let hour = ( date.getHours() > 12 ) ? ( date.getHours() - 12 ) : date.getHours(); hour = ( hour > 9 ) ? hour : ( '0' + hour ); let minute = date.getMinutes(); minute = ( minute > 9 ) ? minute : ( '0' + minute ); let seconds = date.getSeconds(); seconds = ( seconds > 9 ) ? seconds : ( '0' + seconds ); return `${year}-${month + 1}-${day} ${hour}:${minute}:${seconds}`; }; // get formatted datetime from datetime string // e.g. accept '2021-01-25T12:38:02' and return '12:38 PM' window.ctp.utils.getFormattedTimeStringFromDateTimeString = function( dateString ) { if ( ! dateString ) { return null; } let date = new Date( Date.parse( dateString ) ); let hour = ( date.getHours() > 12 ) ? ( date.getHours() - 12 ) : date.getHours(); hour = ( hour > 9 ) ? hour : ( '0' + hour ); let minute = date.getMinutes(); minute = ( minute > 9 ) ? minute : ( '0' + minute ); let ampm = ( date.getHours() >= 12 ) ? 'PM' : 'AM'; return `${hour}:${minute} ${ampm}`; }; // get formatted date as yyyy-mm-dd window.ctp.utils.getFormattedDateAsISO8601 = function( date ) { let month = '' + ( date.getMonth() + 1 ), day = '' + date.getDate(), year = date.getFullYear(); if ( month.length < 2 ) { month = '0' + month; } if ( day.length < 2 ) { day = '0' + day; } return [year, month, day].join( '-' ); }; // check if element in viewport window.ctp.utils.elementInViewport = function( el ) { // Special bonus for those using jQuery if ( typeof jQuery === "function" && el instanceof jQuery ) { el = el[0]; } let rect = el.getBoundingClientRect(); return ( rect.top >= 0 && rect.left >= 0 && rect.bottom <= ( window.innerHeight || document.documentElement.clientHeight ) && /* or $(window).height() */ rect.right <= ( window.innerWidth || document.documentElement.clientWidth ) /* or $(window).width() */ ); }; // get number of number-of-months-added date window.ctp.utils.addMonthsToDate = function( date, numberOfMonths ) { // make new date from given date let newDate = new Date( date.getTime() ); // add given number of months to new date const addedMonths = newDate.getMonth() + numberOfMonths; newDate.setMonth( addedMonths ); return newDate; } // get year-month string from date window.ctp.utils.getYearMonthStringFromDate = function( date ) { let month = '' + ( date.getMonth() + 1 ); const year = date.getFullYear(); if ( month.length < 2 ) { month = '0' + month; } return year + '-' + month; } // get date from year-month string window.ctp.utils.getDateFromYearMonthString = function( yearMonthString ) { // split given year-month string in array let yearMonthArray = yearMonthString.split( '-' ); const year = yearMonthArray[0]; const month = '' + ( parseInt( yearMonthArray[1] ) - 1 ) return new Date( year, month ); } // get months added year-month string window.ctp.utils.getMonthsAddedYearMonthStringFromYearMonthString = function( startYearMonthString, numberOfMonths ) { // get start date from startYearMonthString const startDate = window.ctp.utils.getDateFromYearMonthString( startYearMonthString ); // get end date const endDate = window.ctp.utils.addMonthsToDate( startDate, numberOfMonths ); // get end year-month string const endYearMonthString = window.ctp.utils.getYearMonthStringFromDate( endDate ); return endYearMonthString; } // get months added year-month string from date window.ctp.utils.getMonthsAddedYearMonthStringFromDate = function( startDate, numberOfMonths ) { const endDate = window.ctp.utils.addMonthsToDate( startDate, numberOfMonths ); const endYearMonthString = window.ctp.utils.getYearMonthStringFromDate( endDate ); return endYearMonthString; } // get number of days in given date's month window.ctp.utils.getNumberOfDaysInGivenDate = function( date ) { return new Date( date.getFullYear(), date.getMonth() + 1, 0 ).getDate(); } // get date object from date string ( string format yyyy-MM-dd ) window.ctp.utils.getDateFromString = function( dateString ) { const dateArray = dateString.split( '-' ); return new Date( dateArray[0], ( parseInt( dateArray[1] ) - 1 ) + '', dateArray[2] ); } // add days to given date string ( string format yyyy-MM-dd ) window.ctp.utils.addDaysToDate = function( dateString, days ) { const date = window.ctp.utils.getDateFromString( dateString ); const daysAdded = date.getDate() + days; const month = date.getMonth(); return new Date( date.getFullYear().toString(), month.toString(), daysAdded.toString() ); } // google map styles window.ctp.google_map_styles = [ { "featureType": "road", "elementType": "geometry", "stylers": [ { "lightness": 100 }, { "visibility": "simplified" } ] }, { "featureType": "water", "elementType": "geometry", "stylers": [ { "visibility": "on" }, { "color": "#C6E2FF" } ] }, { "featureType": "poi", "elementType": "geometry.fill", "stylers": [ { "color": "#C5E3BF" } ] }, { "featureType": "road", "elementType": "geometry.fill", "stylers": [ { "color": "#D1D1B8" } ] } ]; // default file icon window.ctp.defaultFileIcon = '/uind/img/file_types/misc.svg'; /** * get similarity score using Levenshtein distance algorithm */ window.ctp.utils.getSimilarityScore = function( toCheck, original ) { const m = toCheck.length; const n = original.length; const d = []; for ( let i = 0; i <= m; i++ ) { d[i] = [i]; } for ( let j = 0; j <= n; j++ ) { d[0][j] = j; } for ( let j = 1; j <= n; j++ ) { for ( let i = 1; i <= m; i++ ) { if ( toCheck[i - 1] === original[j - 1] ) { d[i][j] = d[i - 1][j - 1]; } else { d[i][j] = Math.min( d[i - 1][j] + 1, // deletion d[i][j - 1] + 1, // insertion d[i - 1][j - 1] + 1 // substitution ); } } } return Math.max( 0, Math.min( 1, ( 1 - d[m][n] / Math.max( m, n ) ) ) ); }; /* * return the uuid for browser * */ window.ctp.utils.getOrGenerateBrowserId = function () { let browserId = localStorage.getItem('device-hash'); if ( !browserId ) { browserId = window.ctp.utils.generateUUID(); localStorage.setItem( 'device-hash', browserId ); } return browserId; } /* * generate uuid for each browser * */ window.ctp.utils.generateUUID = function () { return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) { var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8); return v.toString(16); }); } })();