import { Injectable, Optional } from '@angular/core'; import { DataColumn, ColumnFormatter, EnumFormatOptions, ColumnFormatService } from '@farris/ui-common/column'; @Injectable({ providedIn: 'root' }) export class CommonUtils { private cfs: ColumnFormatService = null; constructor() { if (!this.cfs) { this.cfs = new ColumnFormatService(null, null); } } /** * 获取对象中指定字段的值。 field: 可以为带有层级结构的路径,如: user.firstName | name 等 * data: 获取字段的数据源,一般为JSON对象 * safe: 为true, 将html字符进行转码输出,默认为 false */ getValue(field: string, data: any, safe = false) { if (!data) { return ''; } let resultVal = ''; if (field.indexOf('.') === -1 && data.hasOwnProperty(field)) { resultVal = data[field]; } else { resultVal = field.split('.').reduce((obj, key) => { if (obj) { return obj[key]; } else { return null; } }, data); } if (safe) { return this.formatterValue(resultVal); } else { return resultVal; } } /** * 更新指定对象中某个字段的值 * @param obj 被更新对象 * @param field 被更新字段 * @param val 新值 * @param nest 是否为嵌套,默认为 true */ setValue(obj: { [key: string]: any }, field: string, val: any, nest = true) { if (field) { if (field.indexOf('.') > -1 && nest) { let lastObj = null; const _fields = field.split('.'); _fields.reduce( (c, p) => { lastObj = c; return c[p]; }, obj); if (lastObj) { lastObj[_fields.pop()] = val; } } else { obj[field] = val; } } } getEnumItem(value: any, enumData: any[], valueField) { const item = enumData.find(n => n[valueField] == value); return item; } private _getEnumTitleFromColumn(value: any, col: any) { const _col = col as DataColumn; const formatter = _col.formatter as ColumnFormatter; if (formatter && typeof formatter === 'object') { if (formatter.type === 'enum' && formatter.options) { return this.getEnumTitleFromColumnOptions(value, formatter.options); } } return value; } getEnumTitle(col: DataColumn, data: any ) { const val = this.getValue(col.field, data); return this._getEnumTitleFromColumn(val, col); } getEnumTitleFromColumnOptions(value: any, opts: any) { const { data, valueField, textField } = opts; const item = this.getEnumItem(value, data, valueField); if (item) { return item[textField]; } else { return value; } } escapeHtml(str) { if (str === null || str === undefined) { return ''; } return str .replace(/&/g, '&') .replace(//g, '>') .replace(/\"/g, '"') .replace(/\'/g, ''') .replace(/\//g, '/'); } unescapeHtml(str) { if (str === null || str === undefined) { return ''; } return str .replace(/&/g, '&') .replace(/</g, '<') .replace(/>/g, '>') .replace(/"/g, '"') .replace(/'/g, '\'') .replace(///g, '/'); } private formatterValue(val: any) { if (val === null || val === undefined || val === '') { return ''; } if (typeof val === 'string') { return this.escapeHtml(val); } return val; } /** 获取字符串在页面中的真实宽度 */ getTextWidth(txt: string, font) { // const frag = document.createDocumentFragment(); const canvas = document.createElement('canvas'); const context = canvas.getContext('2d'); context.font = font; const metrics = context.measureText(txt); return Math.round(metrics.width); } removeStyleSheet(id: string) { const styleElement = document.querySelector('#' + id); if (styleElement) { styleElement.remove(); } } createStyleSheet(styleSheetId: string): HTMLStyleElement { const htmlHead = document.querySelector('head'); const styleEleId = styleSheetId; let styleElement = null; if (document.querySelector('#' + styleEleId)) { styleElement = document.querySelector('#' + styleEleId); styleElement.innerText = ''; } else { styleElement = document.createElement('style'); styleElement.id = styleEleId; htmlHead.appendChild(styleElement); } return styleElement; } getStyleSheet(styleSheetId) { const styleSheets = document.styleSheets as any; let styleSheet = null; for (const stylesheet of styleSheets) { if ((stylesheet.ownerNode || stylesheet['owningElement']).id === styleSheetId) { styleSheet = stylesheet; break; } } return styleSheet; } appendCssRules(rules: string[], styleSheet) { for (const rule of rules) { const ruleName = rule.slice(0, rule.indexOf('{')); const removedCssRule = this.removeCssRule(ruleName, styleSheet); if (styleSheet.addRule) { let cssText = ''; if (removedCssRule) { cssText += removedCssRule.cssText.slice(removedCssRule.cssText.indexOf('{') + 1, removedCssRule.cssText.indexOf('}')); } cssText += rule.slice(rule.indexOf('{') + 1, rule.indexOf('}')).replace(/"/g, '').replace(/,/g, ';') + ';'; styleSheet.addRule(ruleName, cssText, 0); } else { styleSheet.insertRule(rule, 0); } } } getCssRule(ruleName: string, styleSheet) { const cssRules = (styleSheet.cssRules || styleSheet.rules) as any; let r = null; for (const rule of cssRules) { if (rule.selectorText == ruleName) { r = rule; } } return r; } removeCssRule(ruleName: string, styleSheet ) { const cssRules = (styleSheet.cssRules || styleSheet.rules) as any; let ii = 0; let cssRule: any = false; do { cssRule = cssRules[ii]; if (cssRule) { if (cssRule.selectorText.toLowerCase() == ruleName.toLowerCase()) { if (styleSheet.cssRules) { styleSheet.deleteRule(ii); } else { styleSheet.removeRule(ii); } return cssRule; } } ii++; } while (cssRule); } isNullOrUndefined(val: any) { return val === null || val === undefined; } isIE() { const uA = window.navigator.userAgent; return /msie\s|trident\/|edge\//i.test(uA) && !!('uniqueID' in document || 'documentMode' in document || ('ActiveXObject' in window) || 'MSInputMethodContext' in window); } buildSortString(sorts: any[]): string { return this.cfs.buildSortString(sorts); } buildSqlWhere(conditions: any[]): string { return this.cfs.buildSqlWhere(conditions); } getBrowserType() { const ua = navigator.userAgent.toLowerCase(); // 获取用户端信息 const info = { ie : /msie/ .test(ua) && !/opera/ .test(ua), // 匹配IE浏览器 op : /opera/ .test(ua), // 匹配Opera浏览器 sa : /version.*safari/.test(ua), // 匹配Safari浏览器 ch : /chrome/.test(ua), // 匹配Chrome浏览器 ff : /gecko/.test(ua) && !/webkit/.test(ua) // 匹配Firefox浏览器 }; return info; } getFFVer() { const ua = navigator.userAgent; const b = ua.indexOf('Firefox/'); if (b < 0) { return 0; } return parseFloat (ua.substring(b + 8, ua.lastIndexOf('\.'))); } }