1/** 2 * JS Feature Toggle - JSFT 3 * Allows to switch off selected parts of code by JSFT.features array entries. 4 * 5 */ 6(function () { 7 /** 8 * Check if JSFT is already declared? 9 */ 10 if (typeof window.JSFT !== 'undefined' || window.hasOwnProperty('JSFT')) { 11 // if declared, we throw warning to console. 12 console.warn('JSFT module already declared. Multiple declarations are not allowed.'); 13 return; 14 } 15 // define returns 16 const FEATURE_FOUND = 1; 17 const FEATURE_NOT_FOUND = 0; 18 /** 19 * This way we keep it private and inacessible from 20 * outside as private of first self-executed function 21 * 22 * @property {array} _features - main feature array 23 * @property {object} _customerFeatures - map of feature -> array of customer IDs 24 */ 25 var _features = []; 26 var _customerFeatures = {}; 27 /** 28 * JSFT module. 29 * 30 * @namespace JSFT 31 */ 32 window.JSFT = (function () { 33 return { 34 /** 35 * @property {string} JSFT.name - module name 36 */ 37 name: 'Platfrom JS Feature toggler', 38 /** 39 * @property {object} JSFT.messages - internal error messages container 40 */ 41 messages: { 42 validation: 'invalid input type' 43 }, 44 /** 45 * Checks if provided feature is present in this.features array (toggled = ON) 46 * Returns 1 on sucess 0 on fail (this.checkFeature) 47 * 48 * @param {string} feature 49 * @returns {number} 50 */ 51 isToggled: function (feature) { 52 if (!feature) return FEATURE_NOT_FOUND; 53 if (this.validateString(feature) === 0) { 54 this.handleError('JSFT.isToggled ' + this.messages.validation); 55 } 56 return this.checkFeature(feature); 57 }, 58 /** 59 * Returns JSFT.features array 60 * 61 * @returns {[]} 62 */ 63 getFeatures: function () { 64 return _features; 65 }, 66 /** 67 * Confirms feature in features array, if exists 68 * Returns 1 on sucess 0 on fail. 69 * 70 * @param {string} feature 71 * @returns {number} 72 */ 73 checkFeature: function (feature) { 74 if (!feature) return 0; 75 if (this.validateString(feature) === 0) { 76 this.handleError('JSFT.getFeature ' + this.messages.validation); 77 } 78 function include(arr,obj) { 79 return (arr.indexOf(obj) !== -1); 80 } 81 if (include(_features, feature)) { 82 return FEATURE_FOUND; 83 } else { 84 return FEATURE_NOT_FOUND; 85 } 86 }, 87 /** 88 * Sets JSFT.features array. 89 * Validates incoming as array. 90 * Can set value only once 91 * 92 * @param {[]} features 93 * @returns {number} 94 */ 95 setFeatures: function (features) { 96 if (!features) return 0; 97 if (this.validateArrayContent(_features) === 1) { // can be set only if empty 98 this.handleError('Features array already declared'); 99 } 100 if (this.validateArray(features) === 0) { 101 return FEATURE_NOT_FOUND; 102 } 103 if (features.length === 0) { 104 return FEATURE_NOT_FOUND; 105 } 106 if (this.validateArrayContent(features) === 0) { 107 return FEATURE_NOT_FOUND; 108 } 109 _features = features; 110 return FEATURE_FOUND; 111 }, 112 /** 113 * Validates incoming as string 114 * 115 * @param {any} str 116 * @returns {number} 117 */ 118 validateString: function (str) { 119 if (!str) return 0; 120 if (typeof str !== 'string') { 121 return 0; 122 } else { 123 return 1; 124 } 125 }, 126 /** 127 * Validates incoming as array 128 * 129 * @param {any} isarray 130 * @returns {number} 131 */ 132 validateArray: function (isarray) { 133 if (!isarray) return 0; 134 if (isarray.constructor === Array) { 135 return 1; 136 } else { 137 return 0; 138 } 139 }, 140 /** 141 * Validates incoming content for strings. Rejects empty arrays 142 * Checks incoming if array 143 * 144 * @param {any} isarray 145 * @returns {number} 146 */ 147 validateArrayContent: function (isarray) { 148 if (!isarray) return 0; 149 if (this.validateArray(isarray) === 0) { 150 return 0; 151 } 152 if (isarray.length === 0) { 153 return 0; 154 } 155 // validating the array content for strings 156 for (var i = 0; i < isarray.length; i++) { 157 if (this.validateString(isarray[i]) === 0) { 158 return 0; 159 } 160 } 161 return 1; 162 }, 163 /** 164 * Sets customer-specific features. 165 * @param {object} customerFeatures - { featureName: [customerId1, customerId2, ...], ... } 166 */ 167 setCustomerFeatures: function (customerFeatures) { 168 if (typeof customerFeatures !== 'object' || customerFeatures === null) return 0; 169 _customerFeatures = customerFeatures; 170 return 1; 171 }, 172 /** 173 * Checks if a feature is toggled for a specific customer. 174 * Returns 1 if toggled, 0 otherwise. 175 * @param {string} feature 176 * @param {string|number} customerId 177 * @returns {number} 178 */ 179 isToggledForCustomer: function (feature, customerId) { 180 if (!feature || !customerId) return 0; 181 if (this.validateString(feature) === 0) { 182 this.handleError('JSFT.isToggledForCustomer ' + this.messages.val
182idation); 183 } 184 if (!_customerFeatures[feature]) return 0; 185 // Accept both string and number customerId 186 for (var i = 0; i < _customerFeatures[feature].length; i++) { 187 if (_customerFeatures[feature][i] == customerId) { 188 return 1; 189 } 190 } 191 return 0; 192 }, 193 /** 194 * Internal error handler. 195 * @param {string} msg 196 */ 197 handleError: function (msg) { 198 if (this.validateString(msg) === 0) { 199 throw new this.JSFTException('JSFT.handleError ' + this.messages.validation); 200 } 201 throw new this.JSFTException(msg); 202 }, 203 /** 204 * Custom exception 205 * @param {string} msg 206 */ 207 JSFTException: function (msg) { 208 this.status = "Failed"; 209 this.module = "window.JSFT"; 210 this.message = msg; 211 this.toString = function () { 212 return this.status + this.module + this.message; 213 }; 214 }, 215 }; 216 })(); 217})();
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.