'use strict'; function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } /* *+------------------------------------------------------------------------+ *| Licensed Materials - Property of IBM *| IBM Cognos Products: Dashboard *| (C) Copyright IBM Corp. 2017, 2020 *| *| US Government Users Restricted Rights - Use, duplication or disclosure *| restricted by GSA ADP Schedule Contract with IBM Corp. *+------------------------------------------------------------------------+ */ define(['jquery', 'underscore', '../../lib/@waca/core-client/js/core-client/utils/UniqueId', '../../app/nls/StringResources'], function ($, _, UniqueId, StringResources) { var PropertiesUtil = function () { function PropertiesUtil() { _classCallCheck(this, PropertiesUtil); } /** * Loops through an array of properties to add appropriate callbacks and default values * @param {object} properties - the array of properties to process * @param {ContentAPI} contentApi - content which wants to display these properties * @return {Promise} resolved once all the properties have been processed */ PropertiesUtil.prototype.processProperties = function processProperties(properties, contentApi, dashboardApi) { var _this = this; if (!properties) { return false; } var translationService = dashboardApi.getDashboardCoreSvc('TranslationService'); var removeTranslationIcon = function removeTranslationIcon(property) { // if the property has a tanslationIconNode defined then we were showing the missing translation dot. // Since we're just changed the property make sure the dot gets removed. if (translationService && property.translationIconNode) { translationService.removeTranslationIcon(property.translationIconNode); property.translationIconNode = null; } }; var onChangeCallback = function onChangeCallback(property, propertyName, propertyValue) { if (property.displayMultiplier) { propertyValue = Math.round(propertyValue / property.displayMultiplier); } this._callPropertyOnChangeCallback(property, propertyName, propertyValue); contentApi.setPropertyValue(propertyName, propertyValue); removeTranslationIcon(property); }; var promises = []; var removedItems = 0; properties.slice().forEach(function (property, i) { var customOnChangeCallback = typeof property['onChange'] === 'function' ? property.onChange.bind(property) : null; // Ignore hidden properties or the banner if (property.public === false || property.type === 'Banner') { return; } var propertiesOverride = _this._getPropertiesOverride(property, contentApi); if (propertiesOverride.removeProperty === true) { properties.splice(i - removedItems, 1); removedItems++; return; } // Replace any overriden properties $.extend(property, propertiesOverride); // Property UI Controls always need a name property if (property.id && !property.name) { property.name = property.id; } // list of container types. Each section (ie. left, right) of a split has no type (undefined) var containerCtrlTypes = ['Group', 'CollapsibleSection', 'SingleLineLinks', 'Split', undefined]; // list of static placeholders var staticCtrlTypes = ['text', 'icon', 'Separator', 'SectionLabel']; if (!_this._isValidPropertyId(property.id) && containerCtrlTypes.indexOf(property.type) > -1) { // id with spaces doesn't work in core-client/CollapsibleSection.js // remove all special characters and generate a unique id var prefix = property.id.replace(/[^a-zA-Z]/g, ''); property.id = UniqueId.get(prefix); property.name = property.id; } // child properties if (property.type === 'ColorPicker' && property.paletteType) { promises.push(_this.handleColorPickerProperty(property, contentApi, dashboardApi)); } else if (property.type === 'NewPalette' || property.type === 'Palette') { property.type = 'NewPalette'; promises.push(_this.handleNewPaletteProperty(property, contentApi, dashboardApi)); } else if (property.type === 'ToggledCombo') { _this._handleToggledComboProperty(property, contentApi); } else if (property.type === 'IconPicker') { _this._handleIconPickerProperty(property, contentApi); } else if (property.module && property.module.indexOf('UiSlider') >= 0) { _this._handleUISlider(property, contentApi); } else if (property.name === 'pageSizeWidth' || property.name === 'pageSizeHeight') { _this._getPropertyDisplayValueWithUnits(contentApi, property); } else if (containerCtrlTypes.indexOf(property.type) > -1) { promises.push(_this.processProperties(property.items, contentApi, dashboardApi)); } else if (_this._isALayoutPositionProperty(property.name)) { _this._handleLayoutPositionalProperty(contentApi, property); } else if (property.id === 'rotateAngle') { var currentPropValue = contentApi.getPropertyValue(property.id); property.value = _this.getRotateDisplayString(currentPropValue); } else if (staticCtrlTypes.indexOf(property.type) < 0) { var _currentPropValue = contentApi.getPropertyValue(property.id); if (_currentPropValue === null || _currentPropValue === undefined) { _currentPropValue = property.value; } if (property.type === 'CheckBox' || property.type === 'ToggleButton') { if (_currentPropValue === false) { property.checked = false; } else { property.checked = _currentPropValue === true || property.defaultValue === true || _currentPropValue && _currentPropValue === property.defaultValue; } } else { if (property.type === 'DropDown') { var valueToUse = void 0; /* * Enums - Dropdowns, are difficult because of Vida. Basically, we want * to check if the the current value returned is a valid. If it isn't, * use the property default. If it is, then we should check if it is an * object with property called 'name', which Vida enums do. If it does, * then use the name prop. All else fails, use the current prop value. */ if (_currentPropValue !== null && _currentPropValue !== undefined) { if (_currentPropValue.hasOwnProperty('name')) { valueToUse = _currentPropValue.name; } else { valueToUse = _currentPropValue; } } else { valueToUse = property.defaultValue; } property.defaultValue = valueToUse; } else { property.value = _currentPropValue || _currentPropValue === 0 ? _currentPropValue : ''; } } if (property.displayMultiplier && property.value) { var scaledValue = property.value * property.displayMultiplier; property.value = property.decimalPlaces ? scaledValue.toFixed(property.decimalPlaces) : Math.round(scaledValue); } property.onChange = property.onChange || onChangeCallback.bind(_this, property); } if (customOnChangeCallback) { property.onChange = function (property, propertyName, propertyValue, options) { customOnChangeCallback(propertyName, propertyValue, options); removeTranslationIcon(property); }.bind(_this, property); } // Replace any overriden properties once again in case we set defaults $.extend(property, propertiesOverride); }); return Promise.all(promises); }; /** * Identifies if property name is top, left, width or height * @param {String} property - the property name to be searched * @return {boolean} - returns true or false based on property name */ PropertiesUtil.prototype._isALayoutPositionProperty = function _isALayoutPositionProperty(propertyName) { var positionNames = ['left', 'top', 'width', 'height']; return positionNames.indexOf(propertyName) !== -1; }; /** * If the property object defines a 'preRenderCallback' property then call it to get any dynamic properties * that should be applied to the property UI control * @param {object} property - the property object for which to get any dynamically generated member variables * @param {object} contentApi - the widget instance which wants to display these properties * * @return {object} - returns the member variables (properties) to override */ PropertiesUtil.prototype._getPropertiesOverride = function _getPropertiesOverride(property, contentApi) { var propertiesOverride = {}; // Call the callback to get any dynamic property info if (typeof property['preRenderCallback'] === 'function') { propertiesOverride = property.preRenderCallback(property, contentApi); } return propertiesOverride; }; /** * A property can define a custom onChange callback. This is mostly used when one property change effects other properties, * for example the show/hide legend property to hide/show the legened position property. * @param {object} property - the property object for which to get any dynamically generated member variables * @param {string} propertyName - the name of the property * @param {object} propertyValue - the value of the property */ PropertiesUtil.prototype._callPropertyOnChangeCallback = function _callPropertyOnChangeCallback(property, propertyName, propertyValue) { if (property.onChangeCallback) { property.onChangeCallback(propertyName, propertyValue); } }; /** * Handles setting the callbacks and dynamic properties of a slider property control * @param {object} property - the property object for which to get any dynamically generated member variables * @param {object} contentApi - the widget instance which wants to display these properties */ PropertiesUtil.prototype._handleUISlider = function _handleUISlider(property, contentApi) { var currentPropValue = contentApi.getPropertyValue(property.name); if (currentPropValue || currentPropValue === 0 && property.sliderType === 'percentage') { currentPropValue = parseInt(currentPropValue * 100, 10); } property.start = currentPropValue || currentPropValue === 0 ? [currentPropValue] : [property.defaultValue]; property.startLabels = [property.description || property.label]; property.onChange = function (sliderValues) { // All our sliders currently only have one 'slide' var value = sliderValues[0]; // The value with have the postfix at the end, for example 75% if (property.format && property.format.postfix) { value = value.substring(0, value.indexOf(property.format.postfix)); } if (property.sliderType === 'percentage') { value = value * 0.01; } this._callPropertyOnChangeCallback(property, property.name, value); contentApi.setPropertyValue(property.name, value); }.bind(this); }; /** * Handles setting the callbacks and dynamic properties of a toggleCombo (auto refresh) property * @param {object} property - the property object for which to get any dynamically generated member variables * @param {object} contentApi - the widget instance which wants to display these properties */ PropertiesUtil.prototype._handleToggledComboProperty = function _handleToggledComboProperty(property, contentApi) { var propInfo = contentApi.getPropertyValue(property.name); if (!property.inputOptions) { property.inputOptions = {}; } if (!property.checkBoxOptions) { property.checkBoxOptions = {}; } if (!property.dropDownOptions) { property.dropDownOptions = {}; } property.useToggleButton = true; if (propInfo) { property.dropDownOptions.defaultValue = propInfo.unit; property.inputOptions.value = propInfo.value; property.checkBoxOptions.checked = propInfo.autoRefresh; } else { property.inputOptions.value = property.inputOptions.defaultValue || ''; property.checkBoxOptions.checked = false; } property.validateInput = this._validateToggleComboProperty.bind(this); property.onChange = function (propertyName, propertyValue) { this._callPropertyOnChangeCallback(property, propertyName, propertyValue); contentApi.setPropertyValue(propertyName, propertyValue); }.bind(this); }; /** * Handles setting the callbacks and dynamic properties of a IconPickerproperty * @param {object} property - the property object for which to get any dynamically generated member variables * @param {object} contentApi - the widget instance which wants to display these properties */ PropertiesUtil.prototype._handleIconPickerProperty = function _handleIconPickerProperty(property, contentApi) { if (!property.values) { var currentPropValue = contentApi.getPropertyValue(property.name); if (currentPropValue !== null && currentPropValue !== undefined) { property.values = currentPropValue; } else if (property.defaultValue !== undefined) { property.values = property.defaultValue; } } if (!property.onChange) { property.onChange = function (propertyName, propertyValue) { var values = propertyValue; if (propertyValue.length && propertyValue.length === 1) { values = propertyValue[0].name; } else if (propertyValue.length) { values = []; propertyValue.forEach(function (value) { values.push(value.name); }); } this._callPropertyOnChangeCallback(property, propertyName, values); contentApi.setPropertyValue(propertyName, values); }.bind(this); } }; /** * @param timeUnit - 'seconds', 'minutes', 'hours' * @returns a structure stating the min and max of the specified timeUnit */ PropertiesUtil.prototype._getMaxMinRefreshValuesForUnits = function _getMaxMinRefreshValuesForUnits(timeUnit) { /** * The browser method used to provide a timed delay between refresh calls has * a max size of a signed integer. We must ensure we stay below this number * depending on the time unit */ var maxIntervalInSeconds = (Math.pow(2, 31) - 1) / 1000; var maxForTimeUnit = void 0; var values = {}; switch (timeUnit) { case 'minutes': values.min = 1; maxForTimeUnit = maxIntervalInSeconds / 60; values.max = Math.ceil(maxForTimeUnit - 1); break; case 'hours': values.min = 1; maxForTimeUnit = maxIntervalInSeconds / 3600; values.max = Math.ceil(maxForTimeUnit - 1); break; default: // includes seconds values.min = 5; values.max = Math.ceil(maxIntervalInSeconds - 1); } return values; }; /** * Called when the toggleCombo (auto refresh) property changes * @param {string} valueOfInput * @param {string} valueOfDropDown */ PropertiesUtil.prototype._validateToggleComboProperty = function _validateToggleComboProperty(valueOfInput, valueOfDropDown) { if (!valueOfInput || !valueOfDropDown) { return false; } var isValid = $.isNumeric(valueOfInput); if (isValid) { var maxMinValuesForUnit = this._getMaxMinRefreshValuesForUnits(valueOfDropDown); // ensure the valueOfInput is between our current min and max. isValid = valueOfInput >= maxMinValuesForUnit.min && valueOfInput <= maxMinValuesForUnit.max; } return isValid; }; /** * Handles setting the callbacks and dynamic properties of a Palette property * @param {object} property - the property object for which to get any dynamically generated member variables * @param {object} contentApi - the widget instance which wants to display these properties * @param {object} dashboardApi * @param {function} [onChangeCallback] - optional to override the default onchange behavior */ PropertiesUtil.prototype.handleNewPaletteProperty = function handleNewPaletteProperty(property, contentApi, dashboardApi, onChangeCallback) { var _this2 = this; if (!property.paletteType) { throw new Error('Palette property needs a "paletteType"', property); } var colorsService = dashboardApi.getFeature('Colors'); var getPaletteId = property.getPaletteId ? property.getPaletteId : function () { var paletteId = contentApi.getPropertyValue(property.name); paletteId = paletteId || property.defaultValue || colorsService.getDefaultPaletteName(property.paletteType); return paletteId; }; var paletteId = getPaletteId(); var allowPaletteReverse = property.allowPaletteReverse !== false && (property.paletteType === 'HeatPalette' || property.paletteType === 'ConditionalPalette'); var createPaletteType = property.paletteType === 'HeatPalette' ? 'continuous' : 'standard'; var isReverse = property.isReversed ? property.isReversed : function () { var currentOrder = property.reversePalettePropName && contentApi.getPropertyValue(property.reversePalettePropName); return currentOrder === 'DarkerForLowerValue' && allowPaletteReverse; }; property.menuItems = []; if (allowPaletteReverse) { property.menuItems.push('reverse'); } property.reverse = isReverse(); property.createPaletteType = createPaletteType; return colorsService.getPalette({ paletteId: paletteId, type: property.paletteType, defaultPaletteId: property.defaultValue, addMissingBaseColors: property.addMissingBaseColors, defaultIfNotFound: true, forProperties: true }).then(function (selPalette) { property.palette = selPalette; property.hasSection = true; property.readOnly = true; if (selPalette.my && !selPalette.public) { property.menuItems.push('edit'); } if (!property.onChangePalette) { property.onChangePalette = onChangeCallback ? onChangeCallback : function (propertyName, paletteItem) { _this2._callPropertyOnChangeCallback(property, propertyName, paletteItem.id); contentApi.setPropertyValue(propertyName, paletteItem.id); }; } // Handle selection when creating a palette var onCreatePalette = function onCreatePalette(paletteId) { var prefixCMId = '__CM__'; var cmId = prefixCMId + paletteId; property.onChangePalette(property.name, { id: cmId }); return cmId; }; property.onCreatePalette = onCreatePalette; if (property.onReversePalette) { property.onChange = property.onReversePalette; } else { property.onChange = function (propertyName, paletteItem) { var orderValue = paletteItem.reverse === true ? 'DarkerForLowerValue' : 'DarkerForHigherValue'; _this2._callPropertyOnChangeCallback(property, property.reversePalettePropName, orderValue); contentApi.setPropertyValue(property.reversePalettePropName, orderValue); }; } property.changePaletteCb = function () { dashboardApi.getDashboardSvc('propertiesManager').then(function (propertyManager) { var options = { label: property.linkLabel, overlay: true, width: '320px', content: { module: 'authoring-common/changePaletteView', selectedId: paletteId, onCreatePalette: onCreatePalette, createPaletteType: createPaletteType, name: property.name, getPalettes: function getPalettes() { return colorsService.getPalettes({ type: property.paletteType, includeUserColorPalette: property.includeUserColorPalette, forProperties: true, includePatternPalettes: property.includePatternPalettes }); }, getPaletteId: property.getPaletteId ? property.getPaletteId : contentApi.getPropertyValue.bind(contentApi, property.id), reverse: isReverse(), onChange: property.onChangePalette, component: 'dashboard' } }; dashboardApi.prepareGlassOptions(options); propertyManager.addChild(options); }); }; return property; }); }; /** * Builds the payload needed for the property change event * @param {string} propName - the name of the property changing * @param {object} propValue - the new value for the property */ PropertiesUtil.prototype.buildPropChangePayload = function buildPropChangePayload(propName, propValue) { return { 'category': propName, 'item': propValue, 'transactionId': _.uniqueId('prop_change') }; }; /** * Add the ability to a color picker to handle custom colors * @param {object} property - Property object * @param {object} colorsService - ref to the color service */ PropertiesUtil.prototype.addCustomColorCapability = function addCustomColorCapability(property, colorsService) { property.createCustomColor = function (hex) { var className = colorsService.addCustomColor(hex); var colorProp = colorsService.createColorDefinition(className, hex, hex); colorProp.type = 'ColorCode'; colorProp.hidden = true; return colorProp; }; if (colorsService.isCustomColor(property.selectedName) && property.items) { var hex = colorsService.getHexColorFromClassName(property.selectedName); var colorProp = colorsService.createColorDefinition(property.selectedName, hex, hex); colorProp.hidden = true; property.items.push(colorProp); } return property; }; /** * Checks to see if the palette property is set in the model, if it isn't will return the default palette name for the type * of palette being asked for * @param {object} contentApi - the widget instance which wants to display these properties * @param {object} dashboardApi * @param {string} palettePropertyName - the name of the property which contains the palette name * @param {string} paletteType - the type of palette being asked for */ PropertiesUtil.prototype._getColorPalettePropertyValue = function _getColorPalettePropertyValue(contentApi, colorsService, palettePropertyName, paletteType) { var propertyValue = contentApi.getPropertyValue(palettePropertyName); return propertyValue || colorsService.getDefaultPaletteName(paletteType); }; /** * Handles setting the callbacks and dynamic properties of a ColorPicker property * @param {object} property - the property object for which to get any dynamically generated member variables * @param {object} contentApi - the widget instance which wants to display these properties * @param {object} dashboardApi */ PropertiesUtil.prototype.handleColorPickerProperty = function handleColorPickerProperty(property, contentApi, dashboardApi) { var _this3 = this; if (!property.paletteType) { throw new Error('Color picker property needs a "paletteType"', property); } var colorsService = dashboardApi.getFeature('Colors'); property.onChange = function (propertyName, propertyValueInfo) { this._callPropertyOnChangeCallback(property, property.propertyName, propertyValueInfo.name); contentApi.setPropertyValue(propertyName, propertyValueInfo.name); }.bind(this); var currentValue = contentApi.getPropertyValue(property.name); if (!property.selectedName) { // when current value is 0, it should keep it property.selectedName = !currentValue && currentValue !== 0 && property.defaultValue ? property.defaultValue : currentValue; } return this._getColorPickerColors(property, contentApi, dashboardApi).then(function (colors) { // If the colors being show are based off another property, then we need to tweak to payload for backwards compatibility if (property.palettePropertyName) { property.items = []; colors.forEach(function (color, index) { property.items.push({ 'id': index, 'name': index, 'value': color.hexValue, 'type': 'ColorCode', 'label': color.label }); }); } else if (!property.items) { property.items = colors; } // if (property.addButton) { property = _this3.addCustomColorCapability(property, colorsService); } // If the current value saved in the model is higher then the number of colors available, default // back to the first color if (property.selectedName > colors.length) { property.selectedName = 0; } else if (!property.selectedName && property.selectedName !== 0 && property.defaultColorIndex !== undefined) { // when selectedName value is 0, it should keep it property.selectedName = property.defaultColorIndex; } return property; }); }; PropertiesUtil.prototype._getColorPickerColors = function _getColorPickerColors(property, contentApi, dashboardApi) { var colorsService = dashboardApi.getFeature('Colors'); if (property.paletteType === 'DashboardColorSet') { return Promise.resolve(colorsService.getDashboardColorSet().slice(0)); } var paletteId = property.palettePropertyName ? this._getColorPalettePropertyValue(contentApi, colorsService, property.palettePropertyName, property.paletteType) : colorsService.getColorSetId(); return colorsService.getPaletteColors({ paletteId: paletteId, type: property.paletteType, addMissingBaseColors: property.addMissingBaseColors }).then(function (colors) { return colors.slice(0); }); }; /** * Currently only being called by the custom widget since it doesn't use contributions like our other widgets. * Returns the default properties to show on the general property tab. */ PropertiesUtil.prototype.getGeneralProperties = function getGeneralProperties(contentApi, dashboardApi) { var properties = [{ 'id': 'fillColor', 'type': 'ColorPicker', 'label': StringResources.get('propFillColor'), 'showHexValue': true, 'addButton': true, 'open': false, 'ariaLabel': StringResources.get('propFillColor'), 'paletteType': 'ColorPalette', 'defaultValue': 'color1', 'tabName': StringResources.get('tabName_general'), 'sectionName': StringResources.get('sectionName_appearance') }, { 'id': 'borderColor', 'type': 'ColorPicker', 'label': StringResources.get('propBorderColor'), 'open': false, 'showHexValue': true, 'addButton': true, 'ariaLabel': StringResources.get('propBorderColor'), 'paletteType': 'ColorPalette', 'defaultValue': 'transparent', 'tabName': StringResources.get('tabName_general'), 'sectionName': StringResources.get('sectionName_appearance') }]; if (contentApi) { return this.processProperties(properties, contentApi, dashboardApi).then(function () { return properties; }); } else { return Promise.resolve(properties); } }; /** * Method that takes our propertyUIControl spec and generates properties for our public API. This is temporary until * we clean up our properties logic throughout the code * @param {*} properties * @param {*} contentApi * @param {*} dashboardApi */ PropertiesUtil.prototype.propertyUIControlToPublicAPI = function propertyUIControlToPublicAPI(properties, contentApi, dashboardApi) { var _this4 = this; var propertiesList = []; var setValue = function setValue(property, value) { if (dashboardApi.getMode() !== 'authoring') { dashboardApi.getGlassCoreSvc('.Logger').error('Trying to set a property without being in authoring mode.'); return false; } if (property.customValidatorCallback) { var validInfo = property.customValidatorCallback(value); if (validInfo && validInfo.isValid === false) { dashboardApi.getGlassCoreSvc('.Logger').error(validInfo.message); return false; } } if (property.onChange) { if (property.module && property.module.indexOf('UiSlider') >= 0) { property.onChange([value]); } else if (property.type === 'ColorPicker') { var valueToSet = value && value.startsWith('#') ? dashboardApi.getFeature('Colors').addCustomColor(value) : value; property.onChange(property.name, { name: valueToSet }); } else if (property.type === 'NewPalette') { property.onChangePalette(property.name, { id: value }); } else { property.onChange(property.name, value); } return true; } }; var getValue = function getValue(property, contentApi) { var propValue = contentApi.getPropertyValue(property.name); if (propValue) { return propValue; } return property.defaultValue !== undefined ? property.defaultValue : null; }; properties.forEach(function (property) { // For now guard against not having an onChange property. This currently happens with complex property where the onChange is // buried inside of the items property. if (property.type === 'Banner' || property.public === false || !property.onChange) { return null; } // Currently only expose the minimum needed for system tests. Once this starts being used for our UI we'll // need to augment what's exposed in the API var propertyApi = { name: property.name, getValue: getValue.bind(_this4, property, contentApi), setValue: setValue.bind(_this4, property) }; propertiesList.push(propertyApi); }); return propertiesList; }; /** * Creates a string using the value and units, intended for display. Appends a space if required. All other units except 'px' get a decimal place of 2 * @param {*} numericValue The value * @param {*} units The units * @param {*} addSpace Flag indicating if a space should be added * @return {String} Returns a string, either empty or the value appended with the units */ PropertiesUtil.prototype.getPropertyDisplayString = function getPropertyDisplayString(numericValue, units, addSpace) { if (numericValue !== null && numericValue !== undefined) { if (units) { units = units.trim(); if (addSpace) { units = ' ' + units; } } return String(Number(numericValue.toFixed(units === StringResources.get('pixelUnit') ? 0 : 2))) + units; } return ''; }; /** * Gets the display value for a property * @param {*} contentApi The content API, used to retrieve the property value * @param {*} property The property */ PropertiesUtil.prototype._getPropertyDisplayValueWithUnits = function _getPropertyDisplayValueWithUnits(contentApi, property) { var currentPropValue = contentApi.getPropertyValue(property.id); property.value = this.getPropertyDisplayString(currentPropValue, StringResources.get('pixelUnit'), true); }; /** * Gets the display value for a property with space * @param {ContentAPI} contentApi The content API, used to retrieve the property value * @param {Property} property The property */ PropertiesUtil.prototype._handleLayoutPositionalProperty = function _handleLayoutPositionalProperty(contentApi, property) { var currentPropValue = contentApi.getPropertyValue(property.id); var numericValue = parseFloat(currentPropValue); property.value = this.getPropertyDisplayString(numericValue, currentPropValue.replace(/[\d.-]/g, ''), true); }; /** * Creates a string using the value, intended for display. Appends a space and units for rotation * @param {propertyValue} propertyValue propertyValue * @return {String} Returns rotate value formatted for display */ PropertiesUtil.prototype.getRotateDisplayString = function getRotateDisplayString(propertyValue) { var degreeUnit = String.fromCharCode(176); if (propertyValue !== null && propertyValue !== undefined) { return propertyValue + ' ' + degreeUnit; } return ''; }; PropertiesUtil.prototype._isValidPropertyId = function _isValidPropertyId(id) { return (/^[a-zA-Z0-9]*$/.test(id) ); }; return PropertiesUtil; }(); return new PropertiesUtil(); }); //# sourceMappingURL=PropertyListUtil.js.map