Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Essential JavaScript Development Techniques

Tech May 17 3
  1. Merging Duplicate Array Elements

// Merge elements with duplicate prcdTermType and acctFnm properties
mergeDuplicates(arr) {
 const result = [];
 const lookup = {};

 arr.forEach(item => {
   const key = `${item.prcdTermType}-${item.acctFnm}`;
   if (lookup[key]) {
     lookup[key].pymtPrice = Number(lookup[key].pymtPrice) + Number(item.pymtPrice);
   } else {
     lookup[key] = { ...item };
     result.push(lookup[key]);
   }
 });

 return result;
},


  1. Calculating Sum of Specific Array Properties

// Calculate total of specified property in array
calculateSum(arr, propName) {
 return arr.reduce((sum, item) => {
   return item[propName] ? sum + Number(item[propName]) : sum;
 }, 0);
},


  1. Enum Value Transformation

// Project category enum
projectCategories: [
 { value: '1', label: 'Deposit' },
 { value: '2', label: 'Down Payment' },
 { value: '3', label: 'Registration' },
 { value: '4', label: 'Mortgage' },
 { value: '5', label: 'Full Payment' },
 { value: '6', label: 'Initial Payment' },
 { value: '7', label: 'Pre-interest' },
 { value: '8', label: 'Consultation Fee' },
 { value: '9', label: 'GPS' },
 { value: '10', label: 'Accessories' },
 { value: '11', label: 'Sticky Products' },
 { value: '12', label: 'Minor Items' },
 { value: '13', label: 'Other Projects' },
 { value: '14', label: 'Registration Deposit' },
 { value: '15', label: 'Trade-in Deposit' },
 { value: '16', label: 'GD Receivables' },
 { value: '17', label: 'GD Income' },
 { value: '18', label: 'High Margin Amount' },
 { value: '19', label: 'Other Deposits' },
],

transformProjectValues(valueString) {
 if (!valueString) return '';
 return valueString.split(',').map(code => {
   const found = this.projectCategories.find(cat => cat.value === code);
   return found ? found.label : code;
 }).join(',');
},


  1. Sorting Arrays by Property Values

// Sort array based on specific property
sortPayments(array, sortProperty) {
 const priorityOrder = ['5', '6'];
 
 return array.sort((a, b) => {
   const aPriority = priorityOrder.indexOf(a[sortProperty]);
   const bPriority = priorityOrder.indexOf(b[sortProperty]);
   
   if (aPriority !== -1 && bPriority === -1) return -1;
   if (aPriority === -1 && bPriority !== -1) return 1;
   return 0;
 });
},


  1. Calculating Price Differences Between Arrays

// Calculate price differences between two arrays
calculateDifferences(sourceArray, targetArray) {
 return sourceArray.map(item => {
   const matchingItems = targetArray.filter(target => target.prcdPrj === item.prcdPrj);
   const total = matchingItems.reduce((sum, curr) => 
     sum + Number(curr.pymtPrice) + Number(curr.depositAmount) + Number(curr.zhDeduction), 0);
   
   return {
     prcdPrj: item.prcdPrj,
     id: item.id,
     name: item.name,
     difference: item.prcdPrice - total
   };
 });
},


  1. Form Validation Focus Management

export function focusValidationError() {
 const errorFields = document.querySelectorAll('.van-field--error');
 if (errorFields.length > 0) {
   const firstError = errorFields[0].querySelector('.van-field__control');
   if (firstError) {
     firstError.focus();
   }
 }
}


  1. File Download Utility

// Download file utility function
export function downloadData(content, filename, extension) {
 const blob = new Blob([content]);
 const url = URL.createObjectURL(blob);
 const link = document.createElement('a');
 
 link.href = url;
 link.download = `${new Date().toISOString().slice(0, 10)}-${filename}.${extension}`;
 document.body.appendChild(link);
 link.click();
 document.body.removeChild(link);
 URL.revokeObjectURL(url);
}


  1. Conditional CSS Class Management

/**
* Check if element has specific class
*/
export function hasClass(element, className) {
 return element.classList.contains(className);
}

/**
* Add class to element
*/
export function addClass(element, className) {
 if (!hasClass(element, className)) {
   element.classList.add(className);
 }
}

// Usage example
const targetElement = document.getElementById('target-div');
addClass(targetElement, 'highlighted');

  1. Generating Random String Identifiers

/**
* Generate unique 32-bit string identifier
*/
export function generateUniqueId() {
 const timestamp = Date.now().toString();
 const random = Math.floor(Math.random() * 65536).toString();
 return (parseInt(random + timestamp)).toString(32);
}


  1. Removing Duplicates from Object Arrays

/**
* Remove duplicates from array of objects
*/
export function removeDuplicates(array) {
 return array.filter((item, index, self) => 
   index === self.findIndex(obj => JSON.stringify(obj) === JSON.stringify(item))
 );
}


  1. Debounce Function Implementation

/**
* Debounce function execution
*/
export function createDebounce(func, delay, immediate = false) {
 let timeoutId;
 
 return function(...args) {
   const callNow = immediate && !timeoutId;
   
   clearTimeout(timeoutId);
   timeoutId = setTimeout(() => {
     timeoutId = null;
     if (!immediate) func.apply(this, args);
   }, delay);
   
   if (callNow) func.apply(this, args);
 };
}


  1. Toggle CSS Classes

/**
* Toggle CSS class on element
*/
export function toggleClass(element, className) {
 if (!element || !className) return;
 
 if (element.classList.contains(className)) {
   element.classList.remove(className);
 } else {
   element.classList.add(className);
 }
}


  1. Extract Text Content from HTML

/**
* Convert HTML to plain text
*/
export function extractText(htmlString) {
 const tempDiv = document.createElement('div');
 tempDiv.innerHTML = htmlString;
 return tempDiv.textContent || tempDiv.innerText || '';
}

// Usage
const htmlContent = '<p>Hello <strong>World!</strong></p>';
const plainText = extractText(htmlContent);
console.log(plainText); // Outputs: "Hello World!"

  1. Parse URL Query Parameters

/**
* Convert URL query string to object
*/
export function parseQueryString(url) {
 const queryString = url.split('?')[1];
 if (!queryString) return {};
 
 const params = {};
 queryString.split('&').forEach(pair => {
   const [key, value] = pair.split('=');
   params[decodeURIComponent(key)] = decodeURIComponent(value || '');
 });
 
 return params;
}

// Usage
const url = 'http://example.com/?name=John&age=30';
const queryParams = parseQueryString(url);
console.log(queryParams); // { name: "John", age: "30" }

  1. Convert Object to URL Parameters

/**
* Convert object to URL parameter string
*/
export function objectToParams(obj) {
 return Object.entries(obj)
   .filter(([_, value]) => value !== undefined)
   .map(([key, value]) => 
     `${encodeURIComponent(key)}=${encodeURIComponent(value)}`
   )
   .join('&');
}

// Usage
const data = {
 name: 'John Doe',
 age: 30,
 city: undefined,
 job: 'Developer'
};

const params = objectToParams(data);
console.log(params); // name=John%20Doe&age=30&job=Developer

  1. Extract Query Parameters from URL

/**
* Extract query parameters from URL
*/
export function getQueryParams(url = window.location.href) {
 const params = {};
 const queryString = url.split('?')[1];
 
 if (queryString) {
   queryString.split('&').forEach(pair => {
     const [key, value] = pair.split('=');
     params[decodeURIComponent(key)] = decodeURIComponent(value || '');
   });
 }
 
 return params;
}

// Usage
const url = 'http://example.com/?name=John&age=30';
const query = getQueryParams(url);
console.log(query); // { name: 'John', age: '30' }

  1. Calculate Date Difference

/** 
* Calculate difference between two dates in days
*/
export function calculateDateDifference(startDate, endDate) {
 if (!startDate || !endDate) return 0;
 const diffTime = Math.abs(endDate - startDate);
 return Math.ceil(diffTime / (1000 * 60 * 60 * 24));
}


  1. Convert Date Format to Timestamp

/**
* Convert date string to timestamp
*/
export function dateStringToTimestamp(dateString) {
 if (!dateString) return null;
 
 let formattedDate = dateString;
 if (dateString.length === 19) {
   formattedDate = dateString.replace(/-/g, '/');
 } else {
   formattedDate = (dateString + ':00').replace(/-/g, '/');
 }
 
 return new Date(formattedDate).getTime();
}


  1. Component Form Validation Helper

// Form validation utility
export function validateForm(componentRef, callback) {
 componentRef.validate(isValid => {
   callback(isValid);
 });
}

// Example usage in Vue component
export default {
 methods: {
   submitForm() {
     validateForm(this.$refs.formComponent, (isValid) => {
       if (isValid) {
         console.log('Form valid, proceeding with submission');
       } else {
         console.error('Form validation failed');
       }
     });
   }
 }
}

  1. Currency Input Validation

// Validate currency input (positive numbers only)
export function validateCurrency(rule, value, callback) {
 const regex = /(?:^[1-9]([0-9]+)?(?:\.[0-9]{1,2})?$)|(?:^(?:0)$)|(?:^[0-9]\.[0-9](?:[0-9])?$)/;
 
 if (value === '' || value === undefined || value === null) {
   callback();
 } else if (!regex.test(value)) {
   callback(new Error('Please enter a valid number'));
 } else {
   callback();
 }
}


  1. Positive Number Validation

// Validate positive numbers including decimals
export function validatePositiveNumber(rule, value, callback) {
 const regex = /^[+][1-9](\d+)$|^[+]{0,1}(\d+\.\d+)$/;
 
 if (value === '' || value === undefined || value === null) {
   callback();
 } else if (!regex.test(value)) {
   callback(new Error('Please enter a valid positive number'));
 } else {
   callback();
 }
}


  1. Phone Number Validation

// Validate phone numbers and landlines
export function validatePhoneNumber(rule, value, callback) {
 const mobilePattern = /^(([1][3,4,5,7,8]\d{9})|([0]\d{10,11})|(\d{7,8})|(\d{4}|\d{3})-(\d{7,8}))$/;
 const landlinePattern = /^\d{3}-\d{8}|\d{4}-\d{7}$/;

 if (!value || value === '') {
   callback(new Error('Please enter a contact method'));
 } else if (value.length === 11) {
   if (value.indexOf('-') !== -1) {
     callback();
   } else if (mobilePattern.test(value)) {
     callback();
   } else {
     callback(new Error('Please enter a valid phone number or landline (format: area-code-number)'));
   }
 } else if (value.length === 12) {
   if (landlinePattern.test(value)) {
     callback();
   } else {
     callback(new Error('Please enter a valid phone number or landline (format: area-code-number)'));
   }
 } else {
   callback(new Error('Please enter a valid phone number or landline (format: area-code-number)'));
 }
}


  1. Alphanumeric with Uppercase Requirement

// Validate alphanumeric with uppercase requirement
export function validateAlphanumericWithUpper(rule, value, callback) {
 const regex = /^(?=.*[A-Z])(?=.*\d)[a-zA-Z\d]+$/;
 
 if (value === '' || value === undefined || value === null) {
   callback();
 } else if (!regex.test(value)) {
   callback(new Error('Must contain letters, numbers, and at least one uppercase letter'));
 } else {
   callback();
 }
}


  1. Concurrent API Requests

async fetchAccountData() {
 try {
   const [cpResponse, szResponse] = await Promise.all([
     api.getAccountDetails({ cpAcctId: this.formData.cpAcctId }),
     api.getAccountDetails({ szAcctId: this.formData.szAcctId })
   ]);
   
   console.log('CP Account:', cpResponse);
   console.log('SZ Account:', szResponse);
   
 } catch (error) {
   console.error('Failed to fetch account data:', error);
 }
},


  1. Default Value for Cascader Component

<el-cascader
 v-model="formData.vehicleBrand"
 :options="brandOptions"
 filterable
 :props="cascaderProps"
 clearable
/>

// Initialize default selection
computed: {
 cascaderProps() {
   return {
     label: 'name',
     value: 'name',
     children: 'children',
     expandTrigger: 'hover',
     checkStrictly: true
   };
 }
},
methods: {
 getDefaultPath(options) {
   if (!options || options.length === 0) return [];
   
   const firstOption = options[0];
   if (firstOption.children && firstOption.children.length > 0) {
     return [firstOption.name, ...this.getDefaultPath(firstOption.children)];
   }
   return [firstOption.name];
 }
}

// Set initial value
this.formData.vehicleBrand = this.getDefaultPath(this.brandOptions);

  1. Checking Uniformity of Array Properties

// Check if all items have same property value
function checkPropertyConsistency(array, propertyName) {
 if (array.length === 0) return true;
 
 const firstValue = array[0][propertyName];
 return array.every(item => item[propertyName] === firstValue);
}


  1. VIN Number Validation

// Validate VIN number according to GB standard
function validateVin(vin) {
 const vinRegex = /^[A-HJ-NPR-Z0-9]{17}$/;
 if (!vinRegex.test(vin)) return false;

 const weights = [8, 7, 6, 5, 4, 3, 2, 10, 0, 9, 8, 7, 6, 5, 4, 3, 2];
 const values = {
   0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7, 8: 8, 9: 9,
   A: 1, B: 2, C: 3, D: 4, E: 5, F: 6, G: 7, H: 8,
   J: 1, K: 2, L: 3, M: 4, N: 5, P: 7, R: 9,
   S: 2, T: 3, U: 4, V: 5, W: 6, X: 7, Y: 8, Z: 9
 };

 let sum = 0;
 for (let i = 0; i < 17; i++) {
   const char = vin[i].toUpperCase();
   sum += values[char] * weights[i];
 }

 const checkDigit = sum % 11 === 10 ? 'X' : (sum % 11).toString();
 return vin[8].toUpperCase() === checkDigit;
}


  1. Advacned Debounce Implementation

export function debounce(func, wait, immediate = false) {
 let timeoutId;
 
 return function(...args) {
   const callNow = immediate && !timeoutId;
   
   clearTimeout(timeoutId);
   timeoutId = setTimeout(() => {
     timeoutId = null;
     if (!immediate) func.apply(this, args);
   }, wait);
   
   if (callNow) func.apply(this, args);
 };
}

// Usage example
const debouncedSearch = debounce((query) => {
 performSearch(query);
}, 300);

// Call multiple times rapidly, only executes once after 300ms
debouncedSearch('term1');
debouncedSearch('term2');
debouncedSearch('term3');

  1. Date Utilities

  • Get current date in YYYY-MM-DD format
getCurrentDate() {
 const now = new Date();
 const year = now.getFullYear();
 const month = String(now.getMonth() + 1).padStart(2, '0');
 const day = String(now.getDate()).padStart(2, '0');
 return `${year}-${month}-${day}`;
},

// Convert time string to minutes
convertTimeToMinutes(timeString) {
 const [hours, minutes] = timeString.split(':').map(Number);
 return hours * 60 + minutes;
},


  1. Date Picker Restrictions

// Disable past dates
disabledPastDates(date) {
 return date.getTime() < Date.now() - 8.64e7;
}

// Restrict date range to today plus 30 days
restrictedDateRange(date) {
 const today = new Date();
 const maxDate = new Date(today.getFullYear(), today.getMonth(), today.getDate() + 30);
 return date.getTime() < today.getTime() || date.getTime() > maxDate.getTime();
}


  1. Table Selection Control

// Disable selection based on condition
disableSelection(row) {
 return row.quantity === 0;
}

// Process array to set selectable flags
processSelectionStatus(items) {
 return items.map(item => ({
   ...item,
   selectable: item.quantity > 0
 }));
}


  1. Paramter Serialization

// Serialize object to query parameters
const params = {
 method: 'get',
 id: 1,
 name: 'yjn'
};

const serialized = new URLSearchParams(params).toString();
// Result: "method=get&id=1&name=yjn"

// Serialize array
const arrayParam = [2, 3];
const serializedArray = new URLSearchParams({ arr: arrayParam }).toString();
// Result: "arr=2&arr=3"

// With custom serialization
const customSerialized = new URLSearchParams({ 
 arr: arrayParam 
}).toString({ indices: false });
// Result: "arr=2&arr=3"

  1. Table Summary Calculation

// Basic summary calculation
calculateTableSummary(columns) {
 const numericColumns = ['amt', 'costAmt', 'qty', 'recAmt'];
 
 return columns.map((column, index) => {
   if (index === 0) return 'Total';
   
   const columnName = column.property.includes('.') 
     ? column.property.split('.')[1] 
     : column.property;
     
   if (numericColumns.includes(columnName)) {
     return this.calculateSum(this.tableData, columnName);
   }
   return '';
 });
},


  1. Form Layout Behavior

  • When :inline="false" - form fields adapt to container width
  • When :inline="true" - form fields maintain fixed widths
  1. Avoiding Boolean Conversion of Zero

  • Solution 1: Explicit zero comparison
if (myValue === 0 || myValue) {
 // Handle both zero and truthy values
}

  • Solution 2: Complex boolean logic
if (!(myValue === 0 ? false : !myValue)) {
 // Handles zero correctly
}

  1. Numeric Value Validation

// Check if value is a number and not falsy except zero
if (!isNaN(myValue) && !(myValue === 0 ? false : !myValue)) {
 // Valid numeric value
}

// Alternative ternary approach
v-if="myValue === 0 ? true : !!myValue"

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.