1var Inline = new function() { 2 let Mode = { 3 TOKENIZE: 'TOKENIZE', 4 PAY: 'PAY', 5 REGISTER: 'REGISTER' 6 }, 7 8 me = this, 9 context = '/upp/payment/Inline', 10 options, 11 fields, 12 fieldNames, 13 masterFieldName, 14 ready, 15 merchantId, 16 formId, 17 mode, 18 paymentMethods; 19 20 function reset() { 21 options = {}; 22 fields = {}; 23 fieldNames = []; 24 ready = false; 25 formId = ''; 26 paymentMethods = null; 27 masterFieldName = null; 28 } 29 30 reset(); 31 32 function log() { 33 if (window.console && options.debug) { 34 const args = Array.prototype.slice.call(arguments).map((o) => ((typeof o === 'object') ? JSON.stringify(o) : o)); 35 args.splice(1, 0, 'color: blue'); 36 args[0] = `%c${args[0]}`; 37 console.log.apply(console, args); 38 } 39 } 40 41 function getFrameName(field) { 42 return `iframe-${field}`; 43 } 44 45 this.initTokenize = function(_merchantId, _fields, _options) { 46 mode = Mode.TOKENIZE; 47 init(_merchantId, _fields, _options); 48 }; 49 50 this.initPay = function(_merchantId, _fields, _options) { 51 mode = Mode.PAY; 52 init(_merchantId, _fields, _options); 53 }; 54 55 this.initRegister = function(_merchantId, _fields, _options) { 56 mode = Mode.REGISTER; 57 init(_merchantId, _fields, _options); 58 }; 59 60 /** 61 * 62 * var options = { debug: true }; 63 * 64 * Inline.initTokenize( "1000011011", { 65 * cardNumber: "cardNumberPlaceholder", 66 * cvv: "cvvPlaceholder" 67 * }, options); 68 * 69 * @param _merchantId 70 * @param _fields 71 * @param _options 72 */ 73 function init(_merchantId, _fields, _options) { 74 reset(); 75 76 merchantId = _merchantId; 77 options = _options || {}; 78 79 for (const fieldName in _fields) { 80 if (!_fields.hasOwnProperty(fieldName)) { 81 return; 82 } 83 84 let value = _fields[fieldName], 85 placeholderElementId; 86 87 if (typeof value === 'object') { 88 placeholderElementId = value.placeholderElementId; 89 } else { 90 placeholderElementId = value; 91 } 92 93 fields[fieldName] = { 94 fieldName: fieldName, 95 placeholderElementId: placeholderElementId, 96 placeholder: value.placeholder, 97 ariaLabel: value.ariaLabel, 98 inputType: value.inputType, 99 alive: false 100 }; 101 102 fieldNames.push(fieldName); 103 } 104 105 fieldNames.sort((fa, fb) => { 106 if (fa === 'cardNumber') { 107 return -1; 108 } if (fb === 'cardNumber') { 109 return 1; 110 } 111 return fa.localeCompare(fb); 112 }); 113 114 if (Object.prototype.toString.call(options.paymentMethods) === Object.prototype.toString.call([]) && 115 options.paymentMethods.length > 0) { 116 paymentMethods = options.paymentMethods.join(','); 117 } 118 119 log('Initializing iframes for merchantId %s', merchantId, fields, options); 120 121 masterFieldName = fieldNames[0]; 122 123 createIframe(fields[masterFieldName]); 124 } 125 126 function createIframe(field) { 127 const placeHolder = document.getElementById(field.placeholderElementId), 128 129 parameters = { 130 mode: mode, 131 merchantId: merchantId, 132 fieldName: field.fieldName, 133 formId: formId, 134 placeholder: field.placeholder, 135 ariaLabel: field.ariaLabel, 136 inputType: field.inputType, 137 debug: options.debug, 138 version: datatransPaymentConfig.version, 139 paymentMethods: paymentMethods, 140 fieldNames: fieldNames.join(',') 141 }, 142 143 frameName = getFrameName(field.fieldName), 144 145 attributes = { 146 id: frameName, 147 name: frameName, 148 src: `${datatransPaymentConfig.endpoint + context}/paymentField?${param(parameters)}`, 149 frameborder: '0', 150 scrolling: 'no', 151 class: frameName 152 }, 153 iframe = document.createElement('iframe');
154 Object.keys(attributes).forEach((key) => { 155 iframe.setAttribute(key, attributes[key]); 156 }); 157 iframe.setAttribute('style', 'width: 100%; height: 100%'); 158 159 while (placeHolder.hasChildNodes()) { 160 placeHolder.removeChild(placeHolder.lastChild); 161 } 162 placeHolder.appendChild(iframe); 163 164 log('Created iframe for field %s', field); 165 field.iframe = iframe[0]; 166 } 167 168 function createRemainingIframes() { 169 for (let i = 1; i < fieldNames.length; i++) { 170 createIframe(fields[fieldNames[i]]); 171 } 172 } 173 174 this.setStyle = function(p1, p2, globalSelector) { 175 const styles = (typeof p1 === 'object') ? p1 : (function() { const p = {}; p[p1] = p2; return p; }()); 176 177 for (const selector in styles) { 178 if (!styles.hasOwnProperty(selector)) { 179 continue; 180 } 181 182 var style = styles[selector], 183 selectorTokens = [], 184 regex = /(^cardNumber|^cvv|^\*|:{1,2}[\w-]([\w\-.]|\(.*\))+|\.\w+|^@media\s.*|^@font-face)/gi, 185 matched; 186 187 while (matched = regex.exec(selector)) { 188 selectorTokens.push(matched[1]); 189 } 190 191 if (selectorTokens.length > 0 && 192 (selectorTokens[0].indexOf('@media') === 0 || selectorTokens[0].indexOf('@font-face') === 0)) { 193 this.setStyle(style, null, selectorTokens[0]); 194 continue; 195 } 196 197 const targetFieldName = selectorTokens.shift(); 198 199 for (const fieldName in fields) { 200 if (fields.hasOwnProperty(fieldName) && (targetFieldName === '*' || targetFieldName === fieldName)) { 201 window.frames[getFrameName(fieldName)].postMessage({ 202 messageType: 'setStyle', 203 selectors: selectorTokens, 204 style: style, 205 globalSelector: globalSelector 206 }, '*'); 207 } 208 } 209 } 210 }; 211 212 this.setPlaceholder = function(fieldName, placeholder) { 213 if (fields.hasOwnProperty(fieldName)) { 214 window.frames[getFrameName(fieldName)].postMessage({ 215 messageType: 'setPlaceholder', 216 placeholder: placeholder 217 }, '*'); 218 } 219 }; 220 221 this.setAriaLabel = function(fieldName, ariaLabel) { 222 if (fields.hasOwnProperty(fieldName)) { 223 window.frames[getFrameName(fieldName)].postMessage({ 224 messageType: 'setAriaLabel', 225 ariaLabel: ariaLabel 226 }, '*'); 227 } 228 }; 229 230 this.submit = function(parameters) { 231 log(`Sending submitRequest event ${parameters}`); 232 window.frames[getFrameName(masterFieldName)].postMessage({ 233 messageType: 'submitRequest', 234 parameters: parameters 235 }, '*'); 236 }; 237 238 this.validate = function() { 239 log('Sending validate event'); 240 window.frames[getFrameName(masterFieldName)].postMessage({ 241 messageType: 'validateRequest' 242 }, '*'); 243 }; 244 245 this.focus = function(field) { 246 window.frames[getFrameName(field)].focus(); 247 }; 248 249 function receiveMessage(event) { 250 log('receiveMessage \torigin: %s\n\tdata: %s', event.origin, event.data); 251 252 if (datatransPaymentConfig.endpoint !== event.origin) { 253 log('message ignored. origin should be: %s', datatransPaymentConfig.endpoint); 254 return; 255 } 256 257 const handlers = { 258 fieldReady: function(data) { 259 fields[data.fieldName].alive = true; 260 261 if (data.fieldName === masterFieldName) { 262 formId = data.formId; 263 createRemainingIframes(); 264 } 265 266 checkReadiness(); 267 }, 268 initResponse: function(data) { 269 emit('error', data.error); 270 }, 271 submitResponse: function(data) { 272 emit('success', data.response); 273 }, 274 validateResponse: function(data) { 275 emit('validate', data.response); 276 }, 277 change: function(data) { 278 emit('change', data.response); 279 } 280 }, 281 282 handler = handlers[event.data.messageType]; 283 284 if (handler) { 285 handler.apply(Inline, [event.data]); 286 } 287 } 288 289 window.addEventListener('message', receiveMessage, false); 290 291 /// /////////////////////////////////////// 292 function checkReadiness() { 293 ready = Object.keys(fields).map((key, index) => fields[key].alive) 294 .reduce((a, b) => a && b, true); 295 296 if (ready) { 297 log('All iframes are ready. Sending ready event.'); 298 if (typeof options.styles !== 'undefined') { 299 me.setStyle(options.styles); 300 } 301 if (typeof options.focus !== 'undefined') { 302 me.focus(options.focus); 303 } 304 emit('ready'); 305 306 initFocusHack(); 307 } 308 } 309 310 function initFocusHack() { 311 document.addEventListener('touchend', checkFocus, true); 312 313 function checkFocus(event) { 314 Object.keys(fields).map((fieldName) => { 315 const frame = window.frames[getFrameName(fieldName)]; 316 if (typeof frame !== 'undefined') { 317 frame.postMessage({ 318 messageType: 'checkFocus' 319 }, '*'); 320 } 321 }); 322 } 323 } 324 325 /// /////////////////////////////////////// 326 const handlers = {}; 327 328 this.on = function(event, handler) { 329 handlers[event] = handler; 330 }; 331 332 emit = function() { 333 const args = Array.prototype.slice.call(arguments), 334 handler = handlers[args.shift()]; 335 if (handler) {
336 handler.apply(null, args); 337 } 338 }; 339 /// /////////////////////////////////////// 340 341 function param(parameters) { 342 return encodeURI(Object.keys(parameters).map((key) => { 343 const value = parameters[key]; 344 return (typeof value !== 'undefined' && value !== null) 345 ? (`${key}=${value}`) : ''; 346 }).join('&')); 347 } 348 }(), 349 350 datatransDomElement = document.getElementById('datatrans-container'), 351 352 hasToLoadDatatransTest = datatransDomElement 353 ? datatransDomElement.dataset.pciTestActive.toLowerCase() === 'true' 354 : false, 355 356 datatransPaymentConfig = { 357 endpoint: hasToLoadDatatransTest ? 'https://pay.sandbox.datatrans.com' : 'https://pay.datatrans.com', 358 version: '1.0.0' 359 };
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.